Annotation of loncom/interface/lonuserutils.pm, revision 1.46

1.1       raeburn     1: # The LearningOnline Network with CAPA
                      2: # Utility functions for managing LON-CAPA user accounts
                      3: #
1.46    ! raeburn     4: # $Id: lonuserutils.pm,v 1.45 2008/01/06 04:27:25 raeburn Exp $
1.1       raeburn     5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#
                     23: # /home/httpd/html/adm/gpl.txt
                     24: #
                     25: # http://www.lon-capa.org/
                     26: #
                     27: #
                     28: ###############################################################
                     29: ###############################################################
                     30: 
                     31: package Apache::lonuserutils;
                     32: 
                     33: use strict;
                     34: use Apache::lonnet;
                     35: use Apache::loncommon();
                     36: use Apache::lonhtmlcommon;
                     37: use Apache::lonlocal;
1.8       raeburn    38: use Apache::longroup;
                     39: use LONCAPA qw(:DEFAULT :match);
1.1       raeburn    40: 
                     41: ###############################################################
                     42: ###############################################################
                     43: # Drop student from all sections of a course, except optional $csec
                     44: sub modifystudent {
                     45:     my ($udom,$unam,$courseid,$csec,$desiredhost)=@_;
                     46:     # if $csec is undefined, drop the student from all the courses matching
                     47:     # this one.  If $csec is defined, drop them from all other sections of
                     48:     # this course and add them to section $csec
1.17      raeburn    49:     my ($cnum,$cdom) = &get_course_identity($courseid);
1.1       raeburn    50:     my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
                     51:     my ($tmp) = keys(%roles);
                     52:     # Bail out if we were unable to get the students roles
                     53:     return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
                     54:     # Go through the roles looking for enrollment in this course
                     55:     my $result = '';
                     56:     foreach my $course (keys(%roles)) {
                     57:         if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) {
                     58:             # We are in this course
                     59:             my $section=$1;
                     60:             $section='' if ($course eq "/$cdom/$cnum".'_st');
                     61:             if (defined($csec) && $section eq $csec) {
                     62:                 $result .= 'ok:';
                     63:             } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
                     64:                 my (undef,$end,$start)=split(/\_/,$roles{$course});
                     65:                 my $now=time;
                     66:                 # if this is an active role
                     67:                 if (!($start && ($now<$start)) || !($end && ($now>$end))) {
                     68:                     my $reply=&Apache::lonnet::modifystudent
                     69:                         # dom  name  id mode pass     f     m     l     g
                     70:                         ($udom,$unam,'',  '',  '',undef,undef,undef,undef,
1.22      raeburn    71:                          $section,time,undef,undef,$desiredhost,'','manual',
                     72:                          '',$courseid);
1.1       raeburn    73:                     $result .= $reply.':';
                     74:                 }
                     75:             }
                     76:         }
                     77:     }
                     78:     if ($result eq '') {
1.37      raeburn    79:         $result = &mt('Unable to find section for this student');
1.1       raeburn    80:     } else {
                     81:         $result =~ s/(ok:)+/ok/g;
                     82:     }
                     83:     return $result;
                     84: }
                     85: 
                     86: sub modifyuserrole {
                     87:     my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass,
                     88:         $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role,
1.5       raeburn    89:         $end,$start,$checkid) = @_;
                     90:     my ($scope,$userresult,$authresult,$roleresult,$idresult);
1.1       raeburn    91:     if ($setting eq 'course' || $context eq 'course') {
                     92:         $scope = '/'.$cid;
                     93:         $scope =~ s/\_/\//g;
                     94:         if ($role ne 'cc' && $sec ne '') {
                     95:             $scope .='/'.$sec;
                     96:         }
1.5       raeburn    97:     } elsif ($context eq 'domain') {
1.1       raeburn    98:         $scope = '/'.$env{'request.role.domain'}.'/';
1.13      raeburn    99:     } elsif ($context eq 'author') {
1.1       raeburn   100:         $scope =  '/'.$env{'user.domain'}.'/'.$env{'user.name'};
                    101:     }
                    102:     if ($context eq 'domain') {
                    103:         my $uhome = &Apache::lonnet::homeserver($uname,$udom);
                    104:         if ($uhome ne 'no_host') {
1.5       raeburn   105:             if (($changeauth eq 'Yes') && (&Apache::lonnet::allowed('mau',$udom))) {
1.1       raeburn   106:                 if ((($umode =~ /^krb4|krb5|internal$/) && $upass ne '') ||
                    107:                     ($umode eq 'localauth')) {
                    108:                     $authresult = &Apache::lonnet::modifyuserauth($udom,$uname,$umode,$upass);
                    109:                 }
                    110:             }
1.5       raeburn   111:             if (($forceid) && (&Apache::lonnet::allowed('mau',$udom)) &&
                    112:                 ($env{'form.recurseid'}) && ($checkid)) {
                    113:                 my %userupdate = (
                    114:                                   lastname   => $last,
                    115:                                   middlename => $middle,
                    116:                                   firstname  => $first,
                    117:                                   generation => $gene,
                    118:                                   id         => $uid,
                    119:                                  );
                    120:                 $idresult = &propagate_id_change($uname,$udom,\%userupdate);
                    121:             }
1.1       raeburn   122:         }
                    123:     }
                    124:     $userresult =
                    125:         &Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first,
                    126:                                     $middle,$last,$gene,$forceid,$desiredhome,
                    127:                                     $email,$role,$start,$end);
                    128:     if ($userresult eq 'ok') {
1.5       raeburn   129:         if ($role ne '') {
1.22      raeburn   130:             $role =~ s/_/\//g;
1.1       raeburn   131:             $roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope,
                    132:                                                       $role,$end,$start);
                    133:         }
                    134:     }
1.5       raeburn   135:     return ($userresult,$authresult,$roleresult,$idresult);
1.1       raeburn   136: }
                    137: 
1.5       raeburn   138: sub propagate_id_change {
                    139:     my ($uname,$udom,$user) = @_;
1.12      raeburn   140:     my (@types,@roles);
1.5       raeburn   141:     @types = ('active','future');
                    142:     @roles = ('st');
                    143:     my $idresult;
                    144:     my %roleshash = &Apache::lonnet::get_my_roles($uname,
1.12      raeburn   145:                         $udom,'userroles',\@types,\@roles);
                    146:     my %args = (
                    147:                 one_time => 1,
                    148:                );
1.5       raeburn   149:     foreach my $item (keys(%roleshash)) {
1.22      raeburn   150:         my ($cnum,$cdom,$role) = split(/:/,$item,-1);
1.5       raeburn   151:         my ($start,$end) = split(/:/,$roleshash{$item});
                    152:         if (&Apache::lonnet::is_course($cdom,$cnum)) {
1.12      raeburn   153:             my $result = &update_classlist($cdom,$cnum,$udom,$uname,$user);
                    154:             my %coursehash = 
                    155:                 &Apache::lonnet::coursedescription($cdom.'_'.$cnum,\%args);
                    156:             my $cdesc = $coursehash{'description'};
                    157:             if ($cdesc eq '') { 
                    158:                 $cdesc = $cdom.'_'.$cnum;
                    159:             }
1.5       raeburn   160:             if ($result eq 'ok') {
1.12      raeburn   161:                 $idresult .= &mt('Classlist update for "[_1]" in "[_2]".',$uname.':'.$udom,$cdesc).'<br />'."\n";
1.5       raeburn   162:             } else {
1.12      raeburn   163:                 $idresult .= &mt('Error: "[_1]" during classlist update for "[_2]" in "[_3]".',$result,$uname.':'.$udom,$cdesc).'<br />'."\n";
1.5       raeburn   164:             }
                    165:         }
                    166:     }
                    167:     return $idresult;
                    168: }
                    169: 
                    170: sub update_classlist {
                    171:     my ($cdom,$cnum,$udom,$uname,$user) = @_;
1.6       albertel  172:     my ($uid,$classlistentry);
1.5       raeburn   173:     my $fullname =
                    174:         &Apache::lonnet::format_name($user->{'firstname'},$user->{'middlename'},
                    175:                                      $user->{'lastname'},$user->{'generation'},
                    176:                                      'lastname');
                    177:     my %classhash = &Apache::lonnet::get('classlist',[$uname.':'.$udom],
                    178:                                          $cdom,$cnum);
                    179:     my @classinfo = split(/:/,$classhash{$uname.':'.$udom});
                    180:     my $ididx=&Apache::loncoursedata::CL_ID() - 2;
                    181:     my $nameidx=&Apache::loncoursedata::CL_FULLNAME() - 2;
                    182:     for (my $i=0; $i<@classinfo; $i++) {
                    183:         if ($i == $ididx) {
                    184:             if (defined($user->{'id'})) {
                    185:                 $classlistentry .= $user->{'id'}.':';
                    186:             } else {
                    187:                 $classlistentry .= $classinfo[$i].':';
                    188:             }
                    189:         } elsif ($i == $nameidx) {
                    190:             $classlistentry .= $fullname.':';
                    191:         } else {
                    192:             $classlistentry .= $classinfo[$i].':';
                    193:         }
                    194:     }
                    195:     $classlistentry =~ s/:$//;
                    196:     my $reply=&Apache::lonnet::cput('classlist',
                    197:                                     {"$uname:$udom" => $classlistentry},
                    198:                                     $cdom,$cnum);
                    199:     if (($reply eq 'ok') || ($reply eq 'delayed')) {
                    200:         return 'ok';
                    201:     } else {
                    202:         return 'error: '.$reply;
                    203:     }
                    204: }
                    205: 
                    206: 
1.1       raeburn   207: ###############################################################
                    208: ###############################################################
1.2       raeburn   209: # build a role type and role selection form
                    210: sub domain_roles_select {
                    211:     # Set up the role type and role selection boxes when in 
                    212:     # domain context   
                    213:     #
                    214:     # Role types
1.13      raeburn   215:     my @roletypes = ('domain','author','course');
1.2       raeburn   216:     my %lt = &role_type_names();
1.1       raeburn   217:     #
                    218:     # build up the menu information to be passed to
                    219:     # &Apache::loncommon::linked_select_forms
                    220:     my %select_menus;
1.2       raeburn   221:     if ($env{'form.roletype'} eq '') {
                    222:         $env{'form.roletype'} = 'domain';
                    223:     }
                    224:     foreach my $roletype (@roletypes) {
1.1       raeburn   225:         # set up the text for this domain
1.2       raeburn   226:         $select_menus{$roletype}->{'text'}= $lt{$roletype};
1.1       raeburn   227:         # we want a choice of 'default' as the default in the second menu
1.2       raeburn   228:         if ($env{'form.roletype'} ne '') {
                    229:             $select_menus{$roletype}->{'default'} = $env{'form.showrole'};
                    230:         } else { 
                    231:             $select_menus{$roletype}->{'default'} = 'Any';
                    232:         }
1.1       raeburn   233:         # Now build up the other items in the second menu
1.2       raeburn   234:         my @roles;
                    235:         if ($roletype eq 'domain') {
                    236:             @roles = &domain_roles();
1.13      raeburn   237:         } elsif ($roletype eq 'author') {
1.2       raeburn   238:             @roles = &construction_space_roles();
                    239:         } else {
1.17      raeburn   240:             my $custom = 1;
                    241:             @roles = &course_roles('domain',undef,$custom);
1.1       raeburn   242:         }
1.2       raeburn   243:         my $order = ['Any',@roles];
                    244:         $select_menus{$roletype}->{'order'} = $order; 
                    245:         foreach my $role (@roles) {
1.5       raeburn   246:             if ($role eq 'cr') {
                    247:                 $select_menus{$roletype}->{'select2'}->{$role} =
                    248:                               &mt('Custom role');
                    249:             } else {
                    250:                 $select_menus{$roletype}->{'select2'}->{$role} = 
                    251:                               &Apache::lonnet::plaintext($role);
                    252:             }
1.2       raeburn   253:         }
                    254:         $select_menus{$roletype}->{'select2'}->{'Any'} = &mt('Any');
1.1       raeburn   255:     }
1.2       raeburn   256:     my $result = &Apache::loncommon::linked_select_forms
                    257:         ('studentform',('&nbsp;'x3).&mt('Role: '),$env{'form.roletype'},
1.13      raeburn   258:          'roletype','showrole',\%select_menus,['domain','author','course']);
1.1       raeburn   259:     return $result;
                    260: }
                    261: 
                    262: ###############################################################
                    263: ###############################################################
                    264: sub hidden_input {
                    265:     my ($name,$value) = @_;
                    266:     return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
                    267: }
                    268: 
                    269: sub print_upload_manager_header {
1.22      raeburn   270:     my ($r,$datatoken,$distotal,$krbdefdom,$context,$permission)=@_;
1.1       raeburn   271:     my $javascript;
                    272:     #
                    273:     if (! exists($env{'form.upfile_associate'})) {
                    274:         $env{'form.upfile_associate'} = 'forward';
                    275:     }
                    276:     if ($env{'form.associate'} eq 'Reverse Association') {
                    277:         if ( $env{'form.upfile_associate'} ne 'reverse' ) {
                    278:             $env{'form.upfile_associate'} = 'reverse';
                    279:         } else {
                    280:             $env{'form.upfile_associate'} = 'forward';
                    281:         }
                    282:     }
                    283:     if ($env{'form.upfile_associate'} eq 'reverse') {
                    284:         $javascript=&upload_manager_javascript_reverse_associate();
                    285:     } else {
                    286:         $javascript=&upload_manager_javascript_forward_associate();
                    287:     }
                    288:     #
                    289:     # Deal with restored settings
                    290:     my $password_choice = '';
                    291:     if (exists($env{'form.ipwd_choice'}) &&
                    292:         $env{'form.ipwd_choice'} ne '') {
                    293:         # If a column was specified for password, assume it is for an
                    294:         # internal password.  This is a bug waiting to be filed (could be
                    295:         # local or krb auth instead of internal) but I do not have the
                    296:         # time to mess around with this now.
                    297:         $password_choice = 'int';
                    298:     }
                    299:     #
1.22      raeburn   300:     my $groupslist;
                    301:     if ($context eq 'course') {
                    302:         $groupslist = &get_groupslist();
                    303:     }
1.1       raeburn   304:     my $javascript_validations =
1.22      raeburn   305:         &javascript_validations('upload',$krbdefdom,$password_choice,undef,
                    306:                                 $env{'request.role.domain'},$context,
1.33      raeburn   307:                                 $groupslist);
1.1       raeburn   308:     my $checked=(($env{'form.noFirstLine'})?' checked="checked" ':'');
                    309:     $r->print(&mt('Total number of records found in file: <b>[_1]</b>.',$distotal).
                    310:               "<br />\n");
                    311:     $r->print('<div class="LC_left_float"><h3>'.
                    312:               &mt('Identify fields in uploaded list')."</h3>\n");
                    313:     $r->print(&mt('Enter as many fields as you can.<br /> The system will inform you and bring you back to this page, <br /> if the data selected are insufficient to add users.')."<br />\n");
                    314:     $r->print(&hidden_input('action','upload').
                    315:               &hidden_input('state','got_file').
                    316:               &hidden_input('associate','').
                    317:               &hidden_input('datatoken',$datatoken).
                    318:               &hidden_input('fileupload',$env{'form.fileupload'}).
                    319:               &hidden_input('upfiletype',$env{'form.upfiletype'}).
                    320:               &hidden_input('upfile_associate',$env{'form.upfile_associate'}));
                    321:     $r->print('<br /><input type="button" value="Reverse Association" '.
                    322:               'name="'.&mt('Reverse Association').'" '.
                    323:               'onClick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />');
                    324:     $r->print('<label><input type="checkbox" name="noFirstLine"'.$checked.'/>'.
                    325:               &mt('Ignore First Line').'</label>');
                    326:     $r->print("<br /><br />\n".
                    327:               '<script type="text/javascript" language="Javascript">'."\n".
                    328:               $javascript."\n".$javascript_validations.'</script>');
                    329: }
                    330: 
                    331: ###############################################################
                    332: ###############################################################
                    333: sub javascript_validations {
1.22      raeburn   334:     my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain,
1.33      raeburn   335:         $context,$groupslist)=@_;
1.22      raeburn   336:     my %param = (
                    337:                   kerb_def_dom => $krbdefdom,
                    338:                   curr_authtype => $curr_authtype,
                    339:                 );
1.37      raeburn   340:     if ($mode eq 'upload') {
1.22      raeburn   341:         $param{'formname'} = 'studentform';
1.1       raeburn   342:     } elsif ($mode eq 'createcourse') {
1.22      raeburn   343:         $param{'formname'} = 'ccrs';
1.1       raeburn   344:     } elsif ($mode eq 'modifycourse') {
1.22      raeburn   345:         $param{'formname'} = 'cmod';
                    346:         $param{'mode'} = 'modifycourse',
                    347:         $param{'curr_autharg'} = $curr_authfield;
                    348:     }
                    349: 
                    350:     my ($setsection_call,$setsections_js);
                    351:     my $finish = "  vf.submit();\n";
                    352:     if ($mode eq 'upload') {
                    353:         if (($context eq 'course') || ($context eq 'domain')) {
                    354:             if ($context eq 'course') {
                    355:                 if ($env{'request.course.sec'} eq '') {
                    356:                     $setsection_call = 'setSections(document.'.$param{'formname'}.');';
                    357:                     $setsections_js =
                    358:                         &setsections_javascript($param{'formname'},$groupslist,
                    359:                                                 $mode);
                    360:                 } else {
                    361:                     $setsection_call = "'ok'";
                    362:                 }
                    363:             } elsif ($context eq 'domain') {
                    364:                 $setsection_call = 'setCourse()';
1.37      raeburn   365:                 $setsections_js = &dc_setcourse_js($param{'formname'},$mode,$context);
1.22      raeburn   366:             }
                    367:             $finish = "  var checkSec = $setsection_call\n".
                    368:                       "  if (checkSec == 'ok') {\n".
                    369:                       "      vf.submit();\n".
                    370:                       "   }\n";
                    371:         }
1.1       raeburn   372:     }
1.22      raeburn   373:     my $authheader = &Apache::loncommon::authform_header(%param);
1.1       raeburn   374: 
                    375:     my %alert = &Apache::lonlocal::texthash
                    376:         (username => 'You need to specify the username field.',
                    377:          authen   => 'You must choose an authentication type.',
                    378:          krb      => 'You need to specify the Kerberos domain.',
                    379:          ipass    => 'You need to specify the initial password.',
                    380:          name     => 'The optional name field was not specified.',
                    381:          snum     => 'The optional ID number field was not specified.',
                    382:          section  => 'The optional section field was not specified.',
                    383:          email    => 'The optional email address field was not specified.',
                    384:          role     => 'The optional role field was not specified.',
                    385:          continue => 'Continue adding users?',
                    386:          );
1.37      raeburn   387:     my $function_name = <<"END";
1.22      raeburn   388: $setsections_js
                    389: 
1.1       raeburn   390: function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail) {
                    391: END
                    392:     my ($authnum,%can_assign) =  &Apache::loncommon::get_assignable_auth($domain);
                    393:     my $auth_checks;
                    394:     if ($mode eq 'createcourse') {
                    395:         $auth_checks .= (<<END);
                    396:     if (vf.autoadds[0].checked == true) {
                    397:         if (current.radiovalue == null || current.radiovalue == 'nochange') {
                    398:             alert('$alert{'authen'}');
                    399:             return;
                    400:         }
                    401:     }
                    402: END
                    403:     } else {
                    404:         $auth_checks .= (<<END);
                    405:     var foundatype=0;
                    406:     if (founduname==0) {
                    407:         alert('$alert{'username'}');
                    408:         return;
                    409:     }
                    410: 
                    411: END
                    412:         if ($authnum > 1) {
                    413:             $auth_checks .= (<<END);
                    414:     if (current.radiovalue == null || current.radiovalue == '' || current.radiovalue == 'nochange') {
                    415:         // They did not check any of the login radiobuttons.
                    416:         alert('$alert{'authen'}');
                    417:         return;
                    418:     }
                    419: END
                    420:         }
                    421:     }
                    422:     if ($mode eq 'createcourse') {
                    423:         $auth_checks .= "
                    424:     if ( (vf.autoadds[0].checked == true) &&
                    425:          (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') ) {
                    426: ";
                    427:     } elsif ($mode eq 'modifycourse') {
                    428:         $auth_checks .= "
                    429:     if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') {
                    430: ";
                    431:     }
                    432:     if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
                    433:         $auth_checks .= (<<END);
                    434:         var alertmsg = '';
                    435:         switch (current.radiovalue) {
                    436:             case 'krb':
                    437:                 alertmsg = '$alert{'krb'}';
                    438:                 break;
                    439:             default:
                    440:                 alertmsg = '';
                    441:         }
                    442:         if (alertmsg != '') {
                    443:             alert(alertmsg);
                    444:             return;
                    445:         }
                    446:     }
                    447: END
                    448:     } else {
                    449:         $auth_checks .= (<<END);
                    450:     foundatype=1;
                    451:     if (current.argfield == null || current.argfield == '') {
                    452:         var alertmsg = '';
1.38      raeburn   453:         switch (current.radiovalue) {
1.1       raeburn   454:             case 'krb':
                    455:                 alertmsg = '$alert{'krb'}';
                    456:                 break;
                    457:             case 'loc':
                    458:             case 'fsys':
                    459:                 alertmsg = '$alert{'ipass'}';
                    460:                 break;
                    461:             case 'fsys':
                    462:                 alertmsg = '';
                    463:                 break;
                    464:             default:
                    465:                 alertmsg = '';
                    466:         }
                    467:         if (alertmsg != '') {
                    468:             alert(alertmsg);
                    469:             return;
                    470:         }
                    471:     }
                    472: END
                    473:     }
                    474:     my $section_checks;
                    475:     my $optional_checks = '';
                    476:     if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
                    477:         $optional_checks = (<<END);
                    478:     vf.submit();
                    479: }
                    480: END
                    481:     } else {
                    482:         $section_checks = &section_check_js();
                    483:         $optional_checks = (<<END);
                    484:     var message='';
                    485:     if (foundname==0) {
                    486:         message='$alert{'name'}';
                    487:     }
                    488:     if (foundid==0) {
                    489:         if (message!='') {
                    490:             message+='\\n';
                    491:         }
                    492:         message+='$alert{'snum'}';
                    493:     }
                    494:     if (foundsec==0) {
                    495:         if (message!='') {
                    496:             message+='\\n';
                    497:         }
                    498:     }
                    499:     if (foundemail==0) {
                    500:         if (message!='') {
                    501:             message+='\\n';
                    502:         }
                    503:         message+='$alert{'email'}';
                    504:     }
                    505:     if (message!='') {
                    506:         message+= '\\n$alert{'continue'}';
                    507:         if (confirm(message)) {
                    508:             vf.state.value='enrolling';
1.22      raeburn   509:             $finish
1.1       raeburn   510:         }
                    511:     } else {
                    512:         vf.state.value='enrolling';
1.22      raeburn   513:         $finish
1.1       raeburn   514:     }
                    515: }
                    516: END
                    517:     }
1.37      raeburn   518:     my $result = $function_name.$auth_checks.$optional_checks."\n".
                    519:                  $section_checks.$authheader;
1.1       raeburn   520:     return $result;
                    521: }
                    522: ###############################################################
                    523: ###############################################################
                    524: sub upload_manager_javascript_forward_associate {
                    525:     return(<<ENDPICK);
                    526: function verify(vf,sec_caller) {
                    527:     var founduname=0;
                    528:     var foundpwd=0;
                    529:     var foundname=0;
                    530:     var foundid=0;
                    531:     var foundsec=0;
                    532:     var foundemail=0;
                    533:     var foundrole=0;
                    534:     var tw;
                    535:     for (i=0;i<=vf.nfields.value;i++) {
                    536:         tw=eval('vf.f'+i+'.selectedIndex');
                    537:         if (tw==1) { founduname=1; }
                    538:         if ((tw>=2) && (tw<=6)) { foundname=1; }
                    539:         if (tw==7) { foundid=1; }
                    540:         if (tw==8) { foundsec=1; }
                    541:         if (tw==9) { foundpwd=1; }
                    542:         if (tw==10) { foundemail=1; }
                    543:         if (tw==11) { foundrole=1; }
                    544:     }
                    545:     verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole);
                    546: }
                    547: 
                    548: //
                    549: // vf = this.form
                    550: // tf = column number
                    551: //
                    552: // values of nw
                    553: //
                    554: // 0 = none
                    555: // 1 = username
                    556: // 2 = names (lastname, firstnames)
                    557: // 3 = fname (firstname)
                    558: // 4 = mname (middlename)
                    559: // 5 = lname (lastname)
                    560: // 6 = gen   (generation)
                    561: // 7 = id
                    562: // 8 = section
                    563: // 9 = ipwd  (password)
                    564: // 10 = email address
                    565: // 11 = role
                    566: 
                    567: function flip(vf,tf) {
                    568:    var nw=eval('vf.f'+tf+'.selectedIndex');
                    569:    var i;
                    570:    // make sure no other columns are labeled the same as this one
                    571:    for (i=0;i<=vf.nfields.value;i++) {
                    572:       if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
                    573:           eval('vf.f'+i+'.selectedIndex=0;')
                    574:       }
                    575:    }
                    576:    // If we set this to 'lastname, firstnames', clear out all the ones
                    577:    // set to 'fname','mname','lname','gen' (3,4,5,6) currently.
                    578:    if (nw==2) {
                    579:       for (i=0;i<=vf.nfields.value;i++) {
                    580:          if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
                    581:              (eval('vf.f'+i+'.selectedIndex')<=6)) {
                    582:              eval('vf.f'+i+'.selectedIndex=0;')
                    583:          }
                    584:       }
                    585:    }
                    586:    // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
                    587:    // clear out any that are set to 'lastname, firstnames' (2)
                    588:    if ((nw>=3) && (nw<=6)) {
                    589:       for (i=0;i<=vf.nfields.value;i++) {
                    590:          if (eval('vf.f'+i+'.selectedIndex')==2) {
                    591:              eval('vf.f'+i+'.selectedIndex=0;')
                    592:          }
                    593:       }
                    594:    }
                    595:    // If we set the password, make the password form below correspond to
                    596:    // the new value.
                    597:    if (nw==9) {
                    598:        changed_radio('int',document.studentform);
                    599:        set_auth_radio_buttons('int',document.studentform);
                    600:        vf.intarg.value='';
                    601:        vf.krbarg.value='';
                    602:        vf.locarg.value='';
                    603:    }
                    604: }
                    605: 
                    606: function clearpwd(vf) {
                    607:     var i;
                    608:     for (i=0;i<=vf.nfields.value;i++) {
                    609:         if (eval('vf.f'+i+'.selectedIndex')==9) {
                    610:             eval('vf.f'+i+'.selectedIndex=0;')
                    611:         }
                    612:     }
                    613: }
                    614: 
                    615: ENDPICK
                    616: }
                    617: 
                    618: ###############################################################
                    619: ###############################################################
                    620: sub upload_manager_javascript_reverse_associate {
                    621:     return(<<ENDPICK);
                    622: function verify(vf,sec_caller) {
                    623:     var founduname=0;
                    624:     var foundpwd=0;
                    625:     var foundname=0;
                    626:     var foundid=0;
                    627:     var foundsec=0;
                    628:     var foundrole=0;
                    629:     var tw;
                    630:     for (i=0;i<=vf.nfields.value;i++) {
                    631:         tw=eval('vf.f'+i+'.selectedIndex');
                    632:         if (i==0 && tw!=0) { founduname=1; }
                    633:         if (((i>=1) && (i<=5)) && tw!=0 ) { foundname=1; }
                    634:         if (i==6 && tw!=0) { foundid=1; }
                    635:         if (i==7 && tw!=0) { foundsec=1; }
                    636:         if (i==8 && tw!=0) { foundpwd=1; }
                    637:         if (i==9 && tw!=0) { foundrole=1; }
                    638:     }
                    639:     verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundrole);
                    640: }
                    641: 
                    642: function flip(vf,tf) {
                    643:    var nw=eval('vf.f'+tf+'.selectedIndex');
                    644:    var i;
                    645:    // picked the all one name field, reset the other name ones to blank
                    646:    if (tf==1 && nw!=0) {
                    647:       for (i=2;i<=5;i++) {
                    648:          eval('vf.f'+i+'.selectedIndex=0;')
                    649:       }
                    650:    }
                    651:    //picked one of the piecewise name fields, reset the all in
                    652:    //one field to blank
                    653:    if ((tf>=2) && (tf<=5) && (nw!=0)) {
                    654:       eval('vf.f1.selectedIndex=0;')
                    655:    }
                    656:    // intial password specified, pick internal authentication
                    657:    if (tf==8 && nw!=0) {
                    658:        changed_radio('int',document.studentform);
                    659:        set_auth_radio_buttons('int',document.studentform);
                    660:        vf.krbarg.value='';
                    661:        vf.intarg.value='';
                    662:        vf.locarg.value='';
                    663:    }
                    664: }
                    665: 
                    666: function clearpwd(vf) {
                    667:     var i;
                    668:     if (eval('vf.f8.selectedIndex')!=0) {
                    669:         eval('vf.f8.selectedIndex=0;')
                    670:     }
                    671: }
                    672: ENDPICK
                    673: }
                    674: 
                    675: ###############################################################
                    676: ###############################################################
                    677: sub print_upload_manager_footer {
1.22      raeburn   678:     my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context,$permission) = @_;
                    679:     my $form = 'document.studentform';
                    680:     my $formname = 'studentform';
1.1       raeburn   681:     my ($krbdef,$krbdefdom) =
                    682:         &Apache::loncommon::get_kerberos_defaults($defdom);
1.22      raeburn   683:     my %param = ( formname => $form,
1.1       raeburn   684:                   kerb_def_dom => $krbdefdom,
                    685:                   kerb_def_auth => $krbdef
                    686:                   );
                    687:     if (exists($env{'form.ipwd_choice'}) &&
                    688:         defined($env{'form.ipwd_choice'}) &&
                    689:         $env{'form.ipwd_choice'} ne '') {
                    690:         $param{'curr_authtype'} = 'int';
                    691:     }
                    692:     my $krbform = &Apache::loncommon::authform_kerberos(%param);
                    693:     my $intform = &Apache::loncommon::authform_internal(%param);
                    694:     my $locform = &Apache::loncommon::authform_local(%param);
1.22      raeburn   695:     my $date_table = &date_setting_table(undef,undef,$context,undef,
                    696:                                          $formname,$permission);
1.1       raeburn   697:     my $Str = "\n".'<div class="LC_left_float">';
                    698:     $Str .= &hidden_input('nfields',$i);
                    699:     $Str .= &hidden_input('keyfields',$keyfields);
                    700:     $Str .= "<h3>".&mt('Login Type')."</h3>\n";
                    701:     if ($context eq 'domain') {
                    702:         $Str .= '<p>'.&mt('Change authentication for existing users to these settings?').'&nbsp;<span class="LC_nobreak"><label><input type="radio" name="changeauth" value="No" checked="checked" />'.&mt('No').'</label>&nbsp;&nbsp;<label><input type="radio" name="changeauth" value="Yes" />'.&mt('Yes').'</label></span></p>'; 
                    703:     } else {
                    704:         $Str .= "<p>\n".
                    705:             &mt('Note: this will not take effect if the user already exists').
                    706:             &Apache::loncommon::help_open_topic('Auth_Options').
                    707:             "</p>\n";
                    708:     }
                    709:     $Str .= &set_login($defdom,$krbform,$intform,$locform);
                    710:     my ($home_server_pick,$numlib) =
                    711:         &Apache::loncommon::home_server_form_item($defdom,'lcserver',
                    712:                                                   'default','hide');
                    713:     if ($numlib > 1) {
                    714:         $Str .= '<h3>'.&mt('LON-CAPA Home Server for New Users')."</h3>\n".
                    715:                 &mt('LON-CAPA domain: [_1] with home server: [_2]',$defdom,
                    716:                 $home_server_pick).'<br />';
                    717:     } else {
                    718:         $Str .= $home_server_pick;
                    719:     }
                    720:     $Str .= '<h3>'.&mt('Starting and Ending Dates').
                    721:             "</h3>\n";
                    722:     $Str .= "<p>\n".$date_table."</p>\n";
                    723:     if ($context eq 'domain') {
                    724:         $Str .= '<h3>'.&mt('Settings for assigning roles:').'</h3>'."\n".
                    725:                 &mt('Pick the action to take on roles for these users:').'<br /><span class="LC_nobreak"><label><input type="radio" name="roleaction" value="norole" checked="checked" />&nbsp;'.&mt('No role changes').'</label>&nbsp;&nbsp;&nbsp;<label><input type="radio" name="roleaction" value="domain" />&nbsp;'.&mt('Add a domain role').'</label>&nbsp;&nbsp;&nbsp;<label><input type="radio" name="roleaction" value="course" />&nbsp;'.&mt('Add a course role').'</label></span>';
                    726:     }
1.13      raeburn   727:     if ($context eq 'author') {
1.1       raeburn   728:         $Str .= '<h3>'.&mt('Default role')."</h3>\n".
1.25      raeburn   729:                 &mt('Choose the role to assign to users without a value specified in the uploaded file');
1.1       raeburn   730:     } elsif ($context eq 'course') {
                    731:         $Str .= '<h3>'.&mt('Default role and section')."</h3>\n".
1.25      raeburn   732:                 &mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file');
1.1       raeburn   733:     } else {
1.25      raeburn   734:         $Str .= '<br /><br /><b>'.&mt('Default role and/or section(s)')."</b><br />\n".
                    735:                 &mt('Role and/or section(s) for users without values specified in the uploaded file.');
1.1       raeburn   736:     }
1.22      raeburn   737:     $Str .= '<br />';
                    738:     if (($context eq 'domain') || ($context eq 'author')) {
                    739:         my ($options,$cb_script,$coursepick) = &default_role_selector($context,1);
                    740:         if ($context eq 'domain') {
                    741:             $Str .= '<span class="LC_role_level">'.&mt('Domain Level').'</span><br />'.$options.'<br /><br /><span class="LC_role_level">'.&mt('Course Level').'</span><br />'.$cb_script.$coursepick;
                    742:         } elsif ($context eq 'author') {
                    743:             $Str .= $options;
                    744:         }
1.1       raeburn   745:     } else {
1.22      raeburn   746:         my ($cnum,$cdom) = &get_course_identity();
                    747:         my $rowtitle = &mt('section');
                    748:         my $secbox = &section_picker($cdom,$cnum,'Any',$rowtitle,
                    749:                                      $permission,$context,'upload');
                    750:         $Str .= $secbox."<h3>".&mt('Full Update')."</h3>\n".
                    751:                 '<p><label><input type="checkbox" name="fullup" value="yes">'.
1.36      raeburn   752:                 ' '.&mt('Display students with current/future access who are not in the uploaded file.').'</label><br />'.&mt('Students selected from this list can be dropped.').'</p>'."\n";
1.1       raeburn   753:     }
1.5       raeburn   754:     if ($context eq 'course' || $context eq 'domain') {
                    755:         $Str .= &forceid_change($context);
                    756:     }
1.1       raeburn   757:     $Str .= '</div><div class="LC_clear_float_footer"><br /><input type="button"'.
                    758:               'onClick="javascript:verify(this.form,this.form.csec)" '.
                    759:         'value="Update Users" />'."<br />\n";
                    760:     if ($context eq 'course') {
                    761:         $Str .= &mt('Note: for large courses, this operation may be time '.
                    762:                     'consuming');
                    763:     }
                    764:     $Str .= '</div>';
                    765:     $r->print($Str);
                    766:     return;
                    767: }
                    768: 
1.5       raeburn   769: sub forceid_change {
                    770:     my ($context) = @_;
                    771:     my $output = 
                    772:         "<h3>".&mt('ID/Student Number')."</h3>\n".
                    773:         "<p>\n".'<label><input type="checkbox" name="forceid" value="yes">'.
                    774:         &mt('Disable ID/Student Number Safeguard and Force Change '.
                    775:         'of Conflicting IDs').'</label><br />'."\n".
1.25      raeburn   776:         &mt('(only do if you know what you are doing.)')."\n";
1.5       raeburn   777:     if ($context eq 'domain') {
1.25      raeburn   778:         $output .= '<br /><label><input type="checkbox" name="recurseid"'.
1.5       raeburn   779:                    ' value="yes">'. 
1.13      raeburn   780:   &mt('Update ID/Student Number in courses in which user is Active/Future student,<br />(if forcing change).').
1.25      raeburn   781:                    '</label>'."\n";
1.5       raeburn   782:     }
1.25      raeburn   783:     $output .= '</p>';
1.5       raeburn   784:     return $output;
                    785: }
                    786: 
1.1       raeburn   787: ###############################################################
                    788: ###############################################################
                    789: sub print_upload_manager_form {
1.21      raeburn   790:     my ($r,$context,$permission) = @_;
1.1       raeburn   791:     my $firstLine;
                    792:     my $datatoken;
                    793:     if (!$env{'form.datatoken'}) {
                    794:         $datatoken=&Apache::loncommon::upfile_store($r);
                    795:     } else {
                    796:         $datatoken=$env{'form.datatoken'};
                    797:         &Apache::loncommon::load_tmp_file($r);
                    798:     }
                    799:     my @records=&Apache::loncommon::upfile_record_sep();
                    800:     if($env{'form.noFirstLine'}){
                    801:         $firstLine=shift(@records);
                    802:     }
                    803:     my $total=$#records;
                    804:     my $distotal=$total+1;
                    805:     my $today=time;
                    806:     my $halfyear=$today+15552000;
                    807:     #
                    808:     # Restore memorized settings
                    809:     my $col_setting_names =  { 'username_choice' => 'scalar', # column settings
                    810:                                'names_choice' => 'scalar',
                    811:                                'fname_choice' => 'scalar',
                    812:                                'mname_choice' => 'scalar',
                    813:                                'lname_choice' => 'scalar',
                    814:                                'gen_choice' => 'scalar',
                    815:                                'id_choice' => 'scalar',
                    816:                                'sec_choice' => 'scalar',
                    817:                                'ipwd_choice' => 'scalar',
                    818:                                'email_choice' => 'scalar',
                    819:                                'role_choice' => 'scalar',
                    820:                              };
                    821:     my $defdom = $env{'request.role.domain'};
                    822:     if ($context eq 'course') {
                    823:         &Apache::loncommon::restore_course_settings('enrollment_upload',
                    824:                                                     $col_setting_names);
                    825:     } else {
                    826:         &Apache::loncommon::restore_settings($context,'user_upload',
                    827:                                              $col_setting_names);
                    828:     }
                    829:     #
                    830:     # Determine kerberos parameters as appropriate
                    831:     my ($krbdef,$krbdefdom) =
                    832:         &Apache::loncommon::get_kerberos_defaults($defdom);
                    833:     #
1.22      raeburn   834:     &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom,$context,
                    835:                                  $permission);
1.1       raeburn   836:     my $i;
                    837:     my $keyfields;
                    838:     if ($total>=0) {
                    839:         my @field=
                    840:             (['username',&mt('Username'),     $env{'form.username_choice'}],
                    841:              ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}],
                    842:              ['fname',&mt('First Name'),      $env{'form.fname_choice'}],
                    843:              ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}],
                    844:              ['lname',&mt('Last Name'),       $env{'form.lname_choice'}],
                    845:              ['gen',  &mt('Generation'),      $env{'form.gen_choice'}],
                    846:              ['id',   &mt('ID/Student Number'),$env{'form.id_choice'}],
                    847:              ['sec',  &mt('Section'),          $env{'form.sec_choice'}],
                    848:              ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}],
                    849:              ['email',&mt('E-mail Address'),   $env{'form.email_choice'}],
                    850:              ['role',&mt('Role'),             $env{'form.role_choice'}]);
                    851:         if ($env{'form.upfile_associate'} eq 'reverse') {
                    852:             &Apache::loncommon::csv_print_samples($r,\@records);
                    853:             $i=&Apache::loncommon::csv_print_select_table($r,\@records,
                    854:                                                           \@field);
                    855:             foreach (@field) {
                    856:                 $keyfields.=$_->[0].',';
                    857:             }
                    858:             chop($keyfields);
                    859:         } else {
                    860:             unshift(@field,['none','']);
                    861:             $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
                    862:                                                             \@field);
                    863:             my %sone=&Apache::loncommon::record_sep($records[0]);
                    864:             $keyfields=join(',',sort(keys(%sone)));
                    865:         }
                    866:     }
                    867:     $r->print('</div>');
                    868:     &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear,
1.22      raeburn   869:                                  $context,$permission);
1.1       raeburn   870: }
                    871: 
                    872: sub setup_date_selectors {
1.22      raeburn   873:     my ($starttime,$endtime,$mode,$nolink,$formname) = @_;
                    874:     if ($formname eq '') {
                    875:         $formname = 'studentform';
                    876:     }
1.1       raeburn   877:     if (! defined($starttime)) {
                    878:         $starttime = time;
                    879:         unless ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
                    880:             if (exists($env{'course.'.$env{'request.course.id'}.
                    881:                             '.default_enrollment_start_date'})) {
                    882:                 $starttime = $env{'course.'.$env{'request.course.id'}.
                    883:                                   '.default_enrollment_start_date'};
                    884:             }
                    885:         }
                    886:     }
                    887:     if (! defined($endtime)) {
                    888:         $endtime = time+(6*30*24*60*60); # 6 months from now, approx
                    889:         unless ($mode eq 'createcourse') {
                    890:             if (exists($env{'course.'.$env{'request.course.id'}.
                    891:                             '.default_enrollment_end_date'})) {
                    892:                 $endtime = $env{'course.'.$env{'request.course.id'}.
                    893:                                 '.default_enrollment_end_date'};
                    894:             }
                    895:         }
                    896:     }
1.11      raeburn   897: 
                    898:     my $startdateform = 
1.22      raeburn   899:         &Apache::lonhtmlcommon::date_setter($formname,'startdate',$starttime,
1.11      raeburn   900:             undef,undef,undef,undef,undef,undef,undef,$nolink);
                    901: 
                    902:     my $enddateform = 
1.22      raeburn   903:         &Apache::lonhtmlcommon::date_setter($formname,'enddate',$endtime,
1.11      raeburn   904:             undef,undef,undef,undef,undef,undef,undef,$nolink);
                    905: 
1.1       raeburn   906:     if ($mode eq 'create_enrolldates') {
                    907:         $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
                    908:                                                             'startenroll',
                    909:                                                             $starttime);
                    910:         $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
                    911:                                                           'endenroll',
                    912:                                                           $endtime);
                    913:     }
                    914:     if ($mode eq 'create_defaultdates') {
                    915:         $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
                    916:                                                             'startaccess',
                    917:                                                             $starttime);
                    918:         $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
                    919:                                                           'endaccess',
                    920:                                                           $endtime);
                    921:     }
                    922:     return ($startdateform,$enddateform);
                    923: }
                    924: 
                    925: 
                    926: sub get_dates_from_form {
                    927:     my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate');
                    928:     my $enddate   = &Apache::lonhtmlcommon::get_date_from_form('enddate');
                    929:     if ($env{'form.no_end_date'}) {
                    930:         $enddate = 0;
                    931:     }
                    932:     return ($startdate,$enddate);
                    933: }
                    934: 
                    935: sub date_setting_table {
1.22      raeburn   936:     my ($starttime,$endtime,$mode,$bulkaction,$formname,$permission) = @_;
1.11      raeburn   937:     my $nolink;
                    938:     if ($bulkaction) {
                    939:         $nolink = 1;
                    940:     }
                    941:     my ($startform,$endform) = 
1.22      raeburn   942:         &setup_date_selectors($starttime,$endtime,$mode,$nolink,$formname);
1.1       raeburn   943:     my $dateDefault;
                    944:     if ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
                    945:         $dateDefault = '&nbsp;';
1.13      raeburn   946:     } elsif ($mode ne 'author' && $mode ne 'domain') {
1.11      raeburn   947:         if (($bulkaction eq 'reenable') || 
                    948:             ($bulkaction eq 'activate') || 
1.22      raeburn   949:             ($bulkaction eq 'chgdates') ||
                    950:             ($env{'form.action'} eq 'upload')) {
                    951:             if ($env{'request.course.sec'} eq '') {
                    952:                 $dateDefault = '<span class="LC_nobreak">'.
1.25      raeburn   953:                     '<label><input type="checkbox" name="makedatesdefault" value="1" /> '.
1.22      raeburn   954:                     &mt('make these dates the default access dates for future student enrollment').
                    955:                     '</label></span>';
                    956:             }
1.11      raeburn   957:         }
1.1       raeburn   958:     }
1.11      raeburn   959:     my $perpetual = '<span class="LC_nobreak"><label><input type="checkbox" name="no_end_date"';
1.1       raeburn   960:     if (defined($endtime) && $endtime == 0) {
                    961:         $perpetual .= ' checked';
                    962:     }
1.11      raeburn   963:     $perpetual.= ' /> '.&mt('no ending date').'</label></span>';
1.1       raeburn   964:     if ($mode eq 'create_enrolldates') {
                    965:         $perpetual = '&nbsp;';
                    966:     }
1.11      raeburn   967:     my $result = &Apache::lonhtmlcommon::start_pick_box()."\n";
                    968:     $result .= &Apache::lonhtmlcommon::row_title(&mt('Starting Date'),
                    969:                                                      'LC_oddrow_value')."\n".
                    970:                $startform."\n".
                    971:                &Apache::lonhtmlcommon::row_closure(1).
                    972:                &Apache::lonhtmlcommon::row_title(&mt('Ending Date'), 
                    973:                                                      'LC_oddrow_value')."\n".
                    974:                $endform.'&nbsp;'.$perpetual.
                    975:                &Apache::lonhtmlcommon::row_closure(1).
1.22      raeburn   976:                &Apache::lonhtmlcommon::end_pick_box();
1.1       raeburn   977:     if ($dateDefault) {
                    978:         $result .=  $dateDefault.'<br />'."\n";
                    979:     }
                    980:     return $result;
                    981: }
                    982: 
                    983: sub make_dates_default {
                    984:     my ($startdate,$enddate,$context) = @_;
                    985:     my $result = '';
                    986:     if ($context eq 'course') {
1.17      raeburn   987:         my ($cnum,$cdom) = &get_course_identity();
1.1       raeburn   988:         my $put_result = &Apache::lonnet::put('environment',
                    989:                 {'default_enrollment_start_date'=>$startdate,
1.17      raeburn   990:                  'default_enrollment_end_date'  =>$enddate},$cdom,$cnum);
1.1       raeburn   991:         if ($put_result eq 'ok') {
1.25      raeburn   992:             $result .= &mt('Set default start and end access dates for course.').
1.11      raeburn   993:                        '<br />'."\n";
1.1       raeburn   994:             #
                    995:             # Refresh the course environment
                    996:             &Apache::lonnet::coursedescription($env{'request.course.id'},
                    997:                                                {'freshen_cache' => 1});
                    998:         } else {
1.25      raeburn   999:             $result .= &mt('Unable to set default access dates for course.').":".$put_result.
1.1       raeburn  1000:                        '<br />';
                   1001:         }
                   1002:     }
                   1003:     return $result;
                   1004: }
                   1005: 
                   1006: sub default_role_selector {
1.2       raeburn  1007:     my ($context,$checkpriv) = @_;
1.1       raeburn  1008:     my %customroles;
                   1009:     my ($options,$coursepick,$cb_jscript);
1.13      raeburn  1010:     if ($context ne 'author') {
1.1       raeburn  1011:         %customroles = &my_custom_roles();
                   1012:     }
                   1013: 
                   1014:     my %lt=&Apache::lonlocal::texthash(
                   1015:                     'rol'  => "Role",
                   1016:                     'grs'  => "Section",
                   1017:                     'exs'  => "Existing sections",
                   1018:                     'new'  => "New section",
                   1019:                   );
                   1020:     $options = '<select name="defaultrole">'."\n".
                   1021:                ' <option value="">'.&mt('Please select').'</option>'."\n"; 
                   1022:     if ($context eq 'course') {
1.2       raeburn  1023:         $options .= &default_course_roles($context,$checkpriv,%customroles);
1.13      raeburn  1024:     } elsif ($context eq 'author') {
1.2       raeburn  1025:         my @roles = &construction_space_roles($checkpriv);
1.1       raeburn  1026:         foreach my $role (@roles) {
                   1027:            my $plrole=&Apache::lonnet::plaintext($role);
                   1028:            $options .= '  <option value="'.$role.'">'.$plrole.'</option>'."\n";
                   1029:         }
                   1030:     } elsif ($context eq 'domain') {
1.2       raeburn  1031:         my @roles = &domain_roles($checkpriv);
1.1       raeburn  1032:         foreach my $role (@roles) {
                   1033:            my $plrole=&Apache::lonnet::plaintext($role);
                   1034:            $options .= '  <option value="'.$role.'">'.$plrole.'</option>';
                   1035:         }
                   1036:         my $courseform = &Apache::loncommon::selectcourse_link
1.22      raeburn  1037:             ('studentform','dccourse','dcdomain','coursedesc',"$env{'request.role.domain'}",undef,'Course');
1.1       raeburn  1038:         $cb_jscript = 
1.22      raeburn  1039:             &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'},'currsec','studentform');
1.1       raeburn  1040:         $coursepick = &Apache::loncommon::start_data_table().
                   1041:                       &Apache::loncommon::start_data_table_header_row().
                   1042:                       '<th>'.$courseform.'</th><th>'.$lt{'rol'}.'</th>'.
                   1043:                       '<th>'.$lt{'grs'}.'</th>'.
                   1044:                       &Apache::loncommon::end_data_table_header_row().
                   1045:                       &Apache::loncommon::start_data_table_row()."\n".
1.22      raeburn  1046:                       '<td><input type="text" name="coursedesc" value="" onFocus="this.blur();opencrsbrowser('."'studentform','dccourse','dcdomain','coursedesc',''".')" /></td>'."\n".
1.1       raeburn  1047:                       '<td><select name="courserole">'."\n".
1.2       raeburn  1048:                       &default_course_roles($context,$checkpriv,%customroles)."\n".
1.1       raeburn  1049:                       '</select></td><td>'.
                   1050:                       '<table class="LC_createuser">'.
                   1051:                       '<tr class="LC_section_row"><td valign"top">'.
1.22      raeburn  1052:                       $lt{'exs'}.'<br /><select name="currsec">'.
1.1       raeburn  1053:                       ' <option value=""><--'.&mt('Pick course first').
                   1054:                       '</select></td>'.
                   1055:                       '<td>&nbsp;&nbsp;</td>'.
                   1056:                       '<td valign="top">'.$lt{'new'}.'<br />'.
                   1057:                       '<input type="text" name="newsec" value="" size="5" />'.
1.22      raeburn  1058:                       '<input type="hidden" name="groups" value="" />'.
                   1059:                       '<input type="hidden" name="sections" value="" />'.
                   1060:                       '<input type="hidden" name="origdom" value="'.
                   1061:                       $env{'request.role.domain'}.'" />'.
                   1062:                       '<input type="hidden" name="dccourse" value="" />'.
                   1063:                       '<input type="hidden" name="dcdomain" value="" />'.
                   1064:                       '</td></tr></table></td>'.
1.1       raeburn  1065:                       &Apache::loncommon::end_data_table_row().
1.22      raeburn  1066:                       &Apache::loncommon::end_data_table()."\n";
1.1       raeburn  1067:     }
                   1068:     $options .= '</select>';
                   1069:     return ($options,$cb_jscript,$coursepick);
                   1070: }
                   1071: 
                   1072: sub default_course_roles {
1.2       raeburn  1073:     my ($context,$checkpriv,%customroles) = @_;
1.1       raeburn  1074:     my $output;
1.17      raeburn  1075:     my $custom = 1;
                   1076:     my @roles = &course_roles($context,$checkpriv,$custom);
1.1       raeburn  1077:     foreach my $role (@roles) {
1.22      raeburn  1078:         if ($role ne 'cr') {
                   1079:             my $plrole=&Apache::lonnet::plaintext($role);
                   1080:             $output .= '  <option value="'.$role.'">'.$plrole.'</option>';
                   1081:         }
1.1       raeburn  1082:     }
                   1083:     if (keys(%customroles) > 0) {
1.22      raeburn  1084:         if (grep(/^cr$/,@roles)) {
                   1085:             foreach my $cust (sort(keys(%customroles))) {
                   1086:                 my $custrole='cr_'.$env{'user.domain'}.
                   1087:                              '_'.$env{'user.name'}.'_'.$cust;
                   1088:                 $output .= '  <option value="'.$custrole.'">'.$cust.'</option>';
                   1089:             }
1.1       raeburn  1090:         }
                   1091:     }
                   1092:     return $output;
                   1093: }
                   1094: 
                   1095: sub construction_space_roles {
1.2       raeburn  1096:     my ($checkpriv) = @_;
1.17      raeburn  1097:     my @allroles = &roles_by_context('author');
1.1       raeburn  1098:     my @roles;
1.2       raeburn  1099:     if ($checkpriv) {
                   1100:         foreach my $role (@allroles) {
                   1101:             if (&Apache::lonnet::allowed('c'.$role,$env{'user.domain'}.'/'.$env{'user.name'})) { 
                   1102:                 push(@roles,$role); 
                   1103:             }
1.1       raeburn  1104:         }
1.2       raeburn  1105:         return @roles;
                   1106:     } else {
                   1107:         return @allroles;
1.1       raeburn  1108:     }
                   1109: }
                   1110: 
                   1111: sub domain_roles {
1.2       raeburn  1112:     my ($checkpriv) = @_;
1.17      raeburn  1113:     my @allroles = &roles_by_context('domain');
1.1       raeburn  1114:     my @roles;
1.2       raeburn  1115:     if ($checkpriv) {
                   1116:         foreach my $role (@allroles) {
                   1117:             if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
                   1118:                 push(@roles,$role);
                   1119:             }
1.1       raeburn  1120:         }
1.2       raeburn  1121:         return @roles;
                   1122:     } else {
                   1123:         return @allroles;
1.1       raeburn  1124:     }
                   1125: }
                   1126: 
                   1127: sub course_roles {
1.17      raeburn  1128:     my ($context,$checkpriv,$custom) = @_;
                   1129:     my @allroles = &roles_by_context('course',$custom);
1.1       raeburn  1130:     my @roles;
                   1131:     if ($context eq 'domain') {
                   1132:         @roles = @allroles;
                   1133:     } elsif ($context eq 'course') {
                   1134:         if ($env{'request.course.id'}) {
1.2       raeburn  1135:             if ($checkpriv) { 
                   1136:                 foreach my $role (@allroles) {
                   1137:                     if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
                   1138:                         push(@roles,$role);
                   1139:                     } else {
1.22      raeburn  1140:                         if ($role ne 'cc' && $env{'request.course.sec'} ne '') {
                   1141:                             if (&Apache::lonnet::allowed('c'.$role,
1.2       raeburn  1142:                                              $env{'request.course.id'}.'/'.
1.22      raeburn  1143:                                              $env{'request.course.sec'})) {
1.2       raeburn  1144:                                 push(@roles,$role);
                   1145:                             }
1.1       raeburn  1146:                         }
                   1147:                     }
                   1148:                 }
1.2       raeburn  1149:             } else {
                   1150:                 @roles = @allroles;
1.1       raeburn  1151:             }
                   1152:         }
                   1153:     }
                   1154:     return @roles;
                   1155: }
                   1156: 
                   1157: sub curr_role_permissions {
1.2       raeburn  1158:     my ($context,$setting,$checkpriv) = @_; 
1.17      raeburn  1159:     my $custom = 1;
1.1       raeburn  1160:     my @roles;
1.13      raeburn  1161:     if ($context eq 'author') {
1.2       raeburn  1162:         @roles = &construction_space_roles($checkpriv);
1.1       raeburn  1163:     } elsif ($context eq 'domain') {
                   1164:         if ($setting eq 'course') {
1.17      raeburn  1165:             @roles = &course_roles($context,$checkpriv,$custom); 
1.1       raeburn  1166:         } else {
1.2       raeburn  1167:             @roles = &domain_roles($checkpriv);
1.1       raeburn  1168:         }
                   1169:     } elsif ($context eq 'course') {
1.17      raeburn  1170:         @roles = &course_roles($context,$checkpriv,$custom);
1.1       raeburn  1171:     }
                   1172:     return @roles;
                   1173: }
                   1174: 
                   1175: # ======================================================= Existing Custom Roles
                   1176: 
                   1177: sub my_custom_roles {
                   1178:     my %returnhash=();
                   1179:     my %rolehash=&Apache::lonnet::dump('roles');
                   1180:     foreach my $key (keys %rolehash) {
                   1181:         if ($key=~/^rolesdef\_(\w+)$/) {
                   1182:             $returnhash{$1}=$1;
                   1183:         }
                   1184:     }
                   1185:     return %returnhash;
                   1186: }
                   1187: 
1.2       raeburn  1188: sub print_userlist {
                   1189:     my ($r,$mode,$permission,$context,$formname,$totcodes,$codetitles,
                   1190:         $idlist,$idlist_titles) = @_;
                   1191:     my $format = $env{'form.output'};
1.1       raeburn  1192:     if (! exists($env{'form.sortby'})) {
                   1193:         $env{'form.sortby'} = 'username';
                   1194:     }
1.2       raeburn  1195:     if ($env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) {
                   1196:         $env{'form.Status'} = 'Active';
1.1       raeburn  1197:     }
                   1198:     my $status_select = &Apache::lonhtmlcommon::StatusOptions
1.2       raeburn  1199:         ($env{'form.Status'});
1.1       raeburn  1200: 
1.2       raeburn  1201:     if ($env{'form.showrole'} eq '') {
1.13      raeburn  1202:         if ($context eq 'course') {
                   1203:             $env{'form.showrole'} = 'st';
                   1204:         } else {
                   1205:             $env{'form.showrole'} = 'Any';            
                   1206:         }
1.2       raeburn  1207:     }
1.1       raeburn  1208:     if (! defined($env{'form.output'}) ||
                   1209:         $env{'form.output'} !~ /^(csv|excel|html)$/ ) {
                   1210:         $env{'form.output'} = 'html';
                   1211:     }
                   1212: 
1.2       raeburn  1213:     my @statuses;
                   1214:     if ($env{'form.Status'} eq 'Any') {
                   1215:         @statuses = ('previous','active','future');
                   1216:     } elsif ($env{'form.Status'} eq 'Expired') {
                   1217:         @statuses = ('previous');
                   1218:     } elsif ($env{'form.Status'} eq 'Active') {
                   1219:         @statuses = ('active');
                   1220:     } elsif ($env{'form.Status'} eq 'Future') {
                   1221:         @statuses = ('future');
                   1222:     }
1.1       raeburn  1223: 
1.2       raeburn  1224: #    if ($context eq 'course') { 
                   1225: #        $r->print(&display_adv_courseroles());
                   1226: #    }
1.1       raeburn  1227:     #
                   1228:     # Interface output
1.2       raeburn  1229:     $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
                   1230:               '<input type="hidden" name="action" value="'.
1.1       raeburn  1231:               $env{'form.action'}.'" />');
                   1232:     $r->print("<p>\n");
                   1233:     if ($env{'form.action'} ne 'modifystudent') {
                   1234:         my %lt=&Apache::lonlocal::texthash('csv' => "CSV",
                   1235:                                            'excel' => "Excel",
                   1236:                                            'html'  => 'HTML');
                   1237:         my $output_selector = '<select size="1" name="output" >';
                   1238:         foreach my $outputformat ('html','csv','excel') {
                   1239:             my $option = '<option value="'.$outputformat.'" ';
                   1240:             if ($outputformat eq $env{'form.output'}) {
                   1241:                 $option .= 'selected ';
                   1242:             }
                   1243:             $option .='>'.$lt{$outputformat}.'</option>';
                   1244:             $output_selector .= "\n".$option;
                   1245:         }
                   1246:         $output_selector .= '</select>';
                   1247:         $r->print('<label>'.&mt('Output Format: [_1]',$output_selector).'</label>'.('&nbsp;'x3));
                   1248:     }
1.2       raeburn  1249:     $r->print('<label>'.&mt('User Status: [_1]',$status_select).'</label>'.('&nbsp;'x3)."\n");
                   1250:     my $roleselected = '';
                   1251:     if ($env{'form.showrole'} eq 'Any') {
                   1252:        $roleselected = ' selected="selected" '; 
                   1253:     }
1.33      raeburn  1254:     my ($role_select,$cnum,$cdom);
1.2       raeburn  1255:     if ($context eq 'domain') {
                   1256:         $role_select = &domain_roles_select();
                   1257:         $r->print('<label>'.&mt('Role Type: [_1]',$role_select).'</label>');
                   1258:     } else {
                   1259:         $role_select = '<select name="showrole">'."\n".
                   1260:                        '<option value="Any" '.$roleselected.'>'.
                   1261:                        &mt('Any role').'</option>';
                   1262:         my @poss_roles = &curr_role_permissions($context);
                   1263:         foreach my $role (@poss_roles) {
                   1264:             $roleselected = '';
                   1265:             if ($role eq $env{'form.showrole'}) {
                   1266:                 $roleselected = ' selected="selected" ';
                   1267:             }
1.22      raeburn  1268:             my $plrole;
                   1269:             if ($role eq 'cr') {
                   1270:                 $plrole = &mt('Custom role');
                   1271:             } else {
                   1272:                 $plrole=&Apache::lonnet::plaintext($role);
                   1273:             }
1.2       raeburn  1274:             $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>';
                   1275:         }
1.22      raeburn  1276:         $role_select .= '</select>';
1.2       raeburn  1277:         $r->print('<label>'.&mt('Role: [_1]',$role_select).'</label>');
1.33      raeburn  1278:         if ($context eq 'course') {
                   1279:             ($cnum,$cdom) = &get_course_identity();
                   1280:             $r->print(&section_group_filter($cnum,$cdom));
                   1281:         }
1.2       raeburn  1282:     }
                   1283:     if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) {
1.25      raeburn  1284:         $r->print('&nbsp;'.&list_submit_button(&mt('Update Display')).
                   1285:                   "\n</p>\n");
1.2       raeburn  1286:     }
                   1287:     my ($indexhash,$keylist) = &make_keylist_array();
                   1288:     my (%userlist,%userinfo);
1.3       raeburn  1289:     if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
                   1290:         my $courseform =
                   1291:             &Apache::lonhtmlcommon::course_selection($formname,$totcodes,
                   1292:                                          $codetitles,$idlist,$idlist_titles);
                   1293:         $r->print('<p>'.&Apache::lonhtmlcommon::start_pick_box()."\n".
                   1294:                   &Apache::lonhtmlcommon::start_pick_box()."\n".
                   1295:                   &Apache::lonhtmlcommon::row_title(&mt('Select Course(s)'),
                   1296:                                                     'LC_oddrow_value')."\n".
                   1297:                   $courseform."\n".
                   1298:                   &Apache::lonhtmlcommon::row_closure(1).
                   1299:                   &Apache::lonhtmlcommon::end_pick_box().'</p>'.
                   1300:                   '<p>'.&list_submit_button(&mt('Update Display')).
1.34      raeburn  1301:                   "\n".'</p><span class="LC_warning">'.&mt('Warning: data retrieval for multiple courses can take considerable time, as this operation is not currently optimized.').'</span>'."\n");
1.11      raeburn  1302:         if ($env{'form.coursepick'}) {
                   1303:             $r->print('<hr />'.&mt('Searching').' ...<br />&nbsp;<br />');
                   1304:         }
                   1305:     } else {
                   1306:         $r->print('<hr />'.&mt('Searching').' ...<br />&nbsp;<br />');
1.3       raeburn  1307:     }
                   1308:     $r->rflush();
1.1       raeburn  1309:     if ($context eq 'course') {
1.46    ! raeburn  1310:         if (($env{'form.showrole'} eq 'st') || ($env{'form.showrole'} eq 'Any')) { 
1.45      raeburn  1311:             my $classlist = &Apache::loncoursedata::get_classlist();
                   1312:             %userlist = %{$classlist};
                   1313:         }
1.43      raeburn  1314:         if ($env{'form.showrole'} ne 'st') {
                   1315:             my $showroles;
                   1316:             if ($env{'form.showrole'} ne 'Any') {
                   1317:                 $showroles = [$env{'form.showrole'}];
1.3       raeburn  1318:             } else {
1.43      raeburn  1319:                 $showroles = undef;
1.1       raeburn  1320:             }
1.43      raeburn  1321:             my $withsec = 1;
                   1322:             my $hidepriv = 1;
                   1323:             my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
                   1324:                               \@statuses,$showroles,undef,$withsec,$hidepriv);
                   1325:             &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
                   1326:                              \%advrolehash,$permission);
1.1       raeburn  1327:         }
1.2       raeburn  1328:     } else {
                   1329:         my (%cstr_roles,%dom_roles);
1.13      raeburn  1330:         if ($context eq 'author') {
1.2       raeburn  1331:             # List co-authors and assistant co-authors
1.17      raeburn  1332:             my @possroles = &roles_by_context($context);
1.2       raeburn  1333:             %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
                   1334:                                               \@statuses,\@possroles);
                   1335:             &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
1.11      raeburn  1336:                              \%cstr_roles,$permission);
1.2       raeburn  1337:         } elsif ($context eq 'domain') {
                   1338:             if ($env{'form.roletype'} eq 'domain') {
                   1339:                 %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'});
                   1340:                 foreach my $key (keys(%dom_roles)) {
                   1341:                     if (ref($dom_roles{$key}) eq 'HASH') {
                   1342:                         &gather_userinfo($context,$format,\%userlist,$indexhash,
1.11      raeburn  1343:                                          \%userinfo,$dom_roles{$key},$permission);
1.2       raeburn  1344:                     }
                   1345:                 }
1.13      raeburn  1346:             } elsif ($env{'form.roletype'} eq 'author') {
1.2       raeburn  1347:                 my %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'},['au']);
                   1348:                 my %coauthors;
                   1349:                 foreach my $key (keys(%dom_roles)) {
                   1350:                     if (ref($dom_roles{$key}) eq 'HASH') {
                   1351:                         if ($env{'form.showrole'} eq 'au') {
                   1352:                             &gather_userinfo($context,$format,\%userlist,$indexhash,
1.11      raeburn  1353:                                              \%userinfo,$dom_roles{$key},$permission);
1.2       raeburn  1354:                         } else {
                   1355:                             my @possroles;
                   1356:                             if ($env{'form.showrole'} eq 'Any') {
1.22      raeburn  1357:                                 @possroles = &roles_by_context('author');
1.2       raeburn  1358:                             } else {
                   1359:                                 @possroles = ($env{'form.showrole'}); 
                   1360:                             }
                   1361:                             foreach my $author (sort(keys(%{$dom_roles{$key}}))) {
1.22      raeburn  1362:                                 my ($role,$authorname,$authordom) = split(/:/,$author,-1);
1.2       raeburn  1363:                                 my $extent = '/'.$authordom.'/'.$authorname;
                   1364:                                 %{$coauthors{$extent}} =
                   1365:                                     &Apache::lonnet::get_my_roles($authorname,
                   1366:                                        $authordom,undef,\@statuses,\@possroles);
                   1367:                             }
                   1368:                             &gather_userinfo($context,$format,\%userlist,
1.11      raeburn  1369:                                      $indexhash,\%userinfo,\%coauthors,$permission);
1.2       raeburn  1370:                         }
                   1371:                     }
                   1372:                 }
                   1373:             } elsif ($env{'form.roletype'} eq 'course') {
                   1374:                 if ($env{'form.coursepick'}) {
                   1375:                     my %courses = &process_coursepick();
1.39      raeburn  1376:                     my %allusers;
                   1377:                     my $hidepriv = 1;
1.2       raeburn  1378:                     foreach my $cid (keys(%courses)) {
1.17      raeburn  1379:                         my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
1.11      raeburn  1380:                         next if ($cnum eq '' || $cdom eq '');
1.17      raeburn  1381:                         my $custom = 1;
1.2       raeburn  1382:                         my (@roles,@sections,%access,%users,%userdata,
1.6       albertel 1383:                             %statushash);
1.2       raeburn  1384:                         if ($env{'form.showrole'} eq 'Any') {
1.17      raeburn  1385:                             @roles = &course_roles($context,undef,$custom);
1.2       raeburn  1386:                         } else {
                   1387:                             @roles = ($env{'form.showrole'});
                   1388:                         }
                   1389:                         foreach my $role (@roles) {
                   1390:                             %{$users{$role}} = ();
                   1391:                         }
                   1392:                         foreach my $type (@statuses) {
                   1393:                             $access{$type} = $type;
                   1394:                         }
1.39      raeburn  1395:                         &Apache::loncommon::get_course_users($cdom,$cnum,\%access,\@roles,\@sections,\%users,\%userdata,\%statushash,$hidepriv);
1.2       raeburn  1396:                         foreach my $user (keys(%userdata)) {
                   1397:                             next if (ref($userinfo{$user}) eq 'HASH');
                   1398:                             foreach my $item ('fullname','id') {
                   1399:                                 $userinfo{$user}{$item} = $userdata{$user}[$indexhash->{$item}];
                   1400:                             }
                   1401:                         }
                   1402:                         foreach my $role (keys(%users)) {
                   1403:                             foreach my $user (keys(%{$users{$role}})) {
                   1404:                                 my $uniqid = $user.':'.$role;
                   1405:                                 $allusers{$uniqid}{$cid} = { desc => $cdesc,
                   1406:                                                              secs  => $statushash{$user}{$role},
                   1407:                                                            };
                   1408:                             }
                   1409:                         }
                   1410:                     }
                   1411:                     &gather_userinfo($context,$format,\%userlist,$indexhash,
1.11      raeburn  1412:                                      \%userinfo,\%allusers,$permission);
1.2       raeburn  1413:                 } else {
1.10      raeburn  1414:                     $r->print('<input type="hidden" name="phase" value="'.
                   1415:                               $env{'form.phase'}.'" /></form>');
1.2       raeburn  1416:                     return;
                   1417:                 }
1.1       raeburn  1418:             }
                   1419:         }
1.3       raeburn  1420:     }
                   1421:     if (keys(%userlist) == 0) {
1.13      raeburn  1422:         if ($context eq 'author') {
1.3       raeburn  1423:             $r->print(&mt('There are no co-authors to display.')."\n");
                   1424:         } elsif ($context eq 'domain') {
                   1425:             if ($env{'form.roletype'} eq 'domain') {
                   1426:                 $r->print(&mt('There are no users with domain roles to display.')."\n");
1.13      raeburn  1427:             } elsif ($env{'form.roletype'} eq 'author') {
1.3       raeburn  1428:                 $r->print(&mt('There are no authors or co-authors to display.')."\n");
                   1429:             } elsif ($env{'form.roletype'} eq 'course') {
                   1430:                 $r->print(&mt('There are no course users to display')."\n"); 
1.2       raeburn  1431:             }
1.3       raeburn  1432:         } elsif ($context eq 'course') {
                   1433:             $r->print(&mt('There are no course users to display.')."\n");
                   1434:         }
                   1435:     } else {
                   1436:         # Print out the available choices
1.4       raeburn  1437:         my $usercount;
1.3       raeburn  1438:         if ($env{'form.action'} eq 'modifystudent') {
1.10      raeburn  1439:             ($usercount) = &show_users_list($r,$context,'view',$permission,
1.4       raeburn  1440:                                  $env{'form.Status'},\%userlist,$keylist);
1.1       raeburn  1441:         } else {
1.4       raeburn  1442:             ($usercount) = &show_users_list($r,$context,$env{'form.output'},
1.10      raeburn  1443:                                $permission,$env{'form.Status'},\%userlist,$keylist);
1.4       raeburn  1444:         }
                   1445:         if (!$usercount) {
                   1446:             $r->print('<br />'.&mt('There are no users matching the search criteria.')); 
1.2       raeburn  1447:         }
                   1448:     }
1.10      raeburn  1449:     $r->print('<input type="hidden" name="phase" value="'.
                   1450:               $env{'form.phase'}.'" /></form>');
1.2       raeburn  1451: }
                   1452: 
1.33      raeburn  1453: sub section_group_filter {
                   1454:     my ($cnum,$cdom) = @_;
                   1455:     my @filters;
                   1456:     if ($env{'request.course.sec'} eq '') {
                   1457:         @filters = ('sec');
                   1458:     }
                   1459:     push(@filters,'grp');
                   1460:     my %name = (
                   1461:                  sec => 'secfilter',
                   1462:                  grp => 'grpfilter',
                   1463:                );
                   1464:     my %title = &Apache::lonlocal::texthash (
                   1465:                                               sec  => 'Section(s)',
                   1466:                                               grp  => 'Group(s)',
                   1467:                                               all  => 'all',
                   1468:                                               none => 'none',
                   1469:                                             );
                   1470:     my ($output,@options);
                   1471:     foreach my $item (@filters) {
                   1472:         my $markup; 
                   1473:         if ($env{'form.'.$name{$item}} eq '') {
                   1474:             $env{'form.'.$name{$item}} = 'all';
                   1475:         }
                   1476:         if ($item eq 'sec') {
                   1477:             if ($env{'form.showrole'} eq 'cc') {
                   1478:                 $env{'form.'.$name{$item}} = 'none';
                   1479:             }
                   1480:             my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
                   1481:             @options = sort(keys(%sections_count));
                   1482:         } elsif ($item eq 'grp') {
                   1483:             my %curr_groups = &Apache::longroup::coursegroups();
                   1484:             @options = sort(keys(%curr_groups));
                   1485:         }
                   1486:         if (@options > 0) {
                   1487:             my $currsel;
                   1488:             $markup = '<select name="'.$name{$item}.'" />'."\n";
                   1489:             foreach my $option ('all','none',@options) { 
                   1490:                 $currsel = '';
                   1491:                 if ($env{'form.'.$name{$item}} eq $option) {
                   1492:                     $currsel = ' selected="selected" ';
                   1493:                 }
                   1494:                 $markup .= ' <option value="'.$option.'"'.$currsel.'>';
                   1495:                 if (($option eq 'all') || ($option eq 'none')) {
                   1496:                     $markup .= $title{$option};
                   1497:                 } else {
                   1498:                     $markup .= $option;
                   1499:                 }   
                   1500:                 $markup .= '</option>'."\n";
                   1501:             }
                   1502:             $markup .= '</select>'."\n";
                   1503:             $output .= ('&nbsp;'x3).'<label>'.$title{$item}.': '.$markup.'</label>';
                   1504:         }
                   1505:     }
                   1506:     return $output;
                   1507: }
                   1508: 
1.2       raeburn  1509: sub list_submit_button {
                   1510:     my ($text) = @_;
1.11      raeburn  1511:     return '<input type="button" name="updatedisplay" value="'.$text.'" onclick="javascript:display_update()" />';
1.2       raeburn  1512: }
                   1513: 
                   1514: sub gather_userinfo {
1.11      raeburn  1515:     my ($context,$format,$userlist,$indexhash,$userinfo,$rolehash,$permission) = @_;
1.2       raeburn  1516:     foreach my $item (keys(%{$rolehash})) {
                   1517:         my %userdata;
1.22      raeburn  1518:         if ($context eq 'author') { 
1.2       raeburn  1519:             ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
                   1520:                 split(/:/,$item);
                   1521:             ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
1.24      raeburn  1522:             &build_user_record($context,\%userdata,$userinfo,$indexhash,
                   1523:                                $item,$userlist);
1.22      raeburn  1524:         } elsif ($context eq 'course') {
                   1525:             my $viewablesec = &viewable_section($permission);
                   1526:             ($userdata{'username'},$userdata{'domain'},$userdata{'role'},
                   1527:              $userdata{'section'}) = split(/:/,$item,-1);
                   1528:             ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
                   1529:             if (($viewablesec ne '') && ($userdata{'section'} ne '')) {
                   1530:                 next if ($viewablesec ne $userdata{'section'});
                   1531:             }
1.24      raeburn  1532:             &build_user_record($context,\%userdata,$userinfo,$indexhash,
                   1533:                                $item,$userlist);
1.2       raeburn  1534:         } elsif ($context eq 'domain') {
                   1535:             if ($env{'form.roletype'} eq 'domain') {
                   1536:                 ($userdata{'role'},$userdata{'username'},$userdata{'domain'}) =
                   1537:                     split(/:/,$item);
                   1538:                 ($userdata{'end'},$userdata{'start'})=split(/:/,$rolehash->{$item});
1.24      raeburn  1539:                 &build_user_record($context,\%userdata,$userinfo,$indexhash,
                   1540:                                    $item,$userlist);
1.13      raeburn  1541:             } elsif ($env{'form.roletype'} eq 'author') {
1.2       raeburn  1542:                 if (ref($rolehash->{$item}) eq 'HASH') {
                   1543:                     $userdata{'extent'} = $item;
                   1544:                     foreach my $key (keys(%{$rolehash->{$item}})) {
                   1545:                         ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =  split(/:/,$key);
                   1546:                         ($userdata{'start'},$userdata{'end'}) = 
                   1547:                             split(/:/,$rolehash->{$item}{$key});
                   1548:                         my $uniqid = $key.':'.$item;
1.25      raeburn  1549:                         &build_user_record($context,\%userdata,$userinfo,
                   1550:                                            $indexhash,$uniqid,$userlist);
1.2       raeburn  1551:                     }
                   1552:                 }
                   1553:             } elsif ($env{'form.roletype'} eq 'course') {
                   1554:                 ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
                   1555:                     split(/:/,$item);
                   1556:                 if (ref($rolehash->{$item}) eq 'HASH') {
1.11      raeburn  1557:                     my $numcids = keys(%{$rolehash->{$item}});
1.2       raeburn  1558:                     foreach my $cid (sort(keys(%{$rolehash->{$item}}))) {
                   1559:                         if (ref($rolehash->{$item}{$cid}) eq 'HASH') {
                   1560:                             my $spanstart = '';
                   1561:                             my $spanend = '; ';
                   1562:                             my $space = ', ';
                   1563:                             if ($format eq 'html' || $format eq 'view') {
                   1564:                                 $spanstart = '<span class="LC_nobreak">';
1.23      raeburn  1565:                                 # FIXME: actions on courses disabled for now
                   1566: #                                if ($permission->{'cusr'}) {
                   1567: #                                    if ($numcids > 1) {
1.25      raeburn  1568: #                                        $spanstart .= '<input type="radio" name="'.$item.'" value="'.$cid.'" />&nbsp;';
1.23      raeburn  1569: #                                    } else {
1.25      raeburn  1570: #                                        $spanstart .= '<input type="hidden" name="'.$item.'" value="'.$cid.'" />&nbsp;';
1.23      raeburn  1571: #                                    }
                   1572: #                                }
1.2       raeburn  1573:                                 $spanend = '</span><br />';
                   1574:                                 $space = ',&nbsp;';
                   1575:                             }
                   1576:                             $userdata{'extent'} .= $spanstart.
                   1577:                                     $rolehash->{$item}{$cid}{'desc'}.$space;
                   1578:                             if (ref($rolehash->{$item}{$cid}{'secs'}) eq 'HASH') { 
                   1579:                                 foreach my $sec (sort(keys(%{$rolehash->{$item}{$cid}{'secs'}}))) {
1.25      raeburn  1580:                                     if (($env{'form.Status'} eq 'Any') ||
                   1581:                                         ($env{'form.Status'} eq $rolehash->{$item}{$cid}{'secs'}{$sec})) {
                   1582:                                         $userdata{'extent'} .= $sec.$space.$rolehash->{$item}{$cid}{'secs'}{$sec}.$spanend;
                   1583:                                         $userdata{'status'} = $rolehash->{$item}{$cid}{'secs'}{$sec};
                   1584:                                     }
1.2       raeburn  1585:                                 }
                   1586:                             }
                   1587:                         }
                   1588:                     }
                   1589:                 }
1.25      raeburn  1590:                 if ($userdata{'status'} ne '') {
                   1591:                     &build_user_record($context,\%userdata,$userinfo,
                   1592:                                        $indexhash,$item,$userlist);
                   1593:                 }
1.2       raeburn  1594:             }
                   1595:         }
                   1596:     }
                   1597:     return;
                   1598: }
                   1599: 
                   1600: sub build_user_record {
1.24      raeburn  1601:     my ($context,$userdata,$userinfo,$indexhash,$record_key,$userlist) = @_;
1.11      raeburn  1602:     next if ($userdata->{'start'} eq '-1' && $userdata->{'end'} eq '-1');
1.24      raeburn  1603:     if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) {
                   1604:         &process_date_info($userdata);
                   1605:     }
1.2       raeburn  1606:     my $username = $userdata->{'username'};
                   1607:     my $domain = $userdata->{'domain'};
                   1608:     if (ref($userinfo->{$username.':'.$domain}) eq 'HASH') {
1.24      raeburn  1609:         $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
1.2       raeburn  1610:         $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
                   1611:     } else {
                   1612:         &aggregate_user_info($domain,$username,$userinfo);
                   1613:         $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
                   1614:         $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
                   1615:     }
                   1616:     foreach my $key (keys(%{$indexhash})) {
                   1617:         if (defined($userdata->{$key})) {
                   1618:             $userlist->{$record_key}[$indexhash->{$key}] = $userdata->{$key};
                   1619:         }
                   1620:     }
                   1621:     return;
                   1622: }
                   1623: 
                   1624: sub courses_selector {
                   1625:     my ($cdom,$formname) = @_;
                   1626:     my %coursecodes = ();
                   1627:     my %codes = ();
                   1628:     my @codetitles = ();
                   1629:     my %cat_titles = ();
                   1630:     my %cat_order = ();
                   1631:     my %idlist = ();
                   1632:     my %idnums = ();
                   1633:     my %idlist_titles = ();
                   1634:     my $caller = 'global';
                   1635:     my $format_reply;
                   1636:     my $jscript = '';
                   1637: 
1.7       albertel 1638:     my $totcodes = 0;
                   1639:     $totcodes =
1.2       raeburn  1640:         &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,
                   1641:                                                       $cdom,$totcodes);
                   1642:     if ($totcodes > 0) {
                   1643:         $format_reply =
                   1644:              &Apache::lonnet::auto_instcode_format($caller,$cdom,\%coursecodes,
                   1645:                                 \%codes,\@codetitles,\%cat_titles,\%cat_order);
                   1646:         if ($format_reply eq 'ok') {
                   1647:             my $numtypes = @codetitles;
                   1648:             &Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
                   1649:             my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles);
                   1650:             my $longtitles_str = join('","',@{$longtitles});
                   1651:             my $allidlist = $idlist{$codetitles[0]};
                   1652:             $jscript .= &Apache::courseclassifier::courseset_js_start($formname,$longtitles_str,$allidlist);
                   1653:             $jscript .= $scripttext;
                   1654:             $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,@codetitles);
                   1655:         }
                   1656:     }
                   1657:     my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom);
                   1658: 
                   1659:     my %elements = (
                   1660:                      Year => 'selectbox',
                   1661:                      coursepick => 'radio',
                   1662:                      coursetotal => 'text',
                   1663:                      courselist => 'text',
                   1664:                    );
                   1665:     $jscript .= &Apache::lonhtmlcommon::set_form_elements(\%elements);
                   1666:     if ($env{'form.coursepick'} eq 'category') {
                   1667:         $jscript .= qq|
                   1668: function setCourseCat(formname) {
                   1669:     if (formname.Year.options[formname.Year.selectedIndex].value == -1) {
                   1670:         return;
                   1671:     }
                   1672:     courseSet('Year');
                   1673:     for (var j=0; j<formname.Semester.length; j++) {
                   1674:         if (formname.Semester.options[j].value == "$env{'form.Semester'}") {
                   1675:             formname.Semester.options[j].selected = true;
                   1676:         }
                   1677:     }
                   1678:     if (formname.Semester.options[formname.Semester.selectedIndex].value == -1) {
                   1679:         return;
                   1680:     }
                   1681:     courseSet('Semester');
                   1682:     for (var j=0; j<formname.Department.length; j++) {
                   1683:         if (formname.Department.options[j].value == "$env{'form.Department'}") {            formname.Department.options[j].selected = true;
                   1684:         }
                   1685:     }
                   1686:     if (formname.Department.options[formname.Department.selectedIndex].value == -1) {
                   1687:         return;
                   1688:     }
                   1689:     courseSet('Department');
                   1690:     for (var j=0; j<formname.Number.length; j++) {
                   1691:         if (formname.Number.options[j].value == "$env{'form.Number'}") {
                   1692:             formname.Number.options[j].selected = true;
                   1693:         }
                   1694:     }
                   1695: }
                   1696: |;
                   1697:     }
                   1698:     return ($cb_jscript,$jscript,$totcodes,\@codetitles,\%idlist,
                   1699:             \%idlist_titles);
                   1700: }
                   1701: 
                   1702: sub course_selector_loadcode {
                   1703:     my ($formname) = @_;
                   1704:     my $loadcode;
                   1705:     if ($env{'form.coursepick'} ne '') {
                   1706:         $loadcode = 'javascript:setFormElements(document.'.$formname.')';
                   1707:         if ($env{'form.coursepick'} eq 'category') {
                   1708:             $loadcode .= ';javascript:setCourseCat(document.'.$formname.')';
                   1709:         }
                   1710:     }
                   1711:     return $loadcode;
                   1712: }
                   1713: 
                   1714: sub process_coursepick {
                   1715:     my $coursefilter = $env{'form.coursepick'};
                   1716:     my $cdom = $env{'request.role.domain'};
                   1717:     my %courses;
                   1718:     if ($coursefilter eq 'all') {
                   1719:         %courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.',
                   1720:                                                  undef,undef,'Course');
                   1721:     } elsif ($coursefilter eq 'category') {
                   1722:         my $instcode = &instcode_from_coursefilter();
                   1723:         %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.',
                   1724:                                                  undef,undef,'Course');
                   1725:     } elsif ($coursefilter eq 'specific') {
                   1726:         if ($env{'form.coursetotal'} > 1) {
                   1727:             my @course_ids = split(/&&/,$env{'form.courselist'});
                   1728:             foreach my $cid (@course_ids) {
                   1729:                 $courses{$cid} = '';
1.1       raeburn  1730:             }
1.2       raeburn  1731:         } else {
                   1732:             $courses{$env{'form.courselist'}} = '';
1.1       raeburn  1733:         }
1.2       raeburn  1734:     }
                   1735:     return %courses;
                   1736: }
                   1737: 
                   1738: sub instcode_from_coursefilter {
                   1739:     my $instcode = '';
                   1740:     my @cats = ('Semester','Year','Department','Number');
                   1741:     foreach my $category (@cats) {
                   1742:         if (defined($env{'form.'.$category})) {
                   1743:             unless ($env{'form.'.$category} eq '-1') {
                   1744:                 $instcode .= $env{'form.'.$category};
                   1745:            }
                   1746:         }
                   1747:     }
                   1748:     if ($instcode eq '') {
                   1749:         $instcode = '.';
                   1750:     }
                   1751:     return $instcode;
                   1752: }
                   1753: 
                   1754: sub display_adv_courseroles {
                   1755:     my $output;
                   1756:     #
                   1757:     # List course personnel
                   1758:     my %coursepersonnel = 
                   1759:        &Apache::lonnet::get_course_adv_roles($env{'request.course.id'});
                   1760:     #
                   1761:     $output = '<br />'.&Apache::loncommon::start_data_table();
                   1762:     foreach my $role (sort(keys(%coursepersonnel))) {
                   1763:         next if ($role =~ /^\s*$/);
                   1764:         $output .= &Apache::loncommon::start_data_table_row().
                   1765:                   '<td>'.$role.'</td><td>';
                   1766:         foreach my $user (split(',',$coursepersonnel{$role})) {
                   1767:             my ($puname,$pudom)=split(':',$user);
                   1768:             $output .= ' '.&Apache::loncommon::aboutmewrapper(
                   1769:                        &Apache::loncommon::plainname($puname,$pudom),
                   1770:                        $puname,$pudom);
                   1771:         }
                   1772:         $output .= '</td>'.&Apache::loncommon::end_data_table_row();
                   1773:     }
                   1774:     $output .= &Apache::loncommon::end_data_table();
                   1775: }
                   1776: 
                   1777: sub make_keylist_array {
                   1778:     my ($index,$keylist);
                   1779:     $index->{'domain'} = &Apache::loncoursedata::CL_SDOM();
                   1780:     $index->{'username'} = &Apache::loncoursedata::CL_SNAME();
                   1781:     $index->{'end'} = &Apache::loncoursedata::CL_END();
                   1782:     $index->{'start'} = &Apache::loncoursedata::CL_START();
                   1783:     $index->{'id'} = &Apache::loncoursedata::CL_ID();
                   1784:     $index->{'section'} = &Apache::loncoursedata::CL_SECTION();
                   1785:     $index->{'fullname'} = &Apache::loncoursedata::CL_FULLNAME();
                   1786:     $index->{'status'} = &Apache::loncoursedata::CL_STATUS();
                   1787:     $index->{'type'} = &Apache::loncoursedata::CL_TYPE();
                   1788:     $index->{'lockedtype'} = &Apache::loncoursedata::CL_LOCKEDTYPE();
                   1789:     $index->{'groups'} = &Apache::loncoursedata::CL_GROUP();
                   1790:     $index->{'email'} = &Apache::loncoursedata::CL_PERMANENTEMAIL();
                   1791:     $index->{'role'} = &Apache::loncoursedata::CL_ROLE();
                   1792:     $index->{'extent'} = &Apache::loncoursedata::CL_EXTENT();
1.44      raeburn  1793:     $index->{'photo'} = &Apache::loncoursedata::CL_PHOTO();
1.2       raeburn  1794:     foreach my $key (keys(%{$index})) {
                   1795:         $keylist->[$index->{$key}] = $key;
                   1796:     }
                   1797:     return ($index,$keylist);
                   1798: }
                   1799: 
                   1800: sub aggregate_user_info {
                   1801:     my ($udom,$uname,$userinfo) = @_;
                   1802:     my %info=&Apache::lonnet::get('environment',
                   1803:                                   ['firstname','middlename',
                   1804:                                    'lastname','generation','id'],
                   1805:                                    $udom,$uname);
                   1806:     my ($tmp) = keys(%info);
                   1807:     my ($fullname,$id);
                   1808:     if ($tmp =~/^(con_lost|error|no_such_host)/i) {
                   1809:         $fullname = 'not available';
                   1810:         $id = 'not available';
                   1811:         &Apache::lonnet::logthis('unable to retrieve environment '.
                   1812:                                  'for '.$uname.':'.$udom);
1.1       raeburn  1813:     } else {
1.2       raeburn  1814:         $fullname = &Apache::lonnet::format_name(@info{qw/firstname middlename lastname generation/},'lastname');
                   1815:         $id = $info{'id'};
                   1816:     }
                   1817:     $userinfo->{$uname.':'.$udom} = { 
                   1818:                                       fullname => $fullname,
                   1819:                                       id       => $id,
                   1820:                                     };
                   1821:     return;
                   1822: }
1.1       raeburn  1823: 
1.2       raeburn  1824: sub process_date_info {
                   1825:     my ($userdata) = @_;
                   1826:     my $now = time;
                   1827:     $userdata->{'status'} = 'Active';
                   1828:     if ($userdata->{'start'} > 0) {
                   1829:         if ($now < $userdata->{'start'}) {
                   1830:             $userdata->{'status'} = 'Future';
                   1831:         }
1.1       raeburn  1832:     }
1.2       raeburn  1833:     if ($userdata->{'end'} > 0) {
                   1834:         if ($now > $userdata->{'end'}) {
                   1835:             $userdata->{'status'} = 'Expired';
                   1836:         }
                   1837:     }
                   1838:     return;
1.1       raeburn  1839: }
                   1840: 
                   1841: sub show_users_list {
1.10      raeburn  1842:     my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist)=@_;
1.1       raeburn  1843:     #
                   1844:     # Variables for excel output
                   1845:     my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format);
                   1846:     #
                   1847:     # Variables for csv output
                   1848:     my ($CSVfile,$CSVfilename);
                   1849:     #
                   1850:     my $sortby = $env{'form.sortby'};
1.3       raeburn  1851:     my @sortable = ('username','domain','id','fullname','start','end','email','role');
1.2       raeburn  1852:     if ($context eq 'course') {
1.3       raeburn  1853:         push(@sortable,('section','groups','type'));
1.2       raeburn  1854:     } else {
1.3       raeburn  1855:         push(@sortable,'extent');
                   1856:     }
                   1857:     if (!grep(/^\Q$sortby\E$/,@sortable)) {
                   1858:         $sortby = 'username';
1.1       raeburn  1859:     }
1.22      raeburn  1860:     my $setting = $env{'form.roletype'};
1.35      raeburn  1861:     my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers);
1.1       raeburn  1862:     if ($context eq 'course') {
1.22      raeburn  1863:         $cid = $env{'request.course.id'};
1.17      raeburn  1864:         ($cnum,$cdom) = &get_course_identity($cid);
1.2       raeburn  1865:         ($classgroups) = &Apache::loncoursedata::get_group_memberships(
                   1866:                                      $userlist,$keylist,$cdom,$cnum);
1.16      raeburn  1867:         if ($mode eq 'autoenroll') {
                   1868:             $env{'form.showrole'} = 'st';
                   1869:         } else {
                   1870:             if (! exists($env{'form.displayphotos'})) {
                   1871:                 $env{'form.displayphotos'} = 'off';
                   1872:             }
                   1873:             $displayphotos = $env{'form.displayphotos'};
                   1874:             if (! exists($env{'form.displayclickers'})) {
                   1875:                 $env{'form.displayclickers'} = 'off';
                   1876:             }
                   1877:             $displayclickers = $env{'form.displayclickers'};
                   1878:             if ($env{'course.'.$cid.'.internal.showphoto'}) {
                   1879:                 $r->print('
1.1       raeburn  1880: <script type="text/javascript">
                   1881: function photowindow(photolink) {
                   1882:     var title = "Photo_Viewer";
                   1883:     var options = "scrollbars=1,resizable=1,menubar=0";
                   1884:     options += ",width=240,height=240";
                   1885:     stdeditbrowser = open(photolink,title,options,"1");
                   1886:     stdeditbrowser.focus();
                   1887: }
                   1888: </script>
1.16      raeburn  1889:                ');
                   1890:             }
                   1891:             $r->print(<<END);
1.1       raeburn  1892: <input type="hidden" name="displayphotos" value="$displayphotos" />
                   1893: <input type="hidden" name="displayclickers" value="$displayclickers" />
                   1894: END
1.16      raeburn  1895:         }
1.1       raeburn  1896:     }
1.16      raeburn  1897:     if ($mode ne 'autoenroll') {
1.11      raeburn  1898:         my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
                   1899:         my $alert = &mt("You must select at least one user by checking a user's 'Select' checkbox");
1.25      raeburn  1900:         my $singconfirm = &mt(' for a single user?');
                   1901:         my $multconfirm = &mt(' for multiple users?');
1.40      raeburn  1902:         my $date_sec_selector = &date_section_javascript($context,$setting,$statusmode);
                   1903:         my %lt = &Apache::lonlocal::texthash( 
                   1904:               acwi => 'Access will be set to start immediately',
                   1905:               asyo => 'as you did not select an end date in the pop-up window',
                   1906:               accw => 'Access will be set to continue indefinitely',
                   1907:               asyd => 'as you did not select an end date in the pop-up window',
                   1908:               sewi => "Sections will be switched to 'No section'",
                   1909:               ayes => "as you either selected the 'No section' option",
                   1910:               oryo => 'or you did not select a section in the pop-up window',
                   1911:               arol => 'A role with no section will be added',
                   1912:               swbs => 'Sections will be switched to:',
                   1913:               rwba => 'Roles will be added for section(s):',
                   1914:         );
1.1       raeburn  1915:         $r->print(<<END);
1.10      raeburn  1916: 
                   1917: <script type="text/javascript" language="Javascript">
1.11      raeburn  1918: $check_uncheck_js
                   1919: 
                   1920: function verify_action (field) {
                   1921:     var numchecked = 0;
                   1922:     var singconf = '$singconfirm';
                   1923:     var multconf = '$multconfirm';
                   1924:     if (field.length > 0) {
                   1925:         for (i = 0; i < field.length; i++) {
                   1926:             if (field[i].checked == true) {
                   1927:                numchecked ++;
                   1928:             }
                   1929:         }
                   1930:     } else {
                   1931:         if (field.checked == true) {
                   1932:             numchecked ++;
                   1933:         }
                   1934:     }
                   1935:     if (numchecked == 0) {
                   1936:         alert("$alert");
                   1937:     } 
                   1938:     else {
                   1939:         var message = document.studentform.bulkaction[document.studentform.bulkaction.selectedIndex].text;
1.40      raeburn  1940:         var choice = document.studentform.bulkaction[document.studentform.bulkaction.selectedIndex].value;
1.11      raeburn  1941:         if (numchecked == 1) { 
                   1942:             message += singconf;
                   1943:         } 
                   1944:         else {
                   1945:             message += multconf; 
                   1946:         }
1.40      raeburn  1947:         if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate') {
                   1948:             var datemsg = '';
                   1949:             if ((document.studentform.startdate_month.value == '') && 
                   1950:                 (document.studentform.startdate_day.value  == '') &&
                   1951:                 (document.studentform.startdate_year.value == '')) {
                   1952:                 datemsg = "\\n$lt{'acwi'},\\n$lt{'asyo'}.\\n";
                   1953:             }
                   1954:             if ((document.studentform.enddate_month.value == '') &&
                   1955:                 (document.studentform.enddate_day.value  == '') &&
                   1956:                 (document.studentform.enddate_year.value == '')) {
                   1957:                 datemsg += "\\n$lt{'accw'},\\n$lt{'asyd'}.\\n";
                   1958:             }
                   1959:             if (datemsg != '') {
                   1960:                 message += "\\n"+datemsg;
                   1961:             }
                   1962:         }
                   1963:         if (choice == 'chgsec') {
                   1964:             var rolefilter = document.studentform.showrole.options[document.studentform.showrole.selectedIndex].value;
                   1965:             var retained =  document.studentform.retainsec.value;
                   1966:             var secshow = document.studentform.newsecs.value;
                   1967:             if (secshow == '') {
                   1968:                 if (rolefilter == 'st' || retained == 0 || retained == "") {
                   1969:                     message += "\\n\\n$lt{'sewi'},\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n"; 
                   1970:                 } else {
                   1971:                     message += "\\n\\n$lt{'arol'}\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n";
                   1972:                 }
                   1973:             } else {
                   1974:                 if (rolefilter == 'st' || retained == 0 || retained == "") {
                   1975:                     message += "\\n\\n$lt{'swbs'} "+secshow+".\\n";
                   1976:                 } else {
                   1977:                     message += "\\n\\n$lt{'rwba'} "+secshow+".\\n";
                   1978:                 }
                   1979:             }
                   1980:         }
1.11      raeburn  1981:         if (confirm(message)) {
                   1982:             document.studentform.phase.value = 'bulkchange';
                   1983:             document.studentform.submit();
                   1984:         }
                   1985:     }
                   1986: }
1.10      raeburn  1987: 
                   1988: function username_display_launch(username,domain) {
                   1989:     var target;
                   1990:     for (var i=0; i<document.studentform.usernamelink.length; i++) {
                   1991:         if (document.studentform.usernamelink[i].checked) {
                   1992:             target = document.studentform.usernamelink[i].value;
                   1993:         }
                   1994:     }
                   1995:     if (target == 'modify') {
                   1996:         document.studentform.srchterm.value=username;
                   1997:         document.studentform.srchdomain.value=domain;
                   1998:         document.studentform.phase.value='get_user_info';
                   1999:         document.studentform.action.value = 'singleuser';
                   2000:         document.studentform.submit();
                   2001:     }
                   2002:     else {
                   2003:         document.location.href = '/adm/'+domain+'/'+username+'/aboutme';
                   2004:     }
                   2005: }
                   2006: </script>
1.11      raeburn  2007: $date_sec_selector
1.1       raeburn  2008: <input type="hidden" name="state" value="$env{'form.state'}" />
                   2009: END
                   2010:     }
                   2011:     $r->print(<<END);
                   2012: <input type="hidden" name="sortby" value="$sortby" />
                   2013: END
                   2014: 
                   2015:     my %lt=&Apache::lonlocal::texthash(
                   2016:                        'username'   => "username",
                   2017:                        'domain'     => "domain",
                   2018:                        'id'         => 'ID',
                   2019:                        'fullname'   => "name",
                   2020:                        'section'    => "section",
                   2021:                        'groups'     => "active groups",
                   2022:                        'start'      => "start date",
                   2023:                        'end'        => "end date",
                   2024:                        'status'     => "status",
1.2       raeburn  2025:                        'role'       => "role",
1.1       raeburn  2026:                        'type'       => "enroll type/action",
                   2027:                        'email'      => "email address",
                   2028:                        'clicker'    => "clicker id",
                   2029:                        'photo'      => "photo",
1.2       raeburn  2030:                        'extent'     => "extent",
1.41      raeburn  2031:                        'go'         => "go",
1.11      raeburn  2032:                        'pr'         => "Proceed",
                   2033:                        'ca'         => "check all",
                   2034:                        'ua'         => "uncheck all",
                   2035:                        'ac'         => "Action to take for selected users",
1.10      raeburn  2036:                        'link'       => "Behavior of username links",
                   2037:                        'aboutme'    => "Display a user's personal page",
                   2038:                        'modify'     => "Modify a user's information",
1.1       raeburn  2039:                       );
1.2       raeburn  2040:     if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
                   2041:         $lt{'extent'} = &mt('Course(s): description, section(s), status');
1.13      raeburn  2042:     } elsif ($context eq 'author') {
1.2       raeburn  2043:         $lt{'extent'} = &mt('Author'); 
                   2044:     }
1.1       raeburn  2045:     my @cols = ('username','domain','id','fullname');
                   2046:     if ($context eq 'course') {
                   2047:         push(@cols,'section');
                   2048:     }
1.2       raeburn  2049:     if (!($context eq 'domain' && $env{'form.roletype'} eq 'course')) { 
                   2050:         push(@cols,('start','end'));
                   2051:     }
1.3       raeburn  2052:     if ($env{'form.showrole'} eq 'Any' || $env{'form.showrole'} eq 'cr') {
1.2       raeburn  2053:         push(@cols,'role');
                   2054:     }
1.13      raeburn  2055:     if ($context eq 'domain' && ($env{'form.roletype'} eq 'author' ||
1.2       raeburn  2056:                                 $env{'form.roletype'} eq 'course')) {
                   2057:         push (@cols,'extent');
                   2058:     }
                   2059:     if (($statusmode eq 'Any') && 
                   2060:         (!($context eq 'domain' && $env{'form.roletype'} eq 'course'))) {
1.1       raeburn  2061:         push(@cols,'status');
                   2062:     }
                   2063:     if ($context eq 'course') {
                   2064:         push(@cols,'groups');
                   2065:     }
                   2066:     push(@cols,'email');
                   2067: 
1.4       raeburn  2068:     my $rolefilter = $env{'form.showrole'};
1.5       raeburn  2069:     if ($env{'form.showrole'} eq 'cr') {
                   2070:         $rolefilter = &mt('custom');  
                   2071:     } elsif ($env{'form.showrole'} ne 'Any') {
1.2       raeburn  2072:         $rolefilter = &Apache::lonnet::plaintext($env{'form.showrole'});
                   2073:     }
1.16      raeburn  2074:     my $results_description;
                   2075:     if ($mode ne 'autoenroll') {
                   2076:         $results_description = &results_header_row($rolefilter,$statusmode,
1.24      raeburn  2077:                                                    $context,$permission,$mode);
1.16      raeburn  2078:         $r->print('<b>'.$results_description.'</b><br />');
                   2079:     }
1.26      raeburn  2080:     my ($output,$actionselect,%canchange,%canchangesec);
1.16      raeburn  2081:     if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll') {
                   2082:         if ($mode ne 'autoenroll') {
                   2083:             if ($permission->{'cusr'}) {
                   2084:                 $actionselect = &select_actions($context,$setting,$statusmode);
                   2085:             }
                   2086:             $r->print(<<END);
1.10      raeburn  2087: <input type="hidden" name="srchby"  value="uname" />
                   2088: <input type="hidden" name="srchin"   value="dom" />
                   2089: <input type="hidden" name="srchtype" value="exact" />
                   2090: <input type="hidden" name="srchterm" value="" />
1.11      raeburn  2091: <input type="hidden" name="srchdomain" value="" /> 
1.1       raeburn  2092: END
1.16      raeburn  2093:             $output = '<p>';
                   2094:             my @linkdests = ('aboutme');
                   2095:             if ($permission->{'cusr'}) {
                   2096:                 push (@linkdests,'modify');
                   2097:                 $output .= '<span class="LC_nobreak">'.$lt{'link'}.':&nbsp;';
                   2098:                 my $usernamelink = $env{'form.usernamelink'};
                   2099:                 if ($usernamelink eq '') {
                   2100:                     $usernamelink = 'aboutme';
                   2101:                 }
                   2102:                 foreach my $item (@linkdests) {
                   2103:                     my $checkedstr = '';
                   2104:                     if ($item eq $usernamelink) {
                   2105:                         $checkedstr = ' checked="checked" ';
                   2106:                     }
                   2107:                     $output .= '<label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.'>&nbsp;'.$lt{$item}.'</label>&nbsp;&nbsp;';
                   2108:                 }
                   2109:                 $output .= '</span><br />';
                   2110:             } else {
                   2111:                 $output .= &mt("Click on a username to view the user's personal page.").'<br />';
                   2112:             }
                   2113:             if ($actionselect) {
1.41      raeburn  2114:                 $output .= <<"END";
                   2115: $lt{'ac'}:&nbsp;$actionselect <input type="button" value="$lt{'go'}" onclick="javascript:opendatebrowser(this.form,'studentform','go')" /></p>
1.11      raeburn  2116: <p><input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.actionlist)" /> &nbsp;
1.41      raeburn  2117: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.actionlist)" /><br /><br /><input type="button" value="$lt{'pr'}" onclick="javascript:verify_action(document.studentform.actionlist)" />
1.11      raeburn  2118: END
1.26      raeburn  2119:                 my @allroles;
                   2120:                 if ($env{'form.showrole'} eq 'Any') {
                   2121:                     my $custom = 1;
                   2122:                     if ($context eq 'domain') {
                   2123:                         @allroles = &roles_by_context($setting,$custom);
                   2124:                     } else {
                   2125:                         @allroles = &roles_by_context($context,$custom);
                   2126:                     }
                   2127:                 } else {
                   2128:                     @allroles = ($env{'form.showrole'});
                   2129:                 }
                   2130:                 foreach my $role (@allroles) {
                   2131:                     if ($context eq 'domain') {
                   2132:                         if ($setting eq 'domain') {
                   2133:                             if (&Apache::lonnet::allowed('c'.$role,
                   2134:                                     $env{'request.role.domain'})) {
                   2135:                                 $canchange{$role} = 1;
                   2136:                             }
1.31      raeburn  2137:                         } elsif ($setting eq 'author') {
                   2138:                             if (&Apache::lonnet::allowed('c'.$role,
                   2139:                                     $env{'request.role.domain'})) {
                   2140:                                 $canchange{$role} = 1;
                   2141:                             }
1.26      raeburn  2142:                         }
                   2143:                     } elsif ($context eq 'author') {
                   2144:                         if (&Apache::lonnet::allowed('c'.$role,
                   2145:                             $env{'user.domain'}.'/'.$env{'user.name'})) {
                   2146:                             $canchange{$role} = 1;
                   2147:                         }
                   2148:                     } elsif ($context eq 'course') {
                   2149:                         if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
                   2150:                             $canchange{$role} = 1;
                   2151:                         } elsif ($env{'request.course.sec'} ne '') {
                   2152:                             if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
                   2153:                                 $canchangesec{$role} = $env{'request.course.sec'};
                   2154:                             }
                   2155:                         }
                   2156:                     }
                   2157:                 }
1.16      raeburn  2158:             }
1.4       raeburn  2159:         }
                   2160:         $output .= "\n<p>\n".
1.1       raeburn  2161:                   &Apache::loncommon::start_data_table().
1.4       raeburn  2162:                   &Apache::loncommon::start_data_table_header_row();
1.1       raeburn  2163:         if ($mode eq 'autoenroll') {
1.4       raeburn  2164:             $output .= "
1.1       raeburn  2165:  <th><a href=\"javascript:document.studentform.sortby.value='type';document.studentform.submit();\">$lt{'type'}</a></th>
1.4       raeburn  2166:             ";
1.1       raeburn  2167:         } else {
1.11      raeburn  2168:             $output .= "\n".'<th>'.&mt('Count').'</th>'."\n";
                   2169:             if ($actionselect) {
                   2170:                 $output .= '<th>'.&mt('Select').'</th>'."\n";
                   2171:             }
1.1       raeburn  2172:         }
                   2173:         foreach my $item (@cols) {
1.4       raeburn  2174:             $output .= "<th><a href=\"javascript:document.studentform.sortby.value='$item';document.studentform.submit();\">$lt{$item}</a></th>\n";
1.1       raeburn  2175:         }
1.2       raeburn  2176:         my %role_types = &role_type_names();
1.16      raeburn  2177:         if ($context eq 'course' && $mode ne 'autoenroll') {
1.4       raeburn  2178:             if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
                   2179:                 # Clicker display on or off?
                   2180:                 my %clicker_options = &Apache::lonlocal::texthash(
                   2181:                                                             'on' => 'Show',
                   2182:                                                             'off' => 'Hide',
                   2183:                                                            );
                   2184:                 my $clickerchg = 'on';
                   2185:                 if ($displayclickers eq 'on') {
                   2186:                     $clickerchg = 'off';
                   2187:                 }
                   2188:                 $output .= '    <th>'."\n".'     '.
                   2189:                     '<a href="javascript:document.studentform.displayclickers.value='.
1.1       raeburn  2190:                       "'".$clickerchg."'".';document.studentform.submit();">'.
                   2191:                       $clicker_options{$clickerchg}.'</a>&nbsp;'.$lt{'clicker'}."\n".
1.4       raeburn  2192:                       '    </th>'."\n";
1.1       raeburn  2193: 
1.4       raeburn  2194:                 # Photo display on or off?
                   2195:                 if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
                   2196:                     my %photo_options = &Apache::lonlocal::texthash(
                   2197:                                                             'on' => 'Show',
                   2198:                                                             'off' => 'Hide',
                   2199:                                                                 );
                   2200:                     my $photochg = 'on';
                   2201:                     if ($displayphotos eq 'on') {
                   2202:                         $photochg = 'off';
                   2203:                     }
                   2204:                     $output .= '    <th>'."\n".'     '.
                   2205:                 '<a href="javascript:document.studentform.displayphotos.value='.
1.1       raeburn  2206:                       "'".$photochg."'".';document.studentform.submit();">'.
                   2207:                       $photo_options{$photochg}.'</a>&nbsp;'.$lt{'photo'}."\n".
1.4       raeburn  2208:                       '    </th>'."\n";
                   2209:                 }
1.1       raeburn  2210:             }
1.4       raeburn  2211:         }
1.16      raeburn  2212:         $output .= &Apache::loncommon::end_data_table_header_row();
1.1       raeburn  2213: # Done with the HTML header line
                   2214:     } elsif ($mode eq 'csv') {
                   2215:         #
                   2216:         # Open a file
                   2217:         $CSVfilename = '/prtspool/'.
1.2       raeburn  2218:                        $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
                   2219:                        time.'_'.rand(1000000000).'.csv';
1.1       raeburn  2220:         unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
                   2221:             $r->log_error("Couldn't open $CSVfilename for output $!");
                   2222:             $r->print("Problems occured in writing the csv file.  ".
                   2223:                       "This error has been logged.  ".
                   2224:                       "Please alert your LON-CAPA administrator.");
                   2225:             $CSVfile = undef;
                   2226:         }
                   2227:         #
                   2228:         # Write headers and data to file
1.2       raeburn  2229:         print $CSVfile '"'.$results_description.'"'."\n"; 
1.1       raeburn  2230:         print $CSVfile '"'.join('","',map {
                   2231:             &Apache::loncommon::csv_translate($lt{$_})
                   2232:             } (@cols)).'"'."\n";
                   2233:     } elsif ($mode eq 'excel') {
                   2234:         # Create the excel spreadsheet
                   2235:         ($excel_workbook,$excel_filename,$format) =
                   2236:             &Apache::loncommon::create_workbook($r);
                   2237:         return if (! defined($excel_workbook));
                   2238:         $excel_sheet = $excel_workbook->addworksheet('userlist');
1.2       raeburn  2239:         $excel_sheet->write($row++,0,$results_description,$format->{'h2'});
1.1       raeburn  2240:         #
                   2241:         my @colnames = map {$lt{$_}} (@cols);
                   2242:         $excel_sheet->write($row++,0,\@colnames,$format->{'bold'});
                   2243:     }
                   2244: 
                   2245: # Done with header lines in all formats
                   2246: 
                   2247:     my %index;
                   2248:     my $i;
1.2       raeburn  2249:     foreach my $idx (@$keylist) {
                   2250:         $index{$idx} = $i++;
                   2251:     }
1.4       raeburn  2252:     my $usercount = 0;
1.33      raeburn  2253:     my ($secfilter,$grpfilter);
                   2254:     if ($context eq 'course') {
                   2255:         $secfilter = $env{'form.secfilter'};
                   2256:         $grpfilter = $env{'form.grpfilter'};
                   2257:         if ($secfilter eq '') {
                   2258:             $secfilter = 'all';
                   2259:         }
                   2260:         if ($grpfilter eq '') {
                   2261:             $grpfilter = 'all';
                   2262:         }
                   2263:     }
1.2       raeburn  2264:     # Get groups, role, permanent e-mail so we can sort on them if
                   2265:     # necessary.
                   2266:     foreach my $user (keys(%{$userlist})) {
1.43      raeburn  2267:         if ($user eq '' ) {
                   2268:             delete($userlist->{$user});
                   2269:             next;
                   2270:         }
1.11      raeburn  2271:         if ($context eq 'domain' &&  $user eq $env{'request.role.domain'}.'-domainconfig:'.$env{'request.role.domain'}) {
                   2272:             delete($userlist->{$user});
                   2273:             next;
                   2274:         }
1.2       raeburn  2275:         my ($uname,$udom,$role,$groups,$email);
1.5       raeburn  2276:         if (($statusmode ne 'Any') && 
                   2277:                  ($userlist->{$user}->[$index{'status'}] ne $statusmode)) {
                   2278:             delete($userlist->{$user});
                   2279:             next;
                   2280:         }
1.2       raeburn  2281:         if ($context eq 'domain') {
                   2282:             if ($env{'form.roletype'} eq 'domain') {
                   2283:                 ($role,$uname,$udom) = split(/:/,$user);
1.11      raeburn  2284:                 if (($uname eq $env{'request.role.domain'}.'-domainconfig') &&
                   2285:                     ($udom eq $env{'request.role.domain'})) {
                   2286:                     delete($userlist->{$user});
                   2287:                     next;
                   2288:                 }
1.13      raeburn  2289:             } elsif ($env{'form.roletype'} eq 'author') {
1.2       raeburn  2290:                 ($uname,$udom,$role) = split(/:/,$user,-1);
                   2291:             } elsif ($env{'form.roletype'} eq 'course') {
                   2292:                 ($uname,$udom,$role) = split(/:/,$user);
                   2293:             }
                   2294:         } else {
                   2295:             ($uname,$udom,$role) = split(/:/,$user,-1);
                   2296:             if (($context eq 'course') && $role eq '') {
                   2297:                 $role = 'st';
                   2298:             }
                   2299:         }
                   2300:         $userlist->{$user}->[$index{'role'}] = $role;
                   2301:         if (($env{'form.showrole'} ne 'Any') && (!($env{'form.showrole'}  eq 'cr' && $role =~ /^cr\//)) && ($role ne $env{'form.showrole'})) {
                   2302:             delete($userlist->{$user});
                   2303:             next;
                   2304:         }
1.33      raeburn  2305:         if ($context eq 'course') {
                   2306:             my @ac_groups;
                   2307:             if (ref($classgroups) eq 'HASH') {
                   2308:                 $groups = $classgroups->{$user};
                   2309:             }
                   2310:             if (ref($groups->{'active'}) eq 'HASH') {
                   2311:                 @ac_groups = keys(%{$groups->{'active'}});
                   2312:                 $userlist->{$user}->[$index{'groups'}] = join(', ',@ac_groups);
                   2313:             }
                   2314:             if ($mode ne 'autoenroll') {
                   2315:                 my $section = $userlist->{$user}->[$index{'section'}];
1.43      raeburn  2316:                 if (($env{'request.course.sec'} ne '') && 
                   2317:                     ($section ne $env{'request.course.sec'})) {
                   2318:                     if ($role eq 'st') {
                   2319:                         delete($userlist->{$user});
                   2320:                         next;
                   2321:                     }
                   2322:                 }
1.33      raeburn  2323:                 if ($secfilter eq 'none') {
                   2324:                     if ($section ne '') {
                   2325:                         delete($userlist->{$user});
                   2326:                         next;
                   2327:                     }
                   2328:                 } elsif ($secfilter ne 'all') {
                   2329:                     if ($section ne $secfilter) {
                   2330:                         delete($userlist->{$user});
                   2331:                         next;
                   2332:                     }
                   2333:                 }
                   2334:                 if ($grpfilter eq 'none') {
                   2335:                     if (@ac_groups > 0) {
                   2336:                         delete($userlist->{$user});
                   2337:                         next;
                   2338:                     }
                   2339:                 } elsif ($grpfilter ne 'all') {
                   2340:                     if (!grep(/^\Q$grpfilter\E$/,@ac_groups)) {
                   2341:                         delete($userlist->{$user});
                   2342:                         next;
                   2343:                     }
                   2344:                 }
1.44      raeburn  2345:                 if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
                   2346:                     if (($displayphotos eq 'on') && ($role eq 'st')) {
                   2347:                         $userlist->{$user}->[$index{'photo'}] =
                   2348:                             &Apache::lonnet::retrievestudentphoto($udom,$uname,
                   2349:                                                                 'gif','thumbnail');
                   2350:                     }
                   2351:                 }
1.33      raeburn  2352:             }
1.2       raeburn  2353:         }
                   2354:         my %emails   = &Apache::loncommon::getemails($uname,$udom);
                   2355:         if ($emails{'permanentemail'} =~ /\S/) {
                   2356:             $userlist->{$user}->[$index{'email'}] = $emails{'permanentemail'};
                   2357:         }
1.4       raeburn  2358:         $usercount ++;
                   2359:     }
                   2360:     my $autocount = 0;
                   2361:     my $manualcount = 0;
                   2362:     my $lockcount = 0;
                   2363:     my $unlockcount = 0;
                   2364:     if ($usercount) {
                   2365:         $r->print($output);
                   2366:     } else {
                   2367:         if ($mode eq 'autoenroll') {
                   2368:             return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
                   2369:         } else {
                   2370:             return;
                   2371:         }
1.1       raeburn  2372:     }
1.2       raeburn  2373:     #
                   2374:     # Sort the users
1.1       raeburn  2375:     my $index  = $index{$sortby};
                   2376:     my $second = $index{'username'};
                   2377:     my $third  = $index{'domain'};
1.2       raeburn  2378:     my @sorted_users = sort {
                   2379:         lc($userlist->{$a}->[$index])  cmp lc($userlist->{$b}->[$index])
1.1       raeburn  2380:             ||
1.2       raeburn  2381:         lc($userlist->{$a}->[$second]) cmp lc($userlist->{$b}->[$second])            ||
                   2382:         lc($userlist->{$a}->[$third]) cmp lc($userlist->{$b}->[$third])
                   2383:         } (keys(%$userlist));
1.4       raeburn  2384:     my $rowcount = 0;
1.2       raeburn  2385:     foreach my $user (@sorted_users) {
1.4       raeburn  2386:         my %in;
1.2       raeburn  2387:         my $sdata = $userlist->{$user};
1.4       raeburn  2388:         $rowcount ++; 
1.2       raeburn  2389:         foreach my $item (@{$keylist}) {
                   2390:             $in{$item} = $sdata->[$index{$item}];
                   2391:         }
1.11      raeburn  2392:         my $role = $in{'role'};
1.2       raeburn  2393:         $in{'role'}=&Apache::lonnet::plaintext($sdata->[$index{'role'}]); 
                   2394:         if (! defined($in{'start'}) || $in{'start'} == 0) {
                   2395:             $in{'start'} = &mt('none');
                   2396:         } else {
                   2397:             $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
1.1       raeburn  2398:         }
1.2       raeburn  2399:         if (! defined($in{'end'}) || $in{'end'} == 0) {
                   2400:             $in{'end'} = &mt('none');
1.1       raeburn  2401:         } else {
1.2       raeburn  2402:             $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
1.1       raeburn  2403:         }
1.2       raeburn  2404:         if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') {
                   2405:             $r->print(&Apache::loncommon::start_data_table_row());
1.11      raeburn  2406:             my $checkval;
1.16      raeburn  2407:             if ($mode eq 'autoenroll') {
                   2408:                 my $cellentry;
                   2409:                 if ($in{'type'} eq 'auto') {
                   2410:                     $cellentry = '<b>'.&mt('auto').'</b>&nbsp;<label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'" />&nbsp;Change</label>';
                   2411:                     $autocount ++;
                   2412:                 } else {
                   2413:                     $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><nobr><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'" />&nbsp;Change</label></nobr></td></tr><tr><td><nobr>';
                   2414:                     $manualcount ++;
                   2415:                     if ($in{'lockedtype'}) {
                   2416:                         $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" />&nbsp;'.&mt('Unlock').'</label>';
                   2417:                         $unlockcount ++;
                   2418:                     } else {
                   2419:                         $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" />&nbsp;'.&mt('Lock').'</label>';
                   2420:                         $lockcount ++;
1.11      raeburn  2421:                     }
1.16      raeburn  2422:                     $cellentry .= '</nobr></td></tr></table>';
                   2423:                 }
                   2424:                 $r->print("<td>$cellentry</td>\n");
                   2425:             } else {
                   2426:                 $r->print("<td>$rowcount</td>\n");
                   2427:                 if ($actionselect) {
1.26      raeburn  2428:                     my $showcheckbox;
                   2429:                     if ($role =~ /^cr\//) {
                   2430:                         $showcheckbox = $canchange{'cr'};
                   2431:                     } else {
                   2432:                         $showcheckbox = $canchange{$role};
                   2433:                     }
                   2434:                     if (!$showcheckbox) {
                   2435:                         if ($context eq 'course') {
                   2436:                             if ($canchangesec{$role} ne '') {
                   2437:                                 if ($canchangesec{$role} eq $in{'section'}) {
                   2438:                                     $showcheckbox = 1;
                   2439:                                 }
                   2440:                             }
1.16      raeburn  2441:                         }
1.26      raeburn  2442:                     }
                   2443:                     if ($showcheckbox) {
                   2444:                         $checkval = $user; 
                   2445:                         if ($context eq 'course') {
                   2446:                             if ($role eq 'st') {
                   2447:                                 $checkval .= ':st';
                   2448:                             }
                   2449:                             $checkval .= ':'.$in{'section'};
                   2450:                             if ($role eq 'st') {
                   2451:                                 $checkval .= ':'.$in{'type'}.':'.
                   2452:                                              $in{'lockedtype'};
                   2453:                             }
1.16      raeburn  2454:                         }
1.26      raeburn  2455:                         $r->print('<td><input type="checkbox" name="'.
                   2456:                                   'actionlist" value="'.$checkval.'"></td>');
                   2457:                     } else {
                   2458:                         $r->print('<td>&nbsp;</td>');
1.16      raeburn  2459:                     }
1.11      raeburn  2460:                 }
                   2461:             }
1.2       raeburn  2462:             foreach my $item (@cols) {
1.10      raeburn  2463:                 if ($item eq 'username') {
1.16      raeburn  2464:                     $r->print('<td>'.&print_username_link($mode,$permission,
                   2465:                                                           \%in).'</td>');
                   2466:                 } elsif (($item eq 'start' || $item eq 'end') && ($actionselect)) {
1.11      raeburn  2467:                     $r->print('<td>'.$in{$item}.'<input type="hidden" name="'.$checkval.'_'.$item.'" value="'.$sdata->[$index{$item}].'" /></td>'."\n");
1.10      raeburn  2468:                 } else {
                   2469:                     $r->print('<td>'.$in{$item}.'</td>'."\n");
                   2470:                 }
1.2       raeburn  2471:             }
1.16      raeburn  2472:             if (($context eq 'course') && ($mode ne 'autoenroll')) {
1.4       raeburn  2473:                 if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
                   2474:                     if ($displayclickers eq 'on') {
                   2475:                         my $clickers =
1.2       raeburn  2476:                    (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
1.4       raeburn  2477:                         if ($clickers!~/\w/) { $clickers='-'; }
                   2478:                         $r->print('<td>'.$clickers.'</td>');
1.2       raeburn  2479:                     } else {
                   2480:                         $r->print('    <td>&nbsp;</td>  ');
                   2481:                     }
1.4       raeburn  2482:                     if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
1.44      raeburn  2483:                         if ($displayphotos eq 'on' && $role eq 'st' && $in{'photo'} ne '') {
                   2484:                             $r->print('    <td align="right"><a href="javascript:photowindow('."'".&Apache::lonnet::studentphoto($in{'domain'},$in{'username'},'jpg')."'".')"><img src="'.$in{'photo'}.'" border="1"></a></td>');
1.4       raeburn  2485:                         } else {
                   2486:                             $r->print('    <td>&nbsp;</td>  ');
                   2487:                         }
                   2488:                     }
1.2       raeburn  2489:                 }
                   2490:             }
                   2491:             $r->print(&Apache::loncommon::end_data_table_row());
                   2492:         } elsif ($mode eq 'csv') {
                   2493:             next if (! defined($CSVfile));
                   2494:             # no need to bother with $linkto
                   2495:             if (! defined($in{'start'}) || $in{'start'} == 0) {
                   2496:                 $in{'start'} = &mt('none');
                   2497:             } else {
                   2498:                 $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
                   2499:             }
                   2500:             if (! defined($in{'end'}) || $in{'end'} == 0) {
                   2501:                 $in{'end'} = &mt('none');
                   2502:             } else {
                   2503:                 $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
                   2504:             }
                   2505:             my @line = ();
                   2506:             foreach my $item (@cols) {
                   2507:                 push @line,&Apache::loncommon::csv_translate($in{$item});
                   2508:             }
                   2509:             print $CSVfile '"'.join('","',@line).'"'."\n";
                   2510:         } elsif ($mode eq 'excel') {
                   2511:             my $col = 0;
                   2512:             foreach my $item (@cols) {
                   2513:                 if ($item eq 'start' || $item eq 'end') {
                   2514:                     if (defined($item) && $item != 0) {
                   2515:                         $excel_sheet->write($row,$col++,
                   2516:                             &Apache::lonstathelpers::calc_serial($in{item}),
                   2517:                                     $format->{'date'});
                   2518:                     } else {
                   2519:                         $excel_sheet->write($row,$col++,'none');
                   2520:                     }
                   2521:                 } else {
                   2522:                     $excel_sheet->write($row,$col++,$in{$item});
                   2523:                 }
                   2524:             }
                   2525:             $row++;
1.1       raeburn  2526:         }
                   2527:     }
1.2       raeburn  2528:     if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') {
                   2529:             $r->print(&Apache::loncommon::end_data_table().'<br />');
                   2530:     } elsif ($mode eq 'excel') {
                   2531:         $excel_workbook->close();
                   2532:         $r->print('<p><a href="'.$excel_filename.'">'.
                   2533:                   &mt('Your Excel spreadsheet').'</a> '.&mt('is ready for download').'.</p>'."\n");
                   2534:     } elsif ($mode eq 'csv') {
                   2535:         close($CSVfile);
                   2536:         $r->print('<a href="'.$CSVfilename.'">'.
                   2537:                   &mt('Your CSV file').'</a> is ready for download.'.
                   2538:                   "\n");
                   2539:         $r->rflush();
                   2540:     }
                   2541:     if ($mode eq 'autoenroll') {
                   2542:         return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
1.4       raeburn  2543:     } else {
                   2544:         return ($usercount);
1.2       raeburn  2545:     }
1.1       raeburn  2546: }
                   2547: 
1.10      raeburn  2548: sub print_username_link {
1.16      raeburn  2549:     my ($mode,$permission,$in) = @_;
1.10      raeburn  2550:     my $output;
1.16      raeburn  2551:     if ($mode eq 'autoenroll') {
                   2552:         $output = $in->{'username'};
                   2553:     } elsif (!$permission->{'cusr'}) {
1.10      raeburn  2554:         $output = &Apache::loncommon::aboutmewrapper($in->{'username'},
                   2555:                                                      $in->{'username'},
                   2556:                                                      $in->{'domain'});
                   2557:     } else {
                   2558:         $output = '<a href="javascript:username_display_launch('.
                   2559:                   "'$in->{'username'}','$in->{'domain'}'".')" />'.
                   2560:                   $in->{'username'}.'</a>';
                   2561:     }
                   2562:     return $output;
                   2563: }
                   2564: 
1.2       raeburn  2565: sub role_type_names {
                   2566:     my %lt = &Apache::lonlocal::texthash (
1.13      raeburn  2567:                          'domain' => 'Domain Roles',
                   2568:                          'author' => 'Co-Author Roles',
                   2569:                          'course' => 'Course Roles',
1.2       raeburn  2570:              );
                   2571:     return %lt;
                   2572: }
                   2573: 
1.11      raeburn  2574: sub select_actions {
                   2575:     my ($context,$setting,$statusmode) = @_;
                   2576:     my %lt = &Apache::lonlocal::texthash(
                   2577:                 revoke   => "Revoke user roles",
                   2578:                 delete   => "Delete user roles",
                   2579:                 reenable => "Re-enable expired user roles",
                   2580:                 activate => "Make future user roles active now",
                   2581:                 chgdates  => "Change starting/ending dates",
                   2582:                 chgsec   => "Change section associated with user roles",
                   2583:     );
                   2584:     my ($output,$options,%choices);
1.23      raeburn  2585:     # FIXME Disable actions for now for roletype=course in domain context
                   2586:     if ($context eq 'domain' && $setting eq 'course') {
                   2587:         return;
                   2588:     }
1.26      raeburn  2589:     if ($context eq 'course') {
                   2590:         if ($env{'form.showrole'} ne 'Any') {
                   2591:              if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},
                   2592:                                            $env{'request.course.id'})) {
                   2593:                  if ($env{'request.course.sec'} eq '') {
                   2594:                      return;
                   2595:                  } else {
                   2596:                      if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
                   2597:                          return;
                   2598:                      }
                   2599:                  }
                   2600:             }
                   2601:         }
                   2602:     }
1.11      raeburn  2603:     if ($statusmode eq 'Any') {
                   2604:         $options .= '
                   2605: <option value="chgdates">'.$lt{'chgdates'}.'</option>';
                   2606:         $choices{'dates'} = 1;
                   2607:     } else {
                   2608:         if ($statusmode eq 'Future') {
                   2609:             $options .= '
                   2610: <option value="activate">'.$lt{'activate'}.'</option>';
                   2611:             $choices{'dates'} = 1;
                   2612:         } elsif ($statusmode eq 'Expired') {
                   2613:             $options .= '
                   2614: <option value="reenable">'.$lt{'reenable'}.'</option>';
                   2615:             $choices{'dates'} = 1;
                   2616:         }
1.13      raeburn  2617:         if ($statusmode eq 'Active' || $statusmode eq 'Future') {
                   2618:             $options .= '
                   2619: <option value="chgdates">'.$lt{'chgdates'}.'</option>
                   2620: <option value="revoke">'.$lt{'revoke'}.'</option>';
                   2621:             $choices{'dates'} = 1;
                   2622:         }
1.11      raeburn  2623:     }
                   2624:     if ($context eq 'domain') {
                   2625:         $options .= '
                   2626: <option value="delete">'.$lt{'delete'}.'</option>';
                   2627:     }
                   2628:     if (($context eq 'course') || ($context eq 'domain' && $setting eq 'course')) {
1.26      raeburn  2629:         if (($statusmode ne 'Expired') && ($env{'request.course.sec'} eq '')) {
1.11      raeburn  2630:             $options .= '
                   2631: <option value="chgsec">'.$lt{'chgsec'}.'</option>';
                   2632:             $choices{'sections'} = 1;
                   2633:         }
                   2634:     }
                   2635:     if ($options) {
1.41      raeburn  2636:         $output = '<select name="bulkaction" onchange="javascript:opendatebrowser(this.form,'."'studentform','change'".')" />'."\n".
1.11      raeburn  2637:                   '<option value="" selected="selected">'.
                   2638:                   &mt('Please select').'</option>'."\n".$options."\n".'</select>';
                   2639:         if ($choices{'dates'}) {
                   2640:             $output .= 
                   2641:                 '<input type="hidden" name="startdate_month" value="" />'."\n".
                   2642:                 '<input type="hidden" name="startdate_day" value="" />'."\n".
                   2643:                 '<input type="hidden" name="startdate_year" value="" />'."\n".
                   2644:                 '<input type="hidden" name="startdate_hour" value="" />'."\n".
                   2645:                 '<input type="hidden" name="startdate_minute" value="" />'."\n".
                   2646:                 '<input type="hidden" name="startdate_second" value="" />'."\n".
                   2647:                 '<input type="hidden" name="enddate_month" value="" />'."\n".
                   2648:                 '<input type="hidden" name="enddate_day" value="" />'."\n".
                   2649:                 '<input type="hidden" name="enddate_year" value="" />'."\n".
                   2650:                 '<input type="hidden" name="enddate_hour" value="" />'."\n".
                   2651:                 '<input type="hidden" name="enddate_minute" value="" />'."\n".
                   2652:                 '<input type="hidden" name="enddate_second" value="" />'."\n";
                   2653:             if ($context eq 'course') {
                   2654:                 $output .= '<input type="hidden" name="makedatesdefault" value="" />'."\n";
                   2655:             }
                   2656:         }
                   2657:         if ($choices{'sections'}) {
                   2658:             $output .= '<input type="hidden" name="retainsec" value= "" />'."\n".
                   2659:                        '<input type="hidden" name="newsecs" value= "" />'."\n";
                   2660:         }
                   2661:     }
                   2662:     return $output;
                   2663: }
                   2664: 
                   2665: sub date_section_javascript {
                   2666:     my ($context,$setting) = @_;
                   2667:     my $title;
                   2668:     if (($context eq 'course') || ($context eq 'domain' && $setting eq 'course'))  {
                   2669:         $title = &mt('Date and Section selector');
                   2670:     } else {
                   2671:         $title = &mt('Date selector');
                   2672:     }
1.41      raeburn  2673:     my %nopopup = &Apache::lonlocal::texthash (
                   2674:         revoke => "Check the boxes for any users for whom roles are to be revoked, and click 'Proceed'",
                   2675:         delete => "Check the boxes for any users for whom roles are to be deleted, and click 'Proceed'",
                   2676:         none   => "Choose an action to take for selected users",
                   2677:     );  
1.11      raeburn  2678:     my $output = '
                   2679: <script type="text/javascript">
                   2680:     var stdeditbrowser;'."\n";
                   2681:     $output .= <<"ENDONE";
1.41      raeburn  2682:     function opendatebrowser(callingform,formname,calledby) {
1.11      raeburn  2683:         var bulkaction = callingform.bulkaction.options[callingform.bulkaction.selectedIndex].value;
                   2684:         if (bulkaction == 'revoke' || bulkaction == 'delete' || bulkaction == '') {
1.41      raeburn  2685:             if (calledby == 'go') {
                   2686:                 if (bulkaction == 'revoke') {
                   2687:                     alert("$nopopup{'revoke'}");
                   2688:                 }
                   2689:                 if (bulkaction == 'delete') {
                   2690:                     alert("$nopopup{'delete'}"); 
                   2691:                 }
                   2692:                 if (bulkaction == '') {
                   2693:                     alert("$nopopup{'none'}");
                   2694:                 }
                   2695:             }
1.11      raeburn  2696:             return;
                   2697:         }
                   2698:         var url = '/adm/createuser?';
                   2699:         var type = '';
                   2700:         var showrole = callingform.showrole.options[callingform.showrole.selectedIndex].value;
                   2701: ENDONE
                   2702:     if ($context eq 'domain') {
                   2703:         $output .= '
                   2704:         type = callingform.roletype.options[callingform.roletype.selectedIndex].value;
                   2705: ';
                   2706:     }
                   2707:     my $width= '700';
                   2708:     my $height = '400';
                   2709:     $output .= <<"ENDTWO";
                   2710:         url += 'action=dateselect&callingform=' + formname + 
                   2711:                '&roletype='+type+'&showrole='+showrole +'&bulkaction='+bulkaction;
                   2712:         var title = '$title';
                   2713:         var options = 'scrollbars=1,resizable=1,menubar=0';
                   2714:         options += ',width=$width,height=$height';
                   2715:         stdeditbrowser = open(url,title,options,'1');
                   2716:         stdeditbrowser.focus();
                   2717:     }
                   2718: </script>
                   2719: ENDTWO
                   2720:     return $output;
                   2721: }
                   2722: 
                   2723: sub date_section_selector {
1.21      raeburn  2724:     my ($context,$permission) = @_;
1.11      raeburn  2725:     my $callingform = $env{'form.callingform'};
                   2726:     my $formname = 'dateselect';  
                   2727:     my $groupslist = &get_groupslist();
                   2728:     my $sec_js = &setsections_javascript($formname,$groupslist);
                   2729:     my $output = <<"END";
                   2730: <script type="text/javascript">
                   2731: 
                   2732: $sec_js
                   2733: 
                   2734: function saveselections(formname) {
                   2735: 
                   2736: END
                   2737:     if ($env{'form.bulkaction'} eq 'chgsec') {
                   2738:         $output .= <<"END";
1.40      raeburn  2739:         if (formname.retainsec.length > 1) {  
                   2740:             for (var i=0; i<formname.retainsec.length; i++) {
                   2741:                 if (formname.retainsec[i].checked == true) {
                   2742:                     opener.document.$callingform.retainsec.value = formname.retainsec[i].value;
                   2743:                 }
                   2744:             }
                   2745:         } else {
                   2746:             opener.document.$callingform.retainsec.value = formname.retainsec.value;
                   2747:         }
1.11      raeburn  2748:         setSections(formname);
                   2749:         if (seccheck == 'ok') {
                   2750:             opener.document.$callingform.newsecs.value = formname.sections.value;
                   2751:             window.close();
                   2752:         }
                   2753:         return;
                   2754: END
                   2755:     } else {
                   2756:         if ($context eq 'course') {
                   2757:             if (($env{'form.bulkaction'} eq 'reenable') || 
                   2758:                 ($env{'form.bulkaction'} eq 'activate') || 
                   2759:                 ($env{'form.bulkaction'} eq 'chgdates')) {
1.26      raeburn  2760:                 if ($env{'request.course.sec'} eq '') {
                   2761:                     $output .= <<"END";
1.11      raeburn  2762:  
                   2763:         if (formname.makedatesdefault.checked == true) {
                   2764:             opener.document.$callingform.makedatesdefault.value = 1;
                   2765:         }
                   2766:         else {
                   2767:             opener.document.$callingform.makedatesdefault.value = 0;
                   2768:         }
                   2769: 
                   2770: END
1.26      raeburn  2771:                 }
1.11      raeburn  2772:             }
                   2773:         }
                   2774:         $output .= <<"END";
                   2775:     opener.document.$callingform.startdate_month.value =  formname.startdate_month.options[formname.startdate_month.selectedIndex].value;
                   2776:     opener.document.$callingform.startdate_day.value =  formname.startdate_day.value;
                   2777:     opener.document.$callingform.startdate_year.value = formname.startdate_year.value;
                   2778:     opener.document.$callingform.startdate_hour.value =  formname.startdate_hour.options[formname.startdate_hour.selectedIndex].value;
                   2779:     opener.document.$callingform.startdate_minute.value =  formname.startdate_minute.value;
                   2780:     opener.document.$callingform.startdate_second.value = formname.startdate_second.value;
                   2781:     opener.document.$callingform.enddate_month.value =  formname.enddate_month.options[formname.enddate_month.selectedIndex].value;
                   2782:     opener.document.$callingform.enddate_day.value =  formname.enddate_day.value;
                   2783:     opener.document.$callingform.enddate_year.value = formname.enddate_year.value;
                   2784:     opener.document.$callingform.enddate_hour.value =  formname.enddate_hour.options[formname.enddate_hour.selectedIndex].value;
                   2785:     opener.document.$callingform.enddate_minute.value =  formname.enddate_minute.value;
                   2786:     opener.document.$callingform.enddate_second.value = formname.enddate_second.value;
                   2787:     window.close();
                   2788: END
                   2789:     }
                   2790:     $output .= '
                   2791: }
                   2792: </script>
                   2793: ';
                   2794:     my %lt = &Apache::lonlocal::texthash (
                   2795:                  chac => 'Access dates to apply for selected users',
                   2796:                  chse => 'Changes in section affiliation to apply to selected users',
                   2797:                  fors => 'For student roles changing the section, will result in a section switch as students may only be in one section of a course at a time.',
                   2798:                  forn => 'For a role in a course that is not a student role, a user may have roles in more than one section of a course at a time.',
                   2799:                  reta => "Retain each user's current section affiliations?", 
                   2800:                  dnap => '(Does not apply to student roles).', 
                   2801:             );
                   2802:     my ($date_items,$headertext);
                   2803:     if ($env{'form.bulkaction'} eq 'chgsec') {
                   2804:         $headertext = $lt{'chse'};
                   2805:     } else {
                   2806:         $headertext = $lt{'chac'};
                   2807:         my $starttime;
                   2808:         if (($env{'form.bulkaction'} eq 'activate') || 
                   2809:             ($env{'form.bulkaction'} eq 'reenable')) {
                   2810:             $starttime = time;
                   2811:         }
                   2812:         $date_items = &date_setting_table($starttime,undef,$context,
1.21      raeburn  2813:                                           $env{'form.bulkaction'},$formname,
                   2814:                                           $permission);
1.11      raeburn  2815:     }
                   2816:     $output .= '<h3>'.$headertext.'</h3>'.
                   2817:                '<form name="'.$formname.'" method="post">'."\n".
                   2818:                 $date_items;
                   2819:     if ($context eq 'course' && $env{'form.bulkaction'} eq 'chgsec') {
1.17      raeburn  2820:         my ($cnum,$cdom) = &get_course_identity();
1.11      raeburn  2821:         my $info;
                   2822:         if ($env{'form.showrole'} eq 'st') {
                   2823:             $output .= '<p>'.$lt{'fors'}.'</p>'; 
1.26      raeburn  2824:         } elsif ($env{'form.showrole'} eq 'Any') {
1.11      raeburn  2825:             $output .= '<p>'.$lt{'fors'}.'</p>'.
                   2826:                        '<p>'.$lt{'forn'}.'&nbsp;';
                   2827:             $info = $lt{'reta'};
                   2828:         } else {
                   2829:             $output .= '<p>'.$lt{'forn'}.'&nbsp;';
                   2830:             $info = $lt{'reta'};
                   2831:         }
                   2832:         if ($info) {
                   2833:             $info .= '<span class="LC_nobreak">'.
                   2834:                      '<label><input type="radio" name="retainsec" value="1" '.
                   2835:                      'checked="checked" />'.&mt('Yes').'</label>&nbsp;&nbsp;'.
                   2836:                      '<label><input type="radio" name="retainsec" value="0" />'.
                   2837:                      &mt('No').'</label></span>';
                   2838:             if ($env{'form.showrole'} eq 'Any') {
                   2839:                 $info .= '<br />'.$lt{'dnap'};
                   2840:             }
                   2841:             $info .= '</p>';
                   2842:         } else {
                   2843:             $info = '<input type="hidden" name="retainsec" value="0" />'; 
                   2844:         }
1.21      raeburn  2845:         my $rowtitle = &mt('New section to assign');
                   2846:         my $secbox = &section_picker($cdom,$cnum,$env{'form.showrole'},$rowtitle,$permission,$context);
1.11      raeburn  2847:         $output .= $info.$secbox;
                   2848:     }
                   2849:     $output .= '<p>'.
                   2850: &mt('Use "Save" to update the main window with your selections.').'<br /><br />'.
                   2851: '<input type="button" name="dateselection" value="'.&mt('Save').'" onclick="javascript:saveselections(this.form)" /></p>'."\n".
                   2852: '</form>';
                   2853:     return $output;
                   2854: }
                   2855: 
1.17      raeburn  2856: sub section_picker {
                   2857:     my ($cdom,$cnum,$role,$rowtitle,$permission,$context,$mode) = @_;
                   2858:     my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
                   2859:     my $sections_select .= &course_sections(\%sections_count,$role);
                   2860:     my $secbox = '<p>'.&Apache::lonhtmlcommon::start_pick_box()."\n";
                   2861:     if ($mode eq 'upload') {
                   2862:         my ($options,$cb_script,$coursepick) =
                   2863:             &default_role_selector($context,1);
                   2864:         $secbox .= &Apache::lonhtmlcommon::row_title('role','LC_oddrow_value').
                   2865:                    $options. &Apache::lonhtmlcommon::row_closure(1)."\n";
                   2866:     }
                   2867:     $secbox .= &Apache::lonhtmlcommon::row_title($rowtitle,'LC_oddrow_value')."\n";
                   2868:     if ($env{'request.course.sec'} eq '') {
                   2869:         $secbox .= '<table class="LC_createuser"><tr class="LC_section_row">'."\n".
                   2870:                    '<td align="center">'.&mt('Existing sections')."\n".
                   2871:                    '<br />'.$sections_select.'</td><td align="center">'.
                   2872:                    &mt('New section').'<br />'."\n".
                   2873:                    '<input type="text" name="newsec" size="15" />'."\n".
                   2874:                    '<input type="hidden" name="sections" value="" />'."\n".
                   2875:                    '</td></tr></table>'."\n";
                   2876:     } else {
                   2877:        $secbox .= '<input type="hidden" name="sections" value="'.
                   2878:                    $env{'request.course.sec'}.'" />'.
                   2879:                    $env{'request.course.sec'};
                   2880:     }
                   2881:     $secbox .= &Apache::lonhtmlcommon::row_closure(1)."\n".
                   2882:                &Apache::lonhtmlcommon::end_pick_box().'</p>';
                   2883:     return $secbox;
                   2884: }
                   2885: 
1.2       raeburn  2886: sub results_header_row {
1.24      raeburn  2887:     my ($rolefilter,$statusmode,$context,$permission,$mode) = @_;
1.5       raeburn  2888:     my ($description,$showfilter);
                   2889:     if ($rolefilter ne 'Any') {
                   2890:         $showfilter = $rolefilter;
                   2891:     }
1.2       raeburn  2892:     if ($context eq 'course') {
1.24      raeburn  2893:         if ($mode eq 'csv' || $mode eq 'excel') {
                   2894:             $description = &mt('Course - ').$env{'course.'.$env{'request.course.id'}.'.description'}.': ';
                   2895:         }
1.2       raeburn  2896:         if ($statusmode eq 'Expired') {
1.5       raeburn  2897:             $description .= &mt('Users in course with expired [_1] roles',$showfilter);
1.11      raeburn  2898:         } elsif ($statusmode eq 'Future') {
1.5       raeburn  2899:             $description .= &mt('Users in course with future [_1] roles',$showfilter);
1.2       raeburn  2900:         } elsif ($statusmode eq 'Active') {
1.5       raeburn  2901:             $description .= &mt('Users in course with active [_1] roles',$showfilter);
1.2       raeburn  2902:         } else {
                   2903:             if ($rolefilter eq 'Any') {
                   2904:                 $description .= &mt('All users in course');
                   2905:             } else {
                   2906:                 $description .= &mt('All users in course with [_1] roles',$rolefilter);
                   2907:             }
                   2908:         }
1.33      raeburn  2909:         my $constraint;
1.26      raeburn  2910:         my $viewablesec = &viewable_section($permission);
                   2911:         if ($viewablesec ne '') {
1.15      raeburn  2912:             if ($env{'form.showrole'} eq 'st') {
1.33      raeburn  2913:                 $constraint = &mt('only users in section "[_1]"',$viewablesec);
1.26      raeburn  2914:             } elsif ($env{'form.showrole'} ne 'cc') {
1.33      raeburn  2915:                 $constraint = &mt('only users affiliated with no section or section "[_1]"',$viewablesec);
                   2916:             }
                   2917:             if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
                   2918:                 if ($env{'form.grpfilter'} eq 'none') {
                   2919:                     $constraint .= &mt(' and not in any group');
                   2920:                 } else {
                   2921:                     $constraint .= &mt(' and members of group: "[_1]"',$env{'form.grpfilter'});
                   2922:                 }
                   2923:             }
                   2924:         } else {
                   2925:             if (($env{'form.secfilter'} ne 'all') && ($env{'form.secfilter'} ne '')) {
                   2926:                 if ($env{'form.secfilter'} eq 'none') {
                   2927:                     $constraint = &mt('only users affiliated with no section');
                   2928:                 } else {
                   2929:                     $constraint = &mt('only users affiliated with section "[_1]"',$env{'form.secfilter'});
                   2930:                 }
                   2931:             }
                   2932:             if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
                   2933:                 if ($env{'form.grpfilter'} eq 'none') {
                   2934:                     if ($constraint eq '') {
                   2935:                         $constraint = &mt('only users not in any group');
                   2936:                     } else {
                   2937:                         $constraint .= &mt(' and also not in any group'); 
                   2938:                     }
                   2939:                 } else {
                   2940:                     if ($constraint eq '') {
                   2941:                         $constraint = &mt('only members of group: "[_1]"',$env{'form.grpfilter'});
                   2942:                     } else {
                   2943:                         $constraint .= &mt(' and also members of group: "[_1]"'.$env{'form.grpfilter'});
                   2944:                     }
                   2945:                 }
1.15      raeburn  2946:             }
                   2947:         }
1.33      raeburn  2948:         if ($constraint ne '') {
                   2949:             $description .= ' ('.$constraint.')';
                   2950:         } 
1.13      raeburn  2951:     } elsif ($context eq 'author') {
1.14      raeburn  2952:         $description = 
                   2953:             &mt('Author space for <span class="LC_cusr_emph">[_1]</span>',
                   2954:         &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'})).':&nbsp;&nbsp;';
1.2       raeburn  2955:         if ($statusmode eq 'Expired') {
1.5       raeburn  2956:             $description .= &mt('Co-authors with expired [_1] roles',$showfilter);
1.2       raeburn  2957:         } elsif ($statusmode eq 'Future') {
1.5       raeburn  2958:             $description .= &mt('Co-authors with future [_1] roles',$showfilter);
1.2       raeburn  2959:         } elsif ($statusmode eq 'Active') {
1.5       raeburn  2960:             $description .= &mt('Co-authors with active [_1] roles',$showfilter);
1.2       raeburn  2961:         } else {
                   2962:             if ($rolefilter eq 'Any') {
1.5       raeburn  2963:                 $description .= &mt('All co-authors');
1.2       raeburn  2964:             } else {
                   2965:                 $description .= &mt('All co-authors with [_1] roles',$rolefilter);
                   2966:             }
                   2967:         }
                   2968:     } elsif ($context eq 'domain') {
                   2969:         my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description');
                   2970:         $description = &mt('Domain - ').$domdesc.': ';
                   2971:         if ($env{'form.roletype'} eq 'domain') {
                   2972:             if ($statusmode eq 'Expired') {
1.5       raeburn  2973:                 $description .= &mt('Users in domain with expired [_1] roles',$showfilter);
1.2       raeburn  2974:             } elsif ($statusmode eq 'Future') {
1.5       raeburn  2975:                 $description .= &mt('Users in domain with future [_1] roles',$showfilter);
1.2       raeburn  2976:             } elsif ($statusmode eq 'Active') {
1.5       raeburn  2977:                 $description .= &mt('Users in domain with active [_1] roles',$showfilter);
1.2       raeburn  2978:             } else {
                   2979:                 if ($rolefilter eq 'Any') {
1.5       raeburn  2980:                     $description .= &mt('All users in domain');
1.2       raeburn  2981:                 } else {
                   2982:                     $description .= &mt('All users in domain with [_1] roles',$rolefilter);
                   2983:                 }
                   2984:             }
1.13      raeburn  2985:         } elsif ($env{'form.roletype'} eq 'author') {
1.2       raeburn  2986:             if ($statusmode eq 'Expired') {
1.5       raeburn  2987:                 $description .= &mt('Co-authors in domain with expired [_1] roles',$showfilter);
1.2       raeburn  2988:             } elsif ($statusmode eq 'Future') {
1.5       raeburn  2989:                 $description .= &mt('Co-authors in domain with future [_1] roles',$showfilter);
1.2       raeburn  2990:             } elsif ($statusmode eq 'Active') {
1.5       raeburn  2991:                $description .= &mt('Co-authors in domain with active [_1] roles',$showfilter);
1.2       raeburn  2992:             } else {
                   2993:                 if ($rolefilter eq 'Any') {
1.5       raeburn  2994:                     $description .= &mt('All users with co-author roles in domain',$showfilter);
1.2       raeburn  2995:                 } else {
                   2996:                     $description .= &mt('All co-authors in domain  with [_1] roles',$rolefilter);
                   2997:                 }
                   2998:             }
                   2999:         } elsif ($env{'form.roletype'} eq 'course') {
                   3000:             my $coursefilter = $env{'form.coursepick'};
                   3001:             if ($coursefilter eq 'category') {
                   3002:                 my $instcode = &instcode_from_coursefilter();
                   3003:                 if ($instcode eq '.') {
                   3004:                     $description .= &mt('All courses in domain').' - ';
                   3005:                 } else {
                   3006:                     $description .= &mt('Courses in domain with institutional code: [_1]',$instcode).' - ';
                   3007:                 }
                   3008:             } elsif ($coursefilter eq 'selected') {
                   3009:                 $description .= &mt('Selected courses in domain').' - ';
                   3010:             } elsif ($coursefilter eq 'all') {
                   3011:                 $description .= &mt('All courses in domain').' - ';
                   3012:             }
                   3013:             if ($statusmode eq 'Expired') {
1.5       raeburn  3014:                 $description .= &mt('users with expired [_1] roles',$showfilter);
1.2       raeburn  3015:             } elsif ($statusmode eq 'Future') {
1.5       raeburn  3016:                 $description .= &mt('users with future [_1] roles',$showfilter);
1.2       raeburn  3017:             } elsif ($statusmode eq 'Active') {
1.5       raeburn  3018:                 $description .= &mt('users with active [_1] roles',$showfilter);
1.2       raeburn  3019:             } else {
                   3020:                 if ($rolefilter eq 'Any') {
                   3021:                     $description .= &mt('all users');
                   3022:                 } else {
                   3023:                     $description .= &mt('users with [_1] roles',$rolefilter);
                   3024:                 }
                   3025:             }
                   3026:         }
                   3027:     }
                   3028:     return $description;
                   3029: }
1.22      raeburn  3030: 
                   3031: sub viewable_section {
                   3032:     my ($permission) = @_;
                   3033:     my $viewablesec;
                   3034:     if (ref($permission) eq 'HASH') {
                   3035:         if (exists($permission->{'view_section'})) {
                   3036:             $viewablesec = $permission->{'view_section'};
                   3037:         } elsif (exists($permission->{'cusr_section'})) {
                   3038:             $viewablesec = $permission->{'cusr_section'};
                   3039:         }
                   3040:     }
                   3041:     return $viewablesec;
                   3042: }
                   3043: 
1.2       raeburn  3044:     
1.1       raeburn  3045: #################################################
                   3046: #################################################
                   3047: sub show_drop_list {
1.30      raeburn  3048:     my ($r,$classlist,$nosort,$permission) = @_;
1.29      raeburn  3049:     my $cid = $env{'request.course.id'};
1.17      raeburn  3050:     my ($cnum,$cdom) = &get_course_identity($cid);
1.1       raeburn  3051:     if (! exists($env{'form.sortby'})) {
                   3052:         &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   3053:                                                 ['sortby']);
                   3054:     }
                   3055:     my $sortby = $env{'form.sortby'};
                   3056:     if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) {
                   3057:         $sortby = 'username';
                   3058:     }
                   3059:     my $action = "drop";
1.17      raeburn  3060:     my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
1.1       raeburn  3061:     $r->print(<<END);
                   3062: <input type="hidden" name="sortby" value="$sortby" />
                   3063: <input type="hidden" name="action" value="$action" />
                   3064: <input type="hidden" name="state"  value="done" />
1.17      raeburn  3065: <script type="text/javascript" language="Javascript">
                   3066: $check_uncheck_js
1.1       raeburn  3067: </script>
                   3068: <p>
                   3069: <input type="hidden" name="phase" value="four">
                   3070: END
1.30      raeburn  3071:     my ($indexhash,$keylist) = &make_keylist_array();
                   3072:     my $studentcount = 0;
                   3073:     if (ref($classlist) eq 'HASH') {
                   3074:         foreach my $student (keys(%{$classlist})) {
                   3075:             my $sdata = $classlist->{$student}; 
                   3076:             my $status = $sdata->[$indexhash->{'status'}];
                   3077:             my $section = $sdata->[$indexhash->{'section'}];
                   3078:             if ($status ne 'Active') {
                   3079:                 delete($classlist->{$student});
                   3080:                 next;
                   3081:             }
                   3082:             if ($env{'request.course.sec'} ne '') {
                   3083:                 if ($section ne $env{'request.course.sec'}) {
                   3084:                     delete($classlist->{$student});
                   3085:                     next;
                   3086:                 }
                   3087:             }
                   3088:             $studentcount ++;
                   3089:         }
                   3090:     }
                   3091:     if (!$studentcount) {
                   3092:         $r->print(&mt('There are no students to drop.'));
                   3093:         return;
                   3094:     }
                   3095:     my ($classgroups) = &Apache::loncoursedata::get_group_memberships(
                   3096:                                               $classlist,$keylist,$cdom,$cnum);
                   3097:     my %lt=&Apache::lonlocal::texthash('usrn'   => "username",
                   3098:                                        'dom'    => "domain",
                   3099:                                        'sn'     => "student name",
                   3100:                                        'sec'    => "section",
                   3101:                                        'start'  => "start date",
                   3102:                                        'end'    => "end date",
                   3103:                                        'groups' => "active groups",
                   3104:                                       );
1.1       raeburn  3105:     if ($nosort) {
1.17      raeburn  3106:         $r->print(&Apache::loncommon::start_data_table().
                   3107:                   &Apache::loncommon::start_data_table_header_row());
1.1       raeburn  3108:         $r->print(<<END);
                   3109:     <th>&nbsp;</th>
                   3110:     <th>$lt{'usrn'}</th>
                   3111:     <th>$lt{'dom'}</th>
                   3112:     <th>ID</th>
                   3113:     <th>$lt{'sn'}</th>
                   3114:     <th>$lt{'sec'}</th>
                   3115:     <th>$lt{'start'}</th>
                   3116:     <th>$lt{'end'}</th>
                   3117:     <th>$lt{'groups'}</th>
                   3118: END
1.17      raeburn  3119:         $r->print(&Apache::loncommon::end_data_table_header_row());
1.1       raeburn  3120:     } else  {
1.17      raeburn  3121:         $r->print(&Apache::loncommon::start_data_table().
                   3122:                   &Apache::loncommon::start_data_table_header_row());
1.1       raeburn  3123:         $r->print(<<END);
1.17      raeburn  3124:     <th>&nbsp;</th>
1.1       raeburn  3125:     <th>
1.17      raeburn  3126:        <a href="/adm/createuser?action=$action&sortby=username">$lt{'usrn'}</a>
1.1       raeburn  3127:     </th><th>
1.17      raeburn  3128:        <a href="/adm/createuser?action=$action&sortby=domain">$lt{'dom'}</a>
1.1       raeburn  3129:     </th><th>
1.17      raeburn  3130:        <a href="/adm/createuser?action=$action&sortby=id">ID</a>
1.1       raeburn  3131:     </th><th>
1.17      raeburn  3132:        <a href="/adm/createuser?action=$action&sortby=fullname">$lt{'sn'}</a>
1.1       raeburn  3133:     </th><th>
1.17      raeburn  3134:        <a href="/adm/createuser?action=$action&sortby=section">$lt{'sec'}</a>
1.1       raeburn  3135:     </th><th>
1.17      raeburn  3136:        <a href="/adm/createuser?action=$action&sortby=start">$lt{'start'}</a>
1.1       raeburn  3137:     </th><th>
1.17      raeburn  3138:        <a href="/adm/createuser?action=$action&sortby=end">$lt{'end'}</a>
1.1       raeburn  3139:     </th><th>
1.17      raeburn  3140:        <a href="/adm/createuser?action=$action&sortby=groups">$lt{'groups'}</a>
1.1       raeburn  3141:     </th>
                   3142: END
1.17      raeburn  3143:         $r->print(&Apache::loncommon::end_data_table_header_row());
1.1       raeburn  3144:     }
                   3145:     #
                   3146:     # Sort the students
1.30      raeburn  3147:     my $index  = $indexhash->{$sortby};
                   3148:     my $second = $indexhash->{'username'};
                   3149:     my $third  = $indexhash->{'domain'};
1.1       raeburn  3150:     my @Sorted_Students = sort {
                   3151:         lc($classlist->{$a}->[$index])  cmp lc($classlist->{$b}->[$index])
                   3152:             ||
                   3153:         lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
                   3154:             ||
                   3155:         lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
1.30      raeburn  3156:         } (keys(%{$classlist}));
1.1       raeburn  3157:     foreach my $student (@Sorted_Students) {
                   3158:         my $error;
                   3159:         my $sdata = $classlist->{$student};
1.30      raeburn  3160:         my $username = $sdata->[$indexhash->{'username'}];
                   3161:         my $domain   = $sdata->[$indexhash->{'domain'}];
                   3162:         my $section  = $sdata->[$indexhash->{'section'}];
                   3163:         my $name     = $sdata->[$indexhash->{'fullname'}];
                   3164:         my $id       = $sdata->[$indexhash->{'id'}];
                   3165:         my $start    = $sdata->[$indexhash->{'start'}];
                   3166:         my $end      = $sdata->[$indexhash->{'end'}];
1.1       raeburn  3167:         my $groups = $classgroups->{$student};
                   3168:         my $active_groups;
                   3169:         if (ref($groups->{active}) eq 'HASH') {
                   3170:             $active_groups = join(', ',keys(%{$groups->{'active'}}));
                   3171:         }
                   3172:         if (! defined($start) || $start == 0) {
                   3173:             $start = &mt('none');
                   3174:         } else {
                   3175:             $start = &Apache::lonlocal::locallocaltime($start);
                   3176:         }
                   3177:         if (! defined($end) || $end == 0) {
                   3178:             $end = &mt('none');
                   3179:         } else {
                   3180:             $end = &Apache::lonlocal::locallocaltime($end);
                   3181:         }
1.17      raeburn  3182:         my $studentkey = $student.':'.$section;
1.30      raeburn  3183:         my $startitem = '<input type="hidden" name="'.$studentkey.'_start" value="'.$sdata->[$indexhash->{'start'}].'" />';
1.1       raeburn  3184:         #
                   3185:         $r->print(&Apache::loncommon::start_data_table_row());
                   3186:         $r->print(<<"END");
1.29      raeburn  3187:     <td><input type="checkbox" name="droplist" value="$studentkey"></td>
1.1       raeburn  3188:     <td>$username</td>
                   3189:     <td>$domain</td>
                   3190:     <td>$id</td>
                   3191:     <td>$name</td>
                   3192:     <td>$section</td>
1.29      raeburn  3193:     <td>$start $startitem</td>
1.1       raeburn  3194:     <td>$end</td>
                   3195:     <td>$active_groups</td>
                   3196: END
                   3197:         $r->print(&Apache::loncommon::end_data_table_row());
                   3198:     }
                   3199:     $r->print(&Apache::loncommon::end_data_table().'<br />');
                   3200:     %lt=&Apache::lonlocal::texthash(
1.29      raeburn  3201:                        'dp'   => "Drop Students",
1.1       raeburn  3202:                        'ca'   => "check all",
                   3203:                        'ua'   => "uncheck all",
                   3204:                                        );
                   3205:     $r->print(<<"END");
                   3206: </p><p>
                   3207: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)"> &nbsp;
                   3208: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)">
                   3209: <p><input type=submit value="$lt{'dp'}"></p>
                   3210: END
                   3211:     return;
                   3212: }
                   3213: 
                   3214: #
                   3215: # Print out the initial form to get the file containing a list of users
                   3216: #
                   3217: sub print_first_users_upload_form {
                   3218:     my ($r,$context) = @_;
                   3219:     my $str;
                   3220:     $str  = '<input type="hidden" name="phase" value="two">';
                   3221:     $str .= '<input type="hidden" name="action" value="upload" />';
                   3222:     $str .= '<input type="hidden"   name="state"  value="got_file" />';
1.2       raeburn  3223:     $str .= "<h3>".&mt('Upload a file containing information about users')."</h3>\n";
1.1       raeburn  3224:     $str .= &Apache::loncommon::upfile_select_html();
                   3225:     $str .= "<p>\n";
                   3226:     $str .= '<input type="submit" name="fileupload" value="'.
1.2       raeburn  3227:         &mt('Upload file of users').'">'."\n";
1.1       raeburn  3228:     $str .= '<label><input type="checkbox" name="noFirstLine" /> '.
                   3229:         &mt('Ignore First Line')."</label></p>\n";
                   3230:     $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List",
                   3231:                          &mt("How do I create a users list from a spreadsheet")).
                   3232:                              "<br />\n";
                   3233:     $str .= &Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
                   3234:                            &mt("How do I create a CSV file from a spreadsheet")).
                   3235:                                "<br />\n";
                   3236:     $str .= &Apache::loncommon::end_page();
                   3237:     $r->print($str);
                   3238:     return;
                   3239: }
                   3240: 
                   3241: # ================================================= Drop/Add from uploaded file
                   3242: sub upfile_drop_add {
1.21      raeburn  3243:     my ($r,$context,$permission) = @_;
1.1       raeburn  3244:     &Apache::loncommon::load_tmp_file($r);
                   3245:     my @userdata=&Apache::loncommon::upfile_record_sep();
                   3246:     if($env{'form.noFirstLine'}){shift(@userdata);}
                   3247:     my @keyfields = split(/\,/,$env{'form.keyfields'});
                   3248:     my %fields=();
                   3249:     for (my $i=0; $i<=$env{'form.nfields'}; $i++) {
                   3250:         if ($env{'form.upfile_associate'} eq 'reverse') {
                   3251:             if ($env{'form.f'.$i} ne 'none') {
                   3252:                 $fields{$keyfields[$i]}=$env{'form.f'.$i};
                   3253:             }
                   3254:         } else {
                   3255:             $fields{$env{'form.f'.$i}}=$keyfields[$i];
                   3256:         }
                   3257:     }
1.29      raeburn  3258:     if ($env{'form.fullup'} ne 'yes') {
                   3259:         $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
                   3260:                   '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />');
                   3261:     }
1.1       raeburn  3262:     #
                   3263:     # Store the field choices away
                   3264:     foreach my $field (qw/username names
                   3265:                        fname mname lname gen id sec ipwd email role/) {
                   3266:         $env{'form.'.$field.'_choice'}=$fields{$field};
                   3267:     }
                   3268:     &Apache::loncommon::store_course_settings('enrollment_upload',
                   3269:                                               { 'username_choice' => 'scalar',
                   3270:                                                 'names_choice' => 'scalar',
                   3271:                                                 'fname_choice' => 'scalar',
                   3272:                                                 'mname_choice' => 'scalar',
                   3273:                                                 'lname_choice' => 'scalar',
                   3274:                                                 'gen_choice' => 'scalar',
                   3275:                                                 'id_choice' => 'scalar',
                   3276:                                                 'sec_choice' => 'scalar',
                   3277:                                                 'ipwd_choice' => 'scalar',
                   3278:                                                 'email_choice' => 'scalar',
                   3279:                                                 'role_choice'  => 'scalar' });
                   3280:     #
                   3281:     my ($startdate,$enddate) = &get_dates_from_form();
                   3282:     if ($env{'form.makedatesdefault'}) {
1.27      raeburn  3283:         $r->print(&make_dates_default($startdate,$enddate,$context));
1.1       raeburn  3284:     }
                   3285:     # Determine domain and desired host (home server)
                   3286:     my $domain=$env{'request.role.domain'};
                   3287:     my $desiredhost = $env{'form.lcserver'};
                   3288:     if (lc($desiredhost) eq 'default') {
                   3289:         $desiredhost = undef;
                   3290:     } else {
                   3291:         my %home_servers = &Apache::lonnet::get_servers($domain,'library');
                   3292:         if (! exists($home_servers{$desiredhost})) {
                   3293:             $r->print('<span class="LC_error">'.&mt('Error').
                   3294:                       &mt('Invalid home server specified').'</span>');
                   3295:             $r->print(&Apache::loncommon::end_page());
                   3296:             return;
                   3297:         }
                   3298:     }
                   3299:     # Determine authentication mechanism
                   3300:     my $changeauth;
                   3301:     if ($context eq 'domain') {
                   3302:         $changeauth = $env{'form.changeauth'};
                   3303:     }
                   3304:     my $amode  = '';
                   3305:     my $genpwd = '';
                   3306:     if ($env{'form.login'} eq 'krb') {
                   3307:         $amode='krb';
                   3308:         $amode.=$env{'form.krbver'};
                   3309:         $genpwd=$env{'form.krbarg'};
                   3310:     } elsif ($env{'form.login'} eq 'int') {
                   3311:         $amode='internal';
                   3312:         if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) {
                   3313:             $genpwd=$env{'form.intarg'};
                   3314:         }
                   3315:     } elsif ($env{'form.login'} eq 'loc') {
                   3316:         $amode='localauth';
                   3317:         if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
                   3318:             $genpwd=$env{'form.locarg'};
                   3319:         }
                   3320:     }
                   3321:     if ($amode =~ /^krb/) {
                   3322:         if (! defined($genpwd) || $genpwd eq '') {
                   3323:             $r->print('<span class="Error">'.
                   3324:                       &mt('Unable to enroll users').' '.
                   3325:                       &mt('No Kerberos domain was specified.').'</span></p>');
                   3326:             $amode = ''; # This causes the loop below to be skipped
                   3327:         }
                   3328:     }
                   3329:     my ($cid,$defaultsec,$defaultrole,$setting);
                   3330:     if ($context eq 'domain') {
                   3331:         $setting = $env{'form.roleaction'};
                   3332:         if ($setting eq 'domain') {
                   3333:             $defaultrole = $env{'form.defaultrole'};
                   3334:         } elsif ($setting eq 'course') {
                   3335:             $defaultrole = $env{'form.courserole'};
1.27      raeburn  3336:             $defaultsec = $env{'form.sections'};
1.1       raeburn  3337:         }  
1.13      raeburn  3338:     } elsif ($context eq 'author') {
1.1       raeburn  3339:         $defaultrole = $env{'form.defaultrole'};
1.27      raeburn  3340:     } elsif ($context eq 'course') {
                   3341:         $defaultrole = $env{'form.defaultrole'};
                   3342:         $defaultsec = $env{'form.sections'};
1.1       raeburn  3343:     }
1.27      raeburn  3344:     if ($env{'request.course.id'} ne '') {
                   3345:         $cid = $env{'request.course.id'};
                   3346:     } elsif ($setting eq 'course') {
                   3347:         if (&Apache::lonnet::is_course($env{'form.dcdomain'},$env{'form.dccourse'})) {
                   3348:             $cid = $env{'form.dcdomain'}.'_'.$env{'form.dccourse'};
1.1       raeburn  3349:         }
                   3350:     }
1.27      raeburn  3351:     # Check to see if user information can be changed
                   3352:     my @userinfo = ('firstname','middlename','lastname','generation',
                   3353:                     'permanentemail','id');
                   3354:     my %canmodify;
                   3355:     if (&Apache::lonnet::allowed('mau',$domain)) {
                   3356:         foreach my $field (@userinfo) {
                   3357:             $canmodify{$field} = 1;
                   3358:         }
                   3359:     }
                   3360:     my (%userlist,%modifiable_fields,@poss_roles);
                   3361:     my $secidx = &Apache::loncoursedata::CL_SECTION();
                   3362:     my @courseroles = &roles_by_context('course',1);
                   3363:     if (!&Apache::lonnet::allowed('mau',$domain)) {
                   3364:         if ($context eq 'course' || $context eq 'author') {
                   3365:             @poss_roles =  &curr_role_permissions($context);
                   3366:             my @statuses = ('active','future');
                   3367:             my ($indexhash,$keylist) = &make_keylist_array();
                   3368:             my %info;
                   3369:             foreach my $role (@poss_roles) {
                   3370:                 %{$modifiable_fields{$role}} = &can_modify_userinfo($context,$domain,
                   3371:                                                         \@userinfo,[$role]);
                   3372:             }
                   3373:             if ($context eq 'course') {
                   3374:                 my ($cnum,$cdom) = &get_course_identity();
                   3375:                 my $roster = &Apache::loncoursedata::get_classlist();
                   3376:                 %userlist = %{$roster};
                   3377:                 my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
                   3378:                                                          \@statuses,\@poss_roles);
                   3379:                 &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
                   3380:                                 \%advrolehash,$permission);
                   3381:             } elsif ($context eq 'author') {
                   3382:                 my %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
                   3383:                                                   \@statuses,\@poss_roles);
                   3384:                 &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
                   3385:                              \%cstr_roles,$permission);
                   3386: 
                   3387:             }
                   3388:         }
1.1       raeburn  3389:     }
                   3390:     if ( $domain eq &LONCAPA::clean_domain($domain)
                   3391:         && ($amode ne '')) {
                   3392:         #######################################
                   3393:         ##         Add/Modify Users          ##
                   3394:         #######################################
                   3395:         if ($context eq 'course') {
                   3396:             $r->print('<h3>'.&mt('Enrolling Users')."</h3>\n<p>\n");
1.13      raeburn  3397:         } elsif ($context eq 'author') {
1.1       raeburn  3398:             $r->print('<h3>'.&mt('Updating Co-authors')."</h3>\n<p>\n");
                   3399:         } else {
                   3400:             $r->print('<h3>'.&mt('Adding/Modifying Users')."</h3>\n<p>\n");
                   3401:         }
                   3402:         my %counts = (
                   3403:                        user => 0,
                   3404:                        auth => 0,
                   3405:                        role => 0,
                   3406:                      );
                   3407:         my $flushc=0;
                   3408:         my %student=();
1.42      raeburn  3409:         my (%curr_groups,@sections,@cleansec,$defaultwarn,$groupwarn);
1.1       raeburn  3410:         my %userchg;
1.27      raeburn  3411:         if ($context eq 'course' || $setting eq 'course') {
                   3412:             if ($context eq 'course') {
                   3413:                 # Get information about course groups
                   3414:                 %curr_groups = &Apache::longroup::coursegroups();
                   3415:             } elsif ($setting eq 'course') {
                   3416:                 if ($cid) {
                   3417:                     %curr_groups =
                   3418:                         &Apache::longroup::coursegroups($env{'form.dcdomain'},
                   3419:                                                         $env{'form.dccourse'});
                   3420:                 }
                   3421:             }
                   3422:             # determine section number
                   3423:             if ($defaultsec =~ /,/) {
                   3424:                 push(@sections,split(/,/,$defaultsec));
                   3425:             } else {
                   3426:                 push(@sections,$defaultsec);
                   3427:             }
                   3428:             # remove non alphanumeric values from section
                   3429:             foreach my $item (@sections) {
                   3430:                 $item =~ s/\W//g;
                   3431:                 if ($item eq "none" || $item eq 'all') {
                   3432:                     $defaultwarn = &mt('Default section name [_1] could not be used as it is a reserved word.',$item);
                   3433:                 } elsif ($item ne ''  && exists($curr_groups{$item})) {
                   3434:                     $groupwarn = &mt('Default section name "[_1]" is the name of a course group. Section names and group names must be distinct.',$item);
                   3435:                 } elsif ($item ne '') {
                   3436:                     push(@cleansec,$item);
                   3437:                 }
                   3438:             }
                   3439:             if ($defaultwarn) {
                   3440:                 $r->print($defaultwarn.'<br />');
                   3441:             }
                   3442:             if ($groupwarn) {
                   3443:                 $r->print($groupwarn.'<br />');
                   3444:             }
1.1       raeburn  3445:         }
1.5       raeburn  3446:         my (%curr_rules,%got_rules,%alerts);
1.27      raeburn  3447:         my %customroles = &my_custom_roles();
1.42      raeburn  3448:         my @permitted_roles = &roles_on_upload($context,$setting,%customroles); 
1.1       raeburn  3449:         # Get new users list
1.27      raeburn  3450:         foreach my $line (@userdata) {
1.42      raeburn  3451:             my @secs;
1.27      raeburn  3452:             my %entries=&Apache::loncommon::record_sep($line);
1.1       raeburn  3453:             # Determine user name
                   3454:             unless (($entries{$fields{'username'}} eq '') ||
                   3455:                     (!defined($entries{$fields{'username'}}))) {
                   3456:                 my ($fname, $mname, $lname,$gen) = ('','','','');
                   3457:                 if (defined($fields{'names'})) {
                   3458:                     ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
                   3459:                                             /([^\,]+)\,\s*(\w+)\s*(.*)$/);
                   3460:                 } else {
                   3461:                     if (defined($fields{'fname'})) {
                   3462:                         $fname=$entries{$fields{'fname'}};
                   3463:                     }
                   3464:                     if (defined($fields{'mname'})) {
                   3465:                         $mname=$entries{$fields{'mname'}};
                   3466:                     }
                   3467:                     if (defined($fields{'lname'})) {
                   3468:                         $lname=$entries{$fields{'lname'}};
                   3469:                     }
                   3470:                     if (defined($fields{'gen'})) {
                   3471:                         $gen=$entries{$fields{'gen'}};
                   3472:                     }
                   3473:                 }
                   3474:                 if ($entries{$fields{'username'}}
                   3475:                     ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
                   3476:                     $r->print('<br />'.
                   3477:       &mt('<b>[_1]</b>: Unacceptable username for user [_2] [_3] [_4] [_5]',
                   3478:           $entries{$fields{'username'}},$fname,$mname,$lname,$gen).
                   3479:                               '</b>');
1.27      raeburn  3480:                     next;
1.1       raeburn  3481:                 } else {
1.5       raeburn  3482:                     my $username = $entries{$fields{'username'}};
1.27      raeburn  3483:                     if (defined($fields{'sec'})) {
                   3484:                         if (defined($entries{$fields{'sec'}})) {
1.42      raeburn  3485:                             $entries{$fields{'sec'}} =~ s/\W//g;
1.27      raeburn  3486:                             my $item = $entries{$fields{'sec'}};
                   3487:                             if ($item eq "none" || $item eq 'all') {
                   3488:                                 $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.',$username,$fname,$mname,$lname,$gen,$item));
                   3489:                                 next;
                   3490:                             } elsif (exists($curr_groups{$item})) {
                   3491:                                 $r->print('<br />'.&mt('<b>[_1]</b>: 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.'));
                   3492:                                 next;
                   3493:                             } else {
                   3494:                                 push(@secs,$item);
                   3495:                             }
                   3496:                         }
                   3497:                     }
                   3498:                     if ($env{'request.course.sec'} ne '') {
                   3499:                         @secs = ($env{'request.course.sec'});
                   3500:                         if (ref($userlist{$username.':'.$domain}) eq 'ARRAY') {
                   3501:                             my $currsec = $userlist{$username.':'.$domain}[$secidx];
                   3502:                             if ($currsec ne $env{'request.course.sec'}) {
                   3503:                                 $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".',$username,$fname,$mname,$lname,$gen,$secs[0]).'<br />');
                   3504:                                 if ($currsec eq '') {
                   3505:                                     $r->print(&mt('This user already has an active/future student role in the course, unaffiliated to any section.'));
                   3506: 
                   3507:                                 } else {
                   3508:                                     $r->print(&mt('This user already has an active/future role in section "[_1]" of the course.',$currsec));
                   3509:                                 }
                   3510:                                 $r->print('<br />'.&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]).'<br />');
                   3511:                                 next;
1.1       raeburn  3512:                             }
                   3513:                         }
1.27      raeburn  3514:                     } elsif ($context eq 'course' || $setting eq 'course') {
                   3515:                         if (@secs == 0) {
                   3516:                             @secs = @cleansec;
1.1       raeburn  3517:                         }
                   3518:                     }
                   3519:                     # determine id number
                   3520:                     my $id='';
                   3521:                     if (defined($fields{'id'})) {
                   3522:                         if (defined($entries{$fields{'id'}})) {
                   3523:                             $id=$entries{$fields{'id'}};
                   3524:                         }
                   3525:                         $id=~tr/A-Z/a-z/;
                   3526:                     }
                   3527:                     # determine email address
                   3528:                     my $email='';
                   3529:                     if (defined($fields{'email'})) {
                   3530:                         if (defined($entries{$fields{'email'}})) {
                   3531:                             $email=$entries{$fields{'email'}};
                   3532:                             unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }                        }
                   3533:                     }
                   3534:                     # determine user password
                   3535:                     my $password = $genpwd;
                   3536:                     if (defined($fields{'ipwd'})) {
                   3537:                         if ($entries{$fields{'ipwd'}}) {
                   3538:                             $password=$entries{$fields{'ipwd'}};
                   3539:                         }
                   3540:                     }
                   3541:                     # determine user role
                   3542:                     my $role = '';
                   3543:                     if (defined($fields{'role'})) {
                   3544:                         if ($entries{$fields{'role'}}) {
1.42      raeburn  3545:                             $entries{$fields{'role'}}  =~ s/(\s+$|^\s+)//g;
                   3546:                             if ($entries{$fields{'role'}} ne '') {
                   3547:                                 if (grep(/^\Q$entries{$fields{'role'}}\E$/,@permitted_roles)) {
                   3548:                                     $role = $entries{$fields{'role'}};
1.27      raeburn  3549:                                 }
                   3550:                             }
                   3551:                             if ($role eq '') {
                   3552:                                 my $rolestr = join(', ',@permitted_roles);
1.1       raeburn  3553:                                 $r->print('<br />'.
                   3554:       &mt('<b>[_1]</b>: You do not have permission to add the requested role [_2] for the user.',$entries{$fields{'username'}},$entries{$fields{'role'}}).'<br />'.&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n");
                   3555:                                 next;
                   3556:                             }
                   3557:                         }
                   3558:                     }
                   3559:                     if ($role eq '') {
                   3560:                         $role = $defaultrole;
                   3561:                     }
                   3562:                     # Clean up whitespace
                   3563:                     foreach (\$domain,\$username,\$id,\$fname,\$mname,
1.27      raeburn  3564:                              \$lname,\$gen) {
1.1       raeburn  3565:                         $$_ =~ s/(\s+$|^\s+)//g;
                   3566:                     }
1.5       raeburn  3567:                     # check against rules
                   3568:                     my $checkid = 0;
                   3569:                     my $newuser = 0;
                   3570:                     my (%rulematch,%inst_results,%idinst_results);
                   3571:                     my $uhome=&Apache::lonnet::homeserver($username,$domain);
                   3572:                     if ($uhome eq 'no_host') {
                   3573:                         $checkid = 1;
                   3574:                         $newuser = 1;
                   3575:                         my $checkhash;
                   3576:                         my $checks = { 'username' => 1 };
                   3577:                         $checkhash->{$username.':'.$domain} = { 'newuser' => 1, };
                   3578:                         &Apache::loncommon::user_rule_check($checkhash,$checks,
                   3579:                             \%alerts,\%rulematch,\%inst_results,\%curr_rules,
                   3580:                             \%got_rules);
                   3581:                         if (ref($alerts{'username'}) eq 'HASH') {
                   3582:                             if (ref($alerts{'username'}{$domain}) eq 'HASH') {
                   3583:                                 next if ($alerts{'username'}{$domain}{$username});
                   3584:                             }
                   3585:                         }
1.13      raeburn  3586:                     } else {
1.27      raeburn  3587:                         if ($context eq 'course' || $context eq 'author') {
                   3588:                             if ($role eq '') {
                   3589:                                 my @checkroles;
                   3590:                                 foreach my $role (@poss_roles) {
                   3591:                                     my $endkey;
                   3592:                                     if ($role ne 'st') {
                   3593:                                         $endkey = ':'.$role;
                   3594:                                     }
                   3595:                                     if (exists($userlist{$username.':'.$domain.$endkey})) {
                   3596:                                         if (!grep(/^\Q$role\E$/,@checkroles)) {
                   3597:                                             push(@checkroles,$role);
                   3598:                                         }
                   3599:                                     }
                   3600:                                 }
                   3601:                                 if (@checkroles > 0) {
                   3602:                                     %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles);
                   3603:                                 }
                   3604:                             } elsif (ref($modifiable_fields{$role}) eq 'HASH') {
                   3605:                                 %canmodify = %{$modifiable_fields{$role}};
                   3606:                             }
                   3607:                         }
                   3608:                         my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id);
                   3609:                         for (my $i=0; $i<@userinfo; $i++) {
                   3610:                             if (${$newinfo[$i]} ne '') {
                   3611:                                 if (!$canmodify{$userinfo[$i]}) {
                   3612:                                     ${$newinfo[$i]} = '';
                   3613:                                 }
                   3614:                             }
                   3615:                         }
1.5       raeburn  3616:                     }
                   3617:                     if ($id ne '') {
                   3618:                         if (!$newuser) {
                   3619:                             my %idhash = &Apache::lonnet::idrget($domain,($username));
                   3620:                             if ($idhash{$username} ne $id) {
                   3621:                                 $checkid = 1;
                   3622:                             }
                   3623:                         }
                   3624:                         if ($checkid) {
                   3625:                             my $checkhash;
                   3626:                             my $checks = { 'id' => 1 };
                   3627:                             $checkhash->{$username.':'.$domain} = { 'newuser' => $newuser,
                   3628:                                                                     'id'  => $id };
                   3629:                             &Apache::loncommon::user_rule_check($checkhash,$checks,
                   3630:                                 \%alerts,\%rulematch,\%idinst_results,\%curr_rules,
                   3631:                                 \%got_rules);
                   3632:                             if (ref($alerts{'id'}) eq 'HASH') {
                   3633:                                 if (ref($alerts{'id'}{$domain}) eq 'HASH') {
                   3634:                                     next if ($alerts{'id'}{$domain}{$id});
                   3635:                                 }
                   3636:                             }
                   3637:                         }
                   3638:                     }
1.1       raeburn  3639:                     if ($password || $env{'form.login'} eq 'loc') {
1.27      raeburn  3640:                         my $multiple = 0;
                   3641:                         my ($userresult,$authresult,$roleresult,$idresult);
                   3642:                         my (%userres,%authres,%roleres,%idres);
1.42      raeburn  3643:                         my $singlesec = '';
1.1       raeburn  3644:                         if ($role eq 'st') {
1.27      raeburn  3645:                             my $sec;
1.42      raeburn  3646:                             if (@secs > 0) {
                   3647:                                 $sec = $secs[0];
1.27      raeburn  3648:                             }
1.42      raeburn  3649:                             &modifystudent($domain,$username,$cid,$sec,
                   3650:                                            $desiredhost);
                   3651:                             $roleresult =
                   3652:                                 &Apache::lonnet::modifystudent
                   3653:                                     ($domain,$username,$id,$amode,$password,
                   3654:                                      $fname,$mname,$lname,$gen,$sec,$enddate,
                   3655:                                      $startdate,$env{'form.forceid'},
                   3656:                                      $desiredhost,$email,'manual','',$cid);
                   3657:                             $userresult = $roleresult;
1.1       raeburn  3658:                         } else {
1.42      raeburn  3659:                             if ($role ne '') { 
                   3660:                                 if ($context eq 'course' || $setting eq 'course') {
                   3661:                                     if ($customroles{$role}) {
                   3662:                                         $role = 'cr_'.$env{'user.domain'}.'_'.
                   3663:                                                 $env{'user.name'}.'_'.$role;
                   3664:                                     }
                   3665:                                     if ($role ne 'cc') { 
                   3666:                                         if (@secs > 1) {
                   3667:                                             $multiple = 1;
                   3668:                                             foreach my $sec (@secs) {
                   3669:                                                 ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) =
                   3670:                                                 &modifyuserrole($context,$setting,
                   3671:                                                     $changeauth,$cid,$domain,$username,
                   3672:                                                     $id,$amode,$password,$fname,
                   3673:                                                     $mname,$lname,$gen,$sec,
                   3674:                                                     $env{'form.forceid'},$desiredhost,
                   3675:                                                     $email,$role,$enddate,
                   3676:                                                     $startdate,$checkid);
                   3677:                                             }
                   3678:                                         } elsif (@secs > 0) {
                   3679:                                             $singlesec = $secs[0];
                   3680:                                         }
1.27      raeburn  3681:                                     }
                   3682:                                 }
                   3683:                             }
                   3684:                             if (!$multiple) {
1.28      raeburn  3685:                                 ($userresult,$authresult,$roleresult,$idresult) = 
1.27      raeburn  3686:                                     &modifyuserrole($context,$setting,
1.42      raeburn  3687:                                                     $changeauth,$cid,$domain,$username, 
                   3688:                                                     $id,$amode,$password,$fname,
                   3689:                                                     $mname,$lname,$gen,$singlesec,
                   3690:                                                     $env{'form.forceid'},$desiredhost,
                   3691:                                                     $email,$role,$enddate,$startdate,$checkid);
1.27      raeburn  3692:                             }
                   3693:                         }
                   3694:                         if ($multiple) {
                   3695:                             foreach my $sec (sort(keys(%userres))) {
1.42      raeburn  3696:                                 $flushc =
1.27      raeburn  3697:                                 &user_change_result($r,$userres{$sec},$authres{$sec},
                   3698:                                                     $roleres{$sec},$idres{$sec},\%counts,$flushc,
                   3699:                                                     $username,\%userchg);
                   3700: 
                   3701:                             }
                   3702:                         } else {
                   3703:                             $flushc = 
                   3704:                                 &user_change_result($r,$userresult,$authresult,
1.28      raeburn  3705:                                                     $roleresult,$idresult,\%counts,$flushc,
1.29      raeburn  3706:                                                     $username,\%userchg);
1.1       raeburn  3707:                         }
                   3708:                     } else {
                   3709:                         if ($context eq 'course') {
                   3710:                             $r->print('<br />'. 
                   3711:       &mt('<b>[_1]</b>: Unable to enroll.  No password specified.',$username)
                   3712:                                      );
1.13      raeburn  3713:                         } elsif ($context eq 'author') {
1.1       raeburn  3714:                             $r->print('<br />'.
                   3715:       &mt('<b>[_1]</b>: Unable to add co-author.  No password specified.',$username)
                   3716:                                      );
                   3717:                         } else {
                   3718:                             $r->print('<br />'.
                   3719:       &mt('<b>[_1]</b>: Unable to add user.  No password specified.',$username)
                   3720:                                      );
                   3721:                         }
                   3722:                     }
                   3723:                 }
                   3724:             }
                   3725:         } # end of foreach (@userdata)
                   3726:         # Flush the course logs so reverse user roles immediately updated
1.5       raeburn  3727:         &Apache::lonnet::flushcourselogs();
1.29      raeburn  3728:         $r->print("</p>\n<p>\n".&mt('Processed [quant,_1,user].',$counts{'user'}).
1.1       raeburn  3729:                   "</p>\n");
                   3730:         if ($counts{'role'} > 0) {
                   3731:             $r->print("<p>\n".
1.29      raeburn  3732:                       &mt('Roles added for [quant,_1,user].',$counts{'role'}).' '.&mt('If a user is currently logged-in to LON-CAPA, any new roles which are active will be available when the user next logs in.')."</p>\n");
                   3733:         } else {
                   3734:             $r->print('<p>'.&mt('No roles added').'</p>');
1.1       raeburn  3735:         }
                   3736:         if ($counts{'auth'} > 0) {
                   3737:             $r->print("<p>\n".
                   3738:                       &mt('Authentication changed for [_1] existing users.',
                   3739:                           $counts{'auth'})."</p>\n");
                   3740:         }
1.13      raeburn  3741:         $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules));
1.1       raeburn  3742:         #####################################
1.29      raeburn  3743:         # Display list of students to drop  #
1.1       raeburn  3744:         #####################################
                   3745:         if ($env{'form.fullup'} eq 'yes') {
1.29      raeburn  3746:             $r->print('<h3>'.&mt('Students to Drop')."</h3>\n");
1.1       raeburn  3747:             #  Get current classlist
1.30      raeburn  3748:             my $classlist = &Apache::loncoursedata::get_classlist();
1.1       raeburn  3749:             if (! defined($classlist)) {
1.29      raeburn  3750:                 $r->print('<form name="studentform" method="post" action="/adm/createuser" />'.
                   3751:                           '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'.
                   3752:                           &mt('There are no students with current/future access to the course.').
                   3753:                           '</form>'."\n");
1.1       raeburn  3754:             } else {
                   3755:                 # Remove the students we just added from the list of students.
1.30      raeburn  3756:                 foreach my $line (@userdata) {
                   3757:                     my %entries=&Apache::loncommon::record_sep($line);
1.1       raeburn  3758:                     unless (($entries{$fields{'username'}} eq '') ||
                   3759:                             (!defined($entries{$fields{'username'}}))) {
                   3760:                         delete($classlist->{$entries{$fields{'username'}}.
                   3761:                                                 ':'.$domain});
                   3762:                     }
                   3763:                 }
                   3764:                 # Print out list of dropped students.
1.30      raeburn  3765:                 &show_drop_list($r,$classlist,'nosort',$permission);
1.1       raeburn  3766:             }
                   3767:         }
                   3768:     } # end of unless
1.29      raeburn  3769:     if ($env{'form.fullup'} ne 'yes') {
                   3770:         $r->print('</form>');
                   3771:     }
1.1       raeburn  3772: }
                   3773: 
1.13      raeburn  3774: sub print_namespacing_alerts {
                   3775:     my ($domain,$alerts,$curr_rules) = @_;
                   3776:     my $output;
                   3777:     if (ref($alerts) eq 'HASH') {
                   3778:         if (keys(%{$alerts}) > 0) {
                   3779:             if (ref($alerts->{'username'}) eq 'HASH') {
                   3780:                 foreach my $dom (sort(keys(%{$alerts->{'username'}}))) {
                   3781:                     my $count;
                   3782:                     if (ref($alerts->{'username'}{$dom}) eq 'HASH') {
                   3783:                         $count = keys(%{$alerts->{'username'}{$dom}});
                   3784:                     }
                   3785:                     my $domdesc = &Apache::lonnet::domain($domain,'description');
                   3786:                     if (ref($curr_rules->{$dom}) eq 'HASH') {
                   3787:                         $output .= &Apache::loncommon::instrule_disallow_msg(
                   3788:                                         'username',$domdesc,$count,'upload');
                   3789:                     }
                   3790:                     $output .= &Apache::loncommon::user_rule_formats($dom,
                   3791:                                    $domdesc,$curr_rules->{$dom}{'username'},
                   3792:                                    'username');
                   3793:                 }
                   3794:             }
                   3795:             if (ref($alerts->{'id'}) eq 'HASH') {
                   3796:                 foreach my $dom (sort(keys(%{$alerts->{'id'}}))) {
                   3797:                     my $count;
                   3798:                     if (ref($alerts->{'id'}{$dom}) eq 'HASH') {
                   3799:                         $count = keys(%{$alerts->{'id'}{$dom}});
                   3800:                     }
                   3801:                     my $domdesc = &Apache::lonnet::domain($domain,'description');
                   3802:                     if (ref($curr_rules->{$dom}) eq 'HASH') {
                   3803:                         $output .= &Apache::loncommon::instrule_disallow_msg(
                   3804:                                               'id',$domdesc,$count,'upload');
                   3805:                     }
                   3806:                     $output .= &Apache::loncommon::user_rule_formats($dom,
                   3807:                                     $domdesc,$curr_rules->{$dom}{'id'},'id');
                   3808:                 }
                   3809:             }
                   3810:         }
                   3811:     }
                   3812: }
                   3813: 
1.1       raeburn  3814: sub user_change_result {
1.29      raeburn  3815:     my ($r,$userresult,$authresult,$roleresult,$idresult,$counts,$flushc,
                   3816:         $username,$userchg) = @_;
1.1       raeburn  3817:     my $okresult = 0;
                   3818:     if ($userresult ne 'ok') {
                   3819:         if ($userresult =~ /^error:(.+)$/) {
                   3820:             my $error = $1;
                   3821:             $r->print('<br />'.
                   3822:                   &mt('<b>[_1]</b>:  Unable to add/modify: [_2]',$username,$error));
                   3823:         }
                   3824:     } else {
                   3825:         $counts->{'user'} ++;
                   3826:         $okresult = 1;
                   3827:     }
                   3828:     if ($authresult ne 'ok') {
                   3829:         if ($authresult =~ /^error:(.+)$/) {
                   3830:             my $error = $1;
                   3831:             $r->print('<br />'.
                   3832:                   &mt('<b>[_1]</b>:  Unable to modify authentication: [_2]',$username,$error));
                   3833:         } 
                   3834:     } else {
                   3835:         $counts->{'auth'} ++;
                   3836:         $okresult = 1;
                   3837:     }
                   3838:     if ($roleresult ne 'ok') {
                   3839:         if ($roleresult =~ /^error:(.+)$/) {
                   3840:             my $error = $1;
                   3841:             $r->print('<br />'.
                   3842:                   &mt('<b>[_1]</b>:  Unable to add role: [_2]',$username,$error));
                   3843:         }
                   3844:     } else {
                   3845:         $counts->{'role'} ++;
                   3846:         $okresult = 1;
                   3847:     }
                   3848:     if ($okresult) {
                   3849:         $flushc++;
                   3850:         $userchg->{$username}=1;
                   3851:         $r->print('. ');
                   3852:         if ($flushc>15) {
                   3853:             $r->rflush;
                   3854:             $flushc=0;
                   3855:         }
                   3856:     }
1.29      raeburn  3857:     if ($idresult) {
                   3858:         $r->print($idresult);
                   3859:     }
1.1       raeburn  3860:     return $flushc;
                   3861: }
                   3862: 
                   3863: # ========================================================= Menu Phase Two Drop
1.17      raeburn  3864: sub print_drop_menu {
                   3865:     my ($r,$context,$permission) = @_;
                   3866:     $r->print('<h3>'.&mt("Drop Students").'</h3>'."\n".
                   3867:               '<form name="studentform" method="post">'."\n");
1.30      raeburn  3868:     my $classlist = &Apache::loncoursedata::get_classlist();
1.1       raeburn  3869:     if (! defined($classlist)) {
                   3870:         $r->print(&mt('There are no students currently enrolled.')."\n");
1.30      raeburn  3871:     } else {
                   3872:         &show_drop_list($r,$classlist,'nosort',$permission);
1.1       raeburn  3873:     }
1.17      raeburn  3874:     $r->print('</form>'. &Apache::loncommon::end_page());
1.1       raeburn  3875:     return;
                   3876: }
                   3877: 
                   3878: # ================================================================== Phase four
                   3879: 
1.11      raeburn  3880: sub update_user_list {
                   3881:     my ($r,$context,$setting,$choice) = @_;
                   3882:     my $now = time;
1.1       raeburn  3883:     my $count=0;
1.11      raeburn  3884:     my @changelist;
1.29      raeburn  3885:     if ($choice eq 'drop') {
                   3886:         @changelist = &Apache::loncommon::get_env_multiple('form.droplist');
                   3887:     } else {
1.11      raeburn  3888:         @changelist = &Apache::loncommon::get_env_multiple('form.actionlist');
                   3889:     }
                   3890:     my %result_text = ( ok    => { 'revoke'   => 'Revoked',
                   3891:                                    'delete'   => 'Deleted',
                   3892:                                    'reenable' => 'Re-enabled',
1.17      raeburn  3893:                                    'activate' => 'Activated',
                   3894:                                    'chgdates' => 'Changed Access Dates for',
                   3895:                                    'chgsec'   => 'Changed section for',
                   3896:                                    'drop'     => 'Dropped',
1.11      raeburn  3897:                                  },
                   3898:                         error => {'revoke'    => 'revoking',
                   3899:                                   'delete'    => 'deleting',
                   3900:                                   'reenable'  => 're-enabling',
                   3901:                                   'activate'  => 'activating',
1.17      raeburn  3902:                                   'chgdates'  => 'changing access dates for',
                   3903:                                   'chgsec'    => 'changing section for',
                   3904:                                   'drop'      => 'dropping',
1.11      raeburn  3905:                                  },
                   3906:                       );
                   3907:     my ($startdate,$enddate);
                   3908:     if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
                   3909:         ($startdate,$enddate) = &get_dates_from_form();
                   3910:     }
                   3911:     foreach my $item (@changelist) {
                   3912:         my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,@sections,
                   3913:             $scopestem);
1.17      raeburn  3914:         if ($choice eq 'drop') {
                   3915:             ($uname,$udom,$sec) = split(/:/,$item,-1);
                   3916:             $role = 'st';
                   3917:             $cid = $env{'request.course.id'};
                   3918:             $scopestem = '/'.$cid;
                   3919:             $scopestem =~s/\_/\//g;
                   3920:             if ($sec eq '') {
                   3921:                 $scope = $scopestem;
                   3922:             } else {
                   3923:                 $scope = $scopestem.'/'.$sec;
                   3924:             }
                   3925:         } elsif ($context eq 'course') {
1.11      raeburn  3926:             ($uname,$udom,$role,$sec,$type,$locktype) = split(/\:/,$item,-1);
                   3927:             $cid = $env{'request.course.id'};
                   3928:             $scopestem = '/'.$cid;
                   3929:             $scopestem =~s/\_/\//g;
                   3930:             if ($sec eq '') {
                   3931:                 $scope = $scopestem;
                   3932:             } else {
                   3933:                 $scope = $scopestem.'/'.$sec;
                   3934:             }
1.13      raeburn  3935:         } elsif ($context eq 'author') {
1.11      raeburn  3936:             ($uname,$udom,$role) = split(/\:/,$item,-1);
                   3937:             $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
                   3938:         } elsif ($context eq 'domain') {
                   3939:             if ($setting eq 'domain') {
                   3940:                 ($role,$uname,$udom) = split(/\:/,$item,-1);
                   3941:                 $scope = '/'.$env{'request.role.domain'}.'/';
1.13      raeburn  3942:             } elsif ($setting eq 'author') { 
1.11      raeburn  3943:                 ($uname,$udom,$role,$scope) = split(/\:/,$item);
                   3944:             } elsif ($setting eq 'course') {
                   3945:                 ($uname,$udom,$role,$cid,$sec,$type,$locktype) = 
                   3946:                     split(/\:/,$item);
                   3947:                 $scope = '/'.$cid;
                   3948:                 $scope =~s/\_/\//g;
                   3949:                 if ($sec ne '') {
                   3950:                     $scope .= '/'.$sec;
                   3951:                 }
                   3952:             }
                   3953:         }
                   3954:         my $plrole = &Apache::lonnet::plaintext($role);
                   3955:         my $start = $env{'form.'.$item.'_start'};
                   3956:         my $end = $env{'form.'.$item.'_end'};
1.17      raeburn  3957:         if ($choice eq 'drop') {
                   3958:             # drop students
                   3959:             $end = $now;
                   3960:             $type = 'manual';
                   3961:             $result =
                   3962:                 &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
                   3963:         } elsif ($choice eq 'revoke') {
                   3964:             # revoke or delete user role
1.11      raeburn  3965:             $end = $now; 
                   3966:             if ($role eq 'st') {
                   3967:                 $result = 
                   3968:                     &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
                   3969:             } else {
                   3970:                 $result = 
                   3971:                     &Apache::lonnet::revokerole($udom,$uname,$scope,$role);
                   3972:             }
                   3973:         } elsif ($choice eq 'delete') {
                   3974:             if ($role eq 'st') {
1.29      raeburn  3975:                 &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid);
                   3976:             }
                   3977:             $result =
                   3978:                 &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now,
                   3979:                                             $start,1);
1.11      raeburn  3980:         } else {
                   3981:             #reenable, activate, change access dates or change section
                   3982:             if ($choice ne 'chgsec') {
                   3983:                 $start = $startdate; 
                   3984:                 $end = $enddate;
                   3985:             }
                   3986:             if ($choice eq 'reenable') {
                   3987:                 if ($role eq 'st') {
                   3988:                     $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
                   3989:                 } else {
                   3990:                     $result = 
                   3991:                         &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
                   3992:                                                     $now);
                   3993:                 }
                   3994:             } elsif ($choice eq 'activate') {
                   3995:                 if ($role eq 'st') {
                   3996:                     $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
                   3997:                 } else {
                   3998:                     $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
                   3999:                                             $now);
                   4000:                 }
                   4001:             } elsif ($choice eq 'chgdates') {
                   4002:                 if ($role eq 'st') {
                   4003:                     $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
                   4004:                 } else {
                   4005:                     $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
                   4006:                                                 $start);
                   4007:                 }
                   4008:             } elsif ($choice eq 'chgsec') {
                   4009:                 my (@newsecs,$revresult,$nochg,@retained);
                   4010:                 if ($role ne 'cc') {
                   4011:                     @newsecs = split(/,/,$env{'form.newsecs'});
                   4012:                 }
                   4013:                 # remove existing section if not to be retained.   
                   4014:                 if (!$env{'form.retainsec'}) {
                   4015:                     if ($sec eq '') {
                   4016:                         if (@newsecs == 0) {
                   4017:                             $result = &mt('No change in section assignment (none)');
                   4018:                             $nochg = 1;
1.40      raeburn  4019:                         } else {
                   4020:                             $revresult =
                   4021:                                 &Apache::lonnet::revokerole($udom,$uname,
                   4022:                                                             $scope,$role);
                   4023:                         } 
1.11      raeburn  4024:                     } else {
1.28      raeburn  4025:                         if (@newsecs > 0) {
                   4026:                             if (grep(/^\Q$sec\E$/,@newsecs)) {
                   4027:                                 push(@retained,$sec);
                   4028:                             } else {
                   4029:                                 $revresult =
                   4030:                                     &Apache::lonnet::revokerole($udom,$uname,
                   4031:                                                                 $scope,$role);
                   4032:                             }
                   4033:                         } else {
1.11      raeburn  4034:                             $revresult =
1.28      raeburn  4035:                                 &Apache::lonnet::revokerole($udom,$uname,
                   4036:                                                             $scope,$role);
1.11      raeburn  4037:                         }
                   4038:                     }
                   4039:                 } else {
1.28      raeburn  4040:                     if ($sec eq '') {
                   4041:                         $nochg = 1;
                   4042:                     } else { 
                   4043:                         push(@retained,$sec);
                   4044:                     }
1.11      raeburn  4045:                 }
                   4046:                 # add new sections
                   4047:                 if (@newsecs == 0) {
                   4048:                     if (!$nochg) {
1.28      raeburn  4049:                         if ($role eq 'st') {
                   4050:                             $result = 
                   4051:                                 &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid);
                   4052:                         } else {
                   4053:                             my $newscope = $scopestem;
                   4054:                             $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start);
1.11      raeburn  4055:                         }
                   4056:                     }
                   4057:                 } else {
                   4058:                     foreach my $newsec (@newsecs) { 
                   4059:                         if (!grep(/^\Q$newsec\E$/,@retained)) {
                   4060:                             if ($role eq 'st') {
                   4061:                                 $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid);
                   4062:                             } else {
                   4063:                                 my $newscope = $scopestem;
                   4064:                                 if ($newsec ne '') {
                   4065:                                    $newscope .= '/'.$newsec;
                   4066:                                 }
                   4067:                                 $result = &Apache::lonnet::assignrole($udom,$uname,
                   4068:                                                         $newscope,$role,$end,$start);
                   4069:                             }
                   4070:                         }
                   4071:                     }
                   4072:                 }
                   4073:             }
                   4074:         }
1.17      raeburn  4075:         my $extent = $scope;
                   4076:         if ($choice eq 'drop' || $context eq 'course') {
                   4077:             my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
                   4078:             if ($cdesc) {
                   4079:                 $extent = $cdesc;
                   4080:             }
                   4081:         }
1.1       raeburn  4082:         if ($result eq 'ok' || $result eq 'ok:') {
1.11      raeburn  4083:             $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for [_3]",
1.17      raeburn  4084:                           $plrole,$extent,$uname.':'.$udom).'<br />');
1.1       raeburn  4085:             $count++;
                   4086:         } else {
                   4087:             $r->print(
1.29      raeburn  4088:                 &mt("Error $result_text{'error'}{$choice} [_1] in [_2] for [_3]: [_4].",
1.17      raeburn  4089:                     $plrole,$extent,$uname.':'.$udom,$result).'<br />');
1.11      raeburn  4090:         }
                   4091:     }
1.32      raeburn  4092:     $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n");
1.33      raeburn  4093:     if ($choice eq 'drop') {
                   4094:         $r->print('<input type="hidden" name="action" value="listusers" />'."\n".
                   4095:                   '<input type="hidden" name="Status" value="Active" />'."\n".
                   4096:                   '<input type="hidden" name="showrole" value="st" />'."\n");
                   4097:     } else {
                   4098:         foreach my $item ('action','sortby','roletype','showrole','Status','secfilter','grpfilter') {
                   4099:             if ($env{'form.'.$item} ne '') {
                   4100:                 $r->print('<input type="hidden" name="'.$item.'" value="'.$env{'form.'.$item}.
                   4101:                           '" />'."\n");
                   4102:             }
1.32      raeburn  4103:         }
                   4104:     }
1.29      raeburn  4105:     $r->print('<p><b>'.&mt("$result_text{'ok'}{$choice} role(s) for [quant,_1,user,users,no users].",$count).'</b></p>');
1.11      raeburn  4106:     if ($count > 0) {
1.17      raeburn  4107:         if ($choice eq 'revoke' || $choice eq 'drop') {
1.11      raeburn  4108:             $r->print('<p>'.&mt('Re-enabling will re-activate data for the role.</p>'));
                   4109:         }
                   4110:         # Flush the course logs so reverse user roles immediately updated
                   4111:         &Apache::lonnet::flushcourselogs();
                   4112:     }
                   4113:     if ($env{'form.makedatesdefault'}) {
                   4114:         if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
1.29      raeburn  4115:             $r->print(&make_dates_default($startdate,$enddate,$context));
1.1       raeburn  4116:         }
                   4117:     }
1.33      raeburn  4118:     my $linktext = &mt('Display User Lists');
                   4119:     if ($choice eq 'drop') {
                   4120:         $linktext = &mt('Display current class roster');
                   4121:     }
                   4122:     $r->print('<a href="javascript:document.studentform.submit()">'.$linktext.'</a></form>'."\n");
1.1       raeburn  4123: }
                   4124: 
1.8       raeburn  4125: sub classlist_drop {
1.29      raeburn  4126:     my ($scope,$uname,$udom,$now) = @_;
1.8       raeburn  4127:     my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)});
1.29      raeburn  4128:     if (&Apache::lonnet::is_course($cdom,$cnum)) {
                   4129:         my $user = $uname.':'.$udom;
1.8       raeburn  4130:         if (!&active_student_roles($cnum,$cdom,$uname,$udom)) {
                   4131:             my $result =
                   4132:                 &Apache::lonnet::cput('classlist',
1.29      raeburn  4133:                                       { $user => $now },$cdom,$cnum);
1.8       raeburn  4134:             return &mt('Drop from classlist: [_1]',
                   4135:                        '<b>'.$result.'</b>').'<br />';
                   4136:         }
                   4137:     }
                   4138: }
                   4139: 
                   4140: sub active_student_roles {
                   4141:     my ($cnum,$cdom,$uname,$udom) = @_;
                   4142:     my %roles =
                   4143:         &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
                   4144:                                       ['future','active'],['st']);
                   4145:     return exists($roles{"$cnum:$cdom:st"});
                   4146: }
                   4147: 
1.1       raeburn  4148: sub section_check_js {
1.8       raeburn  4149:     my $groupslist= &get_groupslist();
1.1       raeburn  4150:     return <<"END";
                   4151: function validate(caller) {
1.9       raeburn  4152:     var groups = new Array($groupslist);
1.1       raeburn  4153:     var secname = caller.value;
                   4154:     if ((secname == 'all') || (secname == 'none')) {
                   4155:         alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name.");
                   4156:         return 'error';
                   4157:     }
                   4158:     if (secname != '') {
                   4159:         for (var k=0; k<groups.length; k++) {
                   4160:             if (secname == groups[k]) {
                   4161:                 alert("'"+secname+"' may not be used as the name for a section, as it is the name of a course group.\\nSection names and group names must be distinct. Please choose a different section name.");
                   4162:                 return 'error';
                   4163:             }
                   4164:         }
                   4165:     }
                   4166:     return 'ok';
                   4167: }
                   4168: END
                   4169: }
                   4170: 
                   4171: sub set_login {
                   4172:     my ($dom,$authformkrb,$authformint,$authformloc) = @_;
                   4173:     my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
                   4174:     my $response;
                   4175:     my ($authnum,%can_assign) =
                   4176:         &Apache::loncommon::get_assignable_auth($dom);
                   4177:     if ($authnum) {
                   4178:         $response = &Apache::loncommon::start_data_table();
                   4179:         if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
                   4180:             $response .= &Apache::loncommon::start_data_table_row().
                   4181:                          '<td>'.$authformkrb.'</td>'.
                   4182:                          &Apache::loncommon::end_data_table_row()."\n";
                   4183:         }
                   4184:         if ($can_assign{'int'}) {
                   4185:             $response .= &Apache::loncommon::start_data_table_row().
                   4186:                          '<td>'.$authformint.'</td>'.
                   4187:                          &Apache::loncommon::end_data_table_row()."\n"
                   4188:         }
                   4189:         if ($can_assign{'loc'}) {
                   4190:             $response .= &Apache::loncommon::start_data_table_row().
                   4191:                          '<td>'.$authformloc.'</td>'.
                   4192:                          &Apache::loncommon::end_data_table_row()."\n";
                   4193:         }
                   4194:         $response .= &Apache::loncommon::end_data_table();
                   4195:     }
                   4196:     return $response;
                   4197: }
                   4198: 
1.8       raeburn  4199: sub course_sections {
                   4200:     my ($sections_count,$role) = @_;
                   4201:     my $output = '';
                   4202:     my @sections = (sort {$a <=> $b} keys %{$sections_count});
1.29      raeburn  4203:     my $numsec = scalar(@sections);
                   4204:     if ($numsec <= 1) {
1.8       raeburn  4205:         $output = '<select name="currsec_'.$role.'" >'."\n".
1.29      raeburn  4206:                   '  <option value="">'.&mt('Select').'</option>'."\n".
                   4207:                   '  <option value="">'.&mt('No section').'</option>'."\n";
                   4208:         if ($numsec == 1) {
                   4209:             $output .=  
1.8       raeburn  4210:                   '  <option value="'.$sections[0].'" >'.$sections[0].'</option>'."\n";
1.29      raeburn  4211:         }
1.8       raeburn  4212:     } else {
                   4213:         $output = '<select name="currsec_'.$role.'" ';
                   4214:         my $multiple = 4;
                   4215:         if (scalar(@sections) < 4) { $multiple = scalar(@sections); }
1.29      raeburn  4216:         if ($role eq 'st') {
                   4217:             $output .= '>'."\n".
                   4218:                        '  <option value="">'.&mt('Select').'</option>'."\n".
                   4219:                        '  <option value="">'.&mt('No section')."</option>\n";
                   4220:         } else {
                   4221:             $output .= 'multiple="multiple" size="'.$multiple.'">'."\n";
                   4222:         }
1.8       raeburn  4223:         foreach my $sec (@sections) {
                   4224:             $output .= '<option value="'.$sec.'">'.$sec."</option>\n";
                   4225:         }
                   4226:     }
                   4227:     $output .= '</select>';
                   4228:     return $output;
                   4229: }
                   4230: 
                   4231: sub get_groupslist {
                   4232:     my $groupslist;
                   4233:     my %curr_groups = &Apache::longroup::coursegroups();
                   4234:     if (%curr_groups) {
                   4235:         $groupslist = join('","',sort(keys(%curr_groups)));
                   4236:         $groupslist = '"'.$groupslist.'"';
                   4237:     }
1.11      raeburn  4238:     return $groupslist; 
1.8       raeburn  4239: }
                   4240: 
                   4241: sub setsections_javascript {
1.37      raeburn  4242:     my ($formname,$groupslist,$mode,$checkauth) = @_;
1.28      raeburn  4243:     my ($checkincluded,$finish,$rolecode,$setsection_js);
                   4244:     if ($mode eq 'upload') {
                   4245:         $checkincluded = 'formname.name == "'.$formname.'"';
                   4246:         $finish = "return 'ok';";
                   4247:         $rolecode = "var role = formname.defaultrole.options[formname.defaultrole.selectedIndex].value;\n";
                   4248:     } elsif ($formname eq 'cu') {
1.8       raeburn  4249:         $checkincluded = 'formname.elements[i-1].checked == true';
1.37      raeburn  4250:         if ($checkauth) {
                   4251:             $finish = "var authcheck = auth_check();\n".
                   4252:                       "   if (authcheck == 'ok') {\n".
                   4253:                       "       formname.submit();\n".
                   4254:                       "   }\n";
                   4255:         } else {
                   4256:             $finish = 'formname.submit()';
                   4257:         }
1.28      raeburn  4258:         $rolecode = "var match = str.split('_');
                   4259:                 var role = match[3];\n";
                   4260:     } elsif ($formname eq 'enrollstudent') {
                   4261:         $checkincluded = 'formname.name == "'.$formname.'"';
1.37      raeburn  4262:         if ($checkauth) {
                   4263:             $finish = "var authcheck = auth_check();\n".
                   4264:                       "   if (authcheck == 'ok') {\n".
                   4265:                       "       formname.submit();\n".
                   4266:                       "   }\n";
                   4267:         } else {
                   4268:             $finish = 'formname.submit()';
                   4269:         }
1.28      raeburn  4270:         $rolecode = "var match = str.split('_');
                   4271:                 var role = match[1];\n";
1.8       raeburn  4272:     } else {
1.28      raeburn  4273:         $checkincluded = 'formname.name == "'.$formname.'"'; 
1.8       raeburn  4274:         $finish = "seccheck = 'ok';";
1.28      raeburn  4275:         $rolecode = "var match = str.split('_');
                   4276:                 var role = match[1];\n";
1.11      raeburn  4277:         $setsection_js = "var seccheck = 'alert';"; 
1.8       raeburn  4278:     }
                   4279:     my %alerts = &Apache::lonlocal::texthash(
                   4280:                     secd => 'Section designations do not apply to Course Coordinator roles.',
                   4281:                     accr => 'A course coordinator role will be added with access to all sections.',
                   4282:                     inea => 'In each course, each user may only have one student role at a time.',
                   4283:                     youh => 'You had selected ',
                   4284:                     secs => 'sections.',
                   4285:                     plmo => 'Please modify your selections so they include no more than one section.',
                   4286:                     mayn => 'may not be used as the name for a section, as it is a reserved word.',
                   4287:                     plch => 'Please choose a different section name.',
                   4288:                     mnot => 'may not be used as a section name, as it is the name of a course group.',
                   4289:                     secn => 'Section names and group names must be distinct. Please choose a different section name.',
1.11      raeburn  4290:                  );                
1.8       raeburn  4291:     $setsection_js .= <<"ENDSECCODE";
                   4292: 
                   4293: function setSections(formname) {
                   4294:     var re1 = /^currsec_/;
                   4295:     var groups = new Array($groupslist);
                   4296:     for (var i=0;i<formname.elements.length;i++) {
                   4297:         var str = formname.elements[i].name;
                   4298:         var checkcurr = str.match(re1);
                   4299:         if (checkcurr != null) {
                   4300:             if ($checkincluded) {
1.28      raeburn  4301:                 $rolecode
1.8       raeburn  4302:                 if (role == 'cc') {
                   4303:                     alert("$alerts{'secd'}\\n$alerts{'accr'}");
                   4304:                 }
                   4305:                 else {
                   4306:                     var sections = '';
                   4307:                     var numsec = 0;
                   4308:                     var sections;
                   4309:                     for (var j=0; j<formname.elements[i].length; j++) {
                   4310:                         if (formname.elements[i].options[j].selected == true ) {
                   4311:                             if (formname.elements[i].options[j].value != "") {
                   4312:                                 if (numsec == 0) {
                   4313:                                     if (formname.elements[i].options[j].value != "") {
                   4314:                                         sections = formname.elements[i].options[j].value;
                   4315:                                         numsec ++;
                   4316:                                     }
                   4317:                                 }
                   4318:                                 else {
                   4319:                                     sections = sections + "," +  formname.elements[i].options[j].value
                   4320:                                     numsec ++;
                   4321:                                 }
                   4322:                             }
                   4323:                         }
                   4324:                     }
                   4325:                     if (numsec > 0) {
                   4326:                         if (formname.elements[i+1].value != "" && formname.elements[i+1].value != null) {
                   4327:                             sections = sections + "," +  formname.elements[i+1].value;
                   4328:                         }
                   4329:                     }
                   4330:                     else {
                   4331:                         sections = formname.elements[i+1].value;
                   4332:                     }
                   4333:                     var newsecs = formname.elements[i+1].value;
                   4334:                     var numsplit;
                   4335:                     if (newsecs != null && newsecs != "") {
                   4336:                         numsplit = newsecs.split(/,/g);
                   4337:                         numsec = numsec + numsplit.length;
                   4338:                     }
                   4339: 
                   4340:                     if ((role == 'st') && (numsec > 1)) {
                   4341:                         alert("$alerts{'inea'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}")
                   4342:                         return;
                   4343:                     }
                   4344:                     else {
                   4345:                         if (numsplit != null) {
                   4346:                             for (var j=0; j<numsplit.length; j++) {
                   4347:                                 if ((numsplit[j] == 'all') ||
                   4348:                                     (numsplit[j] == 'none')) {
                   4349:                                     alert("'"+numsplit[j]+"' $alerts{'mayn'}\\n$alerts{'plch'}");
                   4350:                                     return;
                   4351:                                 }
                   4352:                                 for (var k=0; k<groups.length; k++) {
                   4353:                                     if (numsplit[j] == groups[k]) {
                   4354:                                         alert("'"+numsplit[j]+"' $alerts{'mnot'}\\n$alerts{'secn'}");
                   4355:                                         return;
                   4356:                                     }
                   4357:                                 }
                   4358:                             }
                   4359:                         }
                   4360:                         formname.elements[i+2].value = sections;
                   4361:                     }
                   4362:                 }
                   4363:             }
                   4364:         }
                   4365:     }
                   4366:     $finish
                   4367: }
                   4368: ENDSECCODE
1.11      raeburn  4369:     return $setsection_js; 
1.8       raeburn  4370: }
                   4371: 
1.15      raeburn  4372: sub can_create_user {
                   4373:     my ($dom,$context,$usertype) = @_;
                   4374:     my %domconf = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
                   4375:     my $cancreate = 1;
1.28      raeburn  4376:     if (&Apache::lonnet::allowed('mau',$dom)) {
                   4377:         return $cancreate;
                   4378:     }
1.15      raeburn  4379:     if (ref($domconf{'usercreation'}) eq 'HASH') {
                   4380:         if (ref($domconf{'usercreation'}{'cancreate'}) eq 'HASH') {
                   4381:             if ($context eq 'course' || $context eq 'author') {
                   4382:                 my $creation = $domconf{'usercreation'}{'cancreate'}{$context};
                   4383:                 if ($creation eq 'none') {
                   4384:                     $cancreate = 0;
                   4385:                 } elsif ($creation ne 'any') {
                   4386:                     if (defined($usertype)) {
                   4387:                         if ($creation ne $usertype) {
                   4388:                             $cancreate = 0;
                   4389:                         }
                   4390:                     }
                   4391:                 }
                   4392:             }
                   4393:         }
                   4394:     }
                   4395:     return $cancreate;
                   4396: }
                   4397: 
1.20      raeburn  4398: sub can_modify_userinfo {
                   4399:     my ($context,$dom,$fields,$userroles) = @_;
                   4400:     my %domconfig =
                   4401:        &Apache::lonnet::get_dom('configuration',['usermodification'],
                   4402:                                 $dom);
                   4403:     my %canmodify;
                   4404:     if (ref($fields) eq 'ARRAY') {
                   4405:         foreach my $field (@{$fields}) {
                   4406:             $canmodify{$field}  = 0;
                   4407:             if (&Apache::lonnet::allowed('mau',$dom)) {
                   4408:                 $canmodify{$field} = 1;
                   4409:             } else {
                   4410:                 if (ref($domconfig{'usermodification'}) eq 'HASH') {
                   4411:                     if (ref($domconfig{'usermodification'}{$context}) eq 'HASH') {
                   4412:                         if (ref($userroles) eq 'ARRAY') {
                   4413:                             foreach my $role (@{$userroles}) {
                   4414:                                 my $testrole;
                   4415:                                 if ($role =~ /^cr\//) {
                   4416:                                     $testrole = 'cr';
                   4417:                                 } else {
                   4418:                                     $testrole = $role;
                   4419:                                 }
                   4420:                                 if (ref($domconfig{'usermodification'}{$context}{$testrole}) eq 'HASH') {
                   4421:                                     if ($domconfig{'usermodification'}{$context}{$testrole}{$field}) {
                   4422:                                         $canmodify{$field} = 1;
                   4423:                                         last;
                   4424:                                     }
                   4425:                                 }
                   4426:                             }
                   4427:                         } else {
                   4428:                             foreach my $key (keys(%{$domconfig{'usermodification'}{$context}})) {
                   4429:                                 if (ref($domconfig{'usermodification'}{$context}{$key}) eq 'HASH') {
                   4430:                                     if ($domconfig{'usermodification'}{$context}{$key}{$field}) {
                   4431:                                         $canmodify{$field} = 1;
                   4432:                                         last;
                   4433:                                     }
                   4434:                                 }
                   4435:                             }
                   4436:                         }
                   4437:                     }
                   4438:                 } elsif ($context eq 'course') {
                   4439:                     if (ref($userroles) eq 'ARRAY') {
                   4440:                         if (grep(/^st$/,@{$userroles})) {
                   4441:                             $canmodify{$field} = 1;
                   4442:                         }
                   4443:                     } else {
                   4444:                         $canmodify{$field} = 1;
                   4445:                     }
                   4446:                 }
                   4447:             }
                   4448:         }
                   4449:     }
                   4450:     return %canmodify;
                   4451: }
                   4452: 
1.18      raeburn  4453: sub check_usertype {
                   4454:     my ($dom,$uname,$rules) = @_;
                   4455:     my $usertype;
                   4456:     if (ref($rules) eq 'HASH') {
                   4457:         my @user_rules = keys(%{$rules});
                   4458:         if (@user_rules > 0) {
                   4459:             my %rule_check = &Apache::lonnet::inst_rulecheck($dom,$uname,undef,'username',\@user_rules);
                   4460:             if (keys(%rule_check) > 0) {
                   4461:                 $usertype = 'unofficial';
                   4462:                 foreach my $item (keys(%rule_check)) {
                   4463:                     if ($rule_check{$item}) {
                   4464:                         $usertype = 'official';
                   4465:                         last;
                   4466:                     }
                   4467:                 }
                   4468:             }
                   4469:         }
                   4470:     }
                   4471:     return $usertype;
                   4472: }
                   4473: 
1.17      raeburn  4474: sub roles_by_context {
                   4475:     my ($context,$custom) = @_;
                   4476:     my @allroles;
                   4477:     if ($context eq 'course') {
                   4478:         @allroles = ('st','ad','ta','ep','in','cc');
                   4479:         if ($custom) {
                   4480:             push(@allroles,'cr');
                   4481:         }
                   4482:     } elsif ($context eq 'author') {
                   4483:         @allroles = ('ca','aa');
                   4484:     } elsif ($context eq 'domain') {
                   4485:         @allroles = ('li','dg','sc','au','dc');
                   4486:     }
                   4487:     return @allroles;
                   4488: }
                   4489: 
1.16      raeburn  4490: sub get_permission {
1.17      raeburn  4491:     my ($context,$roles) = @_;
1.16      raeburn  4492:     my %permission;
                   4493:     if ($context eq 'course') {
1.17      raeburn  4494:         my $custom = 1;
                   4495:         my @allroles = &roles_by_context($context,$custom);
                   4496:         foreach my $role (@allroles) {
                   4497:             if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
                   4498:                 $permission{'cusr'} = 1;
                   4499:                 last;
                   4500:             }
1.16      raeburn  4501:         }
                   4502:         if (&Apache::lonnet::allowed('ccr',$env{'request.course.id'})) {
                   4503:             $permission{'custom'} = 1;
                   4504:         }
                   4505:         if (&Apache::lonnet::allowed('vcl',$env{'request.course.id'})) {
                   4506:             $permission{'view'} = 1;
                   4507:         }
                   4508:         if (!$permission{'view'}) {
                   4509:             my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
                   4510:             $permission{'view'} =  &Apache::lonnet::allowed('vcl',$scope);
                   4511:             if ($permission{'view'}) {
                   4512:                 $permission{'view_section'} = $env{'request.course.sec'};
                   4513:             }
                   4514:         }
1.17      raeburn  4515:         if (!$permission{'cusr'}) {
                   4516:             if ($env{'request.course.sec'} ne '') {
                   4517:                 my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
                   4518:                 $permission{'cusr'} = (&Apache::lonnet::allowed('cst',$scope));
                   4519:                 if ($permission{'cusr'}) {
                   4520:                     $permission{'cusr_section'} = $env{'request.course.sec'};
                   4521:                 }
                   4522:             }
                   4523:         }
1.16      raeburn  4524:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4525:             $permission{'grp_manage'} = 1;
                   4526:         }
                   4527:     } elsif ($context eq 'author') {
                   4528:         $permission{'cusr'} = &authorpriv($env{'user.name'},$env{'request.role.domain'});
                   4529:         $permission{'view'} = $permission{'cusr'};
                   4530:     } else {
1.17      raeburn  4531:         my @allroles = &roles_by_context($context);
                   4532:         foreach my $role (@allroles) {
1.28      raeburn  4533:             if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
                   4534:                 $permission{'cusr'} = 1;
1.17      raeburn  4535:                 last;
                   4536:             }
                   4537:         }
                   4538:         if (!$permission{'cusr'}) {
                   4539:             if (&Apache::lonnet::allowed('mau',$env{'request.role.domain'})) {
                   4540:                 $permission{'cusr'} = 1;
                   4541:             }
1.16      raeburn  4542:         }
                   4543:         if (&Apache::lonnet::allowed('ccr',$env{'request.role.domain'})) {
                   4544:             $permission{'custom'} = 1;
                   4545:         }
                   4546:         $permission{'view'} = $permission{'cusr'};
                   4547:     }
                   4548:     my $allowed = 0;
                   4549:     foreach my $perm (values(%permission)) {
                   4550:         if ($perm) { $allowed=1; last; }
                   4551:     }
                   4552:     return (\%permission,$allowed);
                   4553: }
                   4554: 
                   4555: # ==================================================== Figure out author access
                   4556: 
                   4557: sub authorpriv {
                   4558:     my ($auname,$audom)=@_;
                   4559:     unless ((&Apache::lonnet::allowed('cca',$audom.'/'.$auname))
                   4560:          || (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; }    return 1;
                   4561: }
                   4562: 
1.27      raeburn  4563: sub roles_on_upload {
1.42      raeburn  4564:     my ($context,$setting,%customroles) = @_;
1.27      raeburn  4565:     my (@possible_roles,@permitted_roles);
1.42      raeburn  4566:     @possible_roles = &curr_role_permissions($context,$setting,1);
1.27      raeburn  4567:     foreach my $role (@possible_roles) {
                   4568:         if ($role eq 'cr') {
                   4569:             push(@permitted_roles,keys(%customroles));
                   4570:         } else {
                   4571:             push(@permitted_roles,$role);
                   4572:         }
                   4573:     }
1.42      raeburn  4574:     return @permitted_roles;
1.27      raeburn  4575: }
                   4576: 
1.17      raeburn  4577: sub get_course_identity {
                   4578:     my ($cid) = @_;
                   4579:     my ($cnum,$cdom,$cdesc);
                   4580:     if ($cid eq '') {
                   4581:         $cid = $env{'request.course.id'}
                   4582:     }
                   4583:     if ($cid ne '') {
                   4584:         $cnum = $env{'course.'.$cid.'.num'};
                   4585:         $cdom = $env{'course.'.$cid.'.domain'};
                   4586:         $cdesc = $env{'course.'.$cid.'.description'};
                   4587:         if ($cnum eq '' || $cdom eq '') {
                   4588:             my %coursehash =
                   4589:                 &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
                   4590:             $cdom = $coursehash{'domain'};
                   4591:             $cnum = $coursehash{'num'};
                   4592:             $cdesc = $coursehash{'description'};
                   4593:         }
                   4594:     }
                   4595:     return ($cnum,$cdom,$cdesc);
                   4596: }
                   4597: 
1.19      raeburn  4598: sub dc_setcourse_js {
1.37      raeburn  4599:     my ($formname,$mode,$context) = @_;
                   4600:     my ($dc_setcourse_code,$authen_check);
1.19      raeburn  4601:     my $cctext = &Apache::lonnet::plaintext('cc');
                   4602:     my %alerts = &sectioncheck_alerts();
                   4603:     my $role = 'role';
                   4604:     if ($mode eq 'upload') {
                   4605:         $role = 'courserole';
1.37      raeburn  4606:     } else {
                   4607:         $authen_check = &verify_authen($formname,$context);
1.19      raeburn  4608:     }
                   4609:     $dc_setcourse_code = (<<"SCRIPTTOP");
1.37      raeburn  4610: $authen_check
                   4611: 
1.19      raeburn  4612: function setCourse() {
                   4613:     var course = document.$formname.dccourse.value;
                   4614:     if (course != "") {
                   4615:         if (document.$formname.dcdomain.value != document.$formname.origdom.value) {
                   4616:             alert("$alerts{'curd'}");
                   4617:             return;
                   4618:         }
                   4619:         var userrole = document.$formname.$role.options[document.$formname.$role.selectedIndex].value
                   4620:         var section="";
                   4621:         var numsections = 0;
                   4622:         var newsecs = new Array();
                   4623:         for (var i=0; i<document.$formname.currsec.length; i++) {
                   4624:             if (document.$formname.currsec.options[i].selected == true ) {
                   4625:                 if (document.$formname.currsec.options[i].value != "" && document.$formname.currsec.options[i].value != null) {
                   4626:                     if (numsections == 0) {
                   4627:                         section = document.$formname.currsec.options[i].value
                   4628:                         numsections = 1;
                   4629:                     }
                   4630:                     else {
                   4631:                         section = section + "," +  document.$formname.currsec.options[i].value
                   4632:                         numsections ++;
                   4633:                     }
                   4634:                 }
                   4635:             }
                   4636:         }
                   4637:         if (document.$formname.newsec.value != "" && document.$formname.newsec.value != null) {
                   4638:             if (numsections == 0) {
                   4639:                 section = document.$formname.newsec.value
                   4640:             }
                   4641:             else {
                   4642:                 section = section + "," +  document.$formname.newsec.value
                   4643:             }
                   4644:             newsecs = document.$formname.newsec.value.split(/,/g);
                   4645:             numsections = numsections + newsecs.length;
                   4646:         }
                   4647:         if ((userrole == 'st') && (numsections > 1)) {
                   4648:             alert("$alerts{'inea'}. $alerts{'youh'} "+numsections+" $alerts{'sect'}.\\n$alerts{'plsm'}.")
                   4649:             return;
                   4650:         }
                   4651:         for (var j=0; j<newsecs.length; j++) {
                   4652:             if ((newsecs[j] == 'all') || (newsecs[j] == 'none')) {
                   4653:                 alert("'"+newsecs[j]+"' $alerts{'mayn'}.\\n$alerts{'plsc'}.");
                   4654:                 return;
                   4655:             }
                   4656:             if (document.$formname.groups.value != '') {
                   4657:                 var groups = document.$formname.groups.value.split(/,/g);
                   4658:                 for (var k=0; k<groups.length; k++) {
                   4659:                     if (newsecs[j] == groups[k]) {
                   4660:                         alert("'"+newsecs[j]+"' $alerts{'mayt'}.\\n$alerts{'secn'}. $alerts{'plsc'}.");
                   4661:                         return;
                   4662:                     }
                   4663:                 }
                   4664:             }
                   4665:         }
                   4666:         if ((userrole == 'cc') && (numsections > 0)) {
                   4667:             alert("$alerts{'secd'} $cctext $alerts{'role'}.\\n$alerts{'accr'}.");
                   4668:             section = "";
                   4669:         }
                   4670: SCRIPTTOP
                   4671:     if ($mode ne 'upload') {
                   4672:         $dc_setcourse_code .= (<<"ENDSCRIPT");
                   4673:         var coursename = "_$env{'request.role.domain'}"+"_"+course+"_"+userrole
                   4674:         var numcourse = getIndex(document.$formname.dccourse);
                   4675:         if (numcourse == "-1") {
                   4676:             alert("$alerts{'thwa'}");
                   4677:             return;
                   4678:         }
                   4679:         else {
                   4680:             document.$formname.elements[numcourse].name = "act"+coursename;
                   4681:             var numnewsec = getIndex(document.$formname.newsec);
                   4682:             if (numnewsec != "-1") {
                   4683:                 document.$formname.elements[numnewsec].name = "sec"+coursename;
                   4684:                 document.$formname.elements[numnewsec].value = section;
                   4685:             }
                   4686:             var numstart = getIndex(document.$formname.start);
                   4687:             if (numstart != "-1") {
                   4688:                 document.$formname.elements[numstart].name = "start"+coursename;
                   4689:             }
                   4690:             var numend = getIndex(document.$formname.end);
                   4691:             if (numend != "-1") {
                   4692:                 document.$formname.elements[numend].name = "end"+coursename
                   4693:             }
                   4694:         }
                   4695:     }
1.37      raeburn  4696:     var authcheck = auth_check();
                   4697:     if (authcheck == 'ok') {
                   4698:         document.$formname.submit();
                   4699:     }
1.19      raeburn  4700: }
                   4701: ENDSCRIPT
                   4702:     } else {
                   4703:         $dc_setcourse_code .=  "
                   4704:         document.$formname.sections.value = section;
                   4705:     }
                   4706:     return 'ok';
                   4707: }
                   4708: ";
                   4709:     }
                   4710:     $dc_setcourse_code .= (<<"ENDSCRIPT");
                   4711: 
                   4712:     function getIndex(caller) {
                   4713:         for (var i=0;i<document.$formname.elements.length;i++) {
                   4714:             if (document.$formname.elements[i] == caller) {
                   4715:                 return i;
                   4716:             }
                   4717:         }
                   4718:         return -1;
                   4719:     }
                   4720: ENDSCRIPT
1.37      raeburn  4721:     return $dc_setcourse_code;
                   4722: }
                   4723: 
                   4724: sub verify_authen {
                   4725:     my ($formname,$context) = @_;
                   4726:     my %alerts = &authcheck_alerts();
                   4727:     my $finish = "return 'ok';";
                   4728:     if ($context eq 'author') {
                   4729:         $finish = "document.$formname.submit();";
                   4730:     }
                   4731:     my $outcome = <<"ENDSCRIPT";
                   4732: 
                   4733: function auth_check() {
                   4734:     var logintype;
                   4735:     if (document.$formname.login.length) {
                   4736:         if (document.$formname.login.length > 0) {
                   4737:             var loginpicked = 0;
                   4738:             for (var i=0; i<document.$formname.login.length; i++) {
                   4739:                 if (document.$formname.login[i].checked == true) {
                   4740:                     loginpicked = 1;
                   4741:                     logintype = document.$formname.login[i].value;
                   4742:                 }
                   4743:             }
                   4744:             if (loginpicked == 0) {
                   4745:                 alert("$alerts{'authen'}");
                   4746:                 return;
                   4747:             }
                   4748:         }
                   4749:     } else {
                   4750:         logintype = document.$formname.login.value;
                   4751:     }
                   4752:     if (logintype == 'nochange') {
                   4753:         return 'ok';
                   4754:     }
                   4755:     var argpicked = document.$formname.elements[logintype+'arg'].value;
                   4756:     if ((argpicked == null) || (argpicked == '') || (typeof argpicked == 'undefined')) {
                   4757:         var alertmsg = '';
                   4758:         switch (logintype) {
                   4759:             case 'krb':
                   4760:                 alertmsg = '$alerts{'krb'}';
                   4761:                 break;
                   4762:             case 'int':
                   4763:                 alertmsg = '$alerts{'ipass'}';
                   4764:             case 'fsys':
                   4765:                 alertmsg = '$alerts{'ipass'}';
                   4766:                 break;
                   4767:             case 'loc':
                   4768:                 alertmsg = '';
                   4769:                 break;
                   4770:             default:
                   4771:                 alertmsg = '';
                   4772:         }
                   4773:         if (alertmsg != '') {
                   4774:             alert(alertmsg);
                   4775:             return;
                   4776:         }
                   4777:     }
                   4778:     $finish
                   4779: }
                   4780: ENDSCRIPT
1.19      raeburn  4781: }
                   4782: 
                   4783: sub sectioncheck_alerts {
                   4784:     my %alerts = &Apache::lonlocal::texthash(
                   4785:                     curd => 'You must select a course in the current domain',
                   4786:                     inea => 'In each course, each user may only have one student role at a time',
                   4787:                     youh => 'You had selected',
                   4788:                     sect => 'sections',
                   4789:                     plsm => 'Please modify your selections so they include no more than one section',
                   4790:                     mayn => 'may not be used as the name for a section, as it is a reserved word',
                   4791:                     plsc => 'Please choose a different section name',
                   4792:                     mayt => 'may not be used as the name for a section, as it is the name of a course group',
                   4793:                     secn => 'Section names and group names must be distinct',
                   4794:                     secd => 'Section designations do not apply to ',
                   4795:                     role => 'roles',
                   4796:                     accr => 'role will be added with access to all sections',
                   4797:                     thwa => 'There was a problem with your course selection'
                   4798:                  );
                   4799:     return %alerts;
                   4800: }
1.17      raeburn  4801: 
1.37      raeburn  4802: sub authcheck_alerts {
                   4803:     my %alerts = 
                   4804:         &Apache::lonlocal::texthash(
                   4805:                     authen => 'You must choose an authentication type.',
                   4806:                     krb    => 'You need to specify the Kerberos domain.',
                   4807:                     ipass  => 'You need to specify the initial password.',
                   4808:         );
                   4809:     return %alerts;
                   4810: }
                   4811: 
1.1       raeburn  4812: 1;
                   4813: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.