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

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

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.