File:  [LON-CAPA] / loncom / interface / lonuserutils.pm
Revision 1.171: download - view: text, annotated - select for diffs
Wed Aug 5 18:47:21 2015 UTC (8 years, 10 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
- Bug 5596.
  Add a routine to lonnet.pm -- get_multiple_instusers() which makes one call
  to lond > lonsql > localenroll.pm to retrieve institutional data
  for multiple users when adding users via file upload, to minimize number
  of sleep() commands needed. Supports up to 1s per query, on localenroll.pm
  side if adding more than 100 new users.

- Add new routine to localenroll.pm -- &get_multusersinfo() -- to retrieve
    institutional data for users being added via user file upload.

  Note: if this routine does not exist in localenroll.pm, will fall-back
  to retrieving institutional data using a separate call to &get_userinfo()
  for each user.

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>