File:  [LON-CAPA] / loncom / interface / lonrequestcourse.pm
Revision 1.60: download - view: text, annotated - select for diffs
Wed Jan 5 18:47:46 2011 UTC (13 years, 4 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
- Authentication type and authentication arg (optional) need to be stored
  in course request for any users without existing accounts.
  Will use domain defaults if no usertype determined (i.e., no username
  format rules active).
  Otherwise will use values defined in localenroll::username_rules() for "official"
  users and internal auth with randomly generated password (e-mailed to new user)
  for "unofficial" users.

# The LearningOnline Network
# Request a course
#
# $Id: lonrequestcourse.pm,v 1.60 2011/01/05 18:47:46 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
###

=head1 NAME

Apache::lonrequestcourse.pm

=head1 SYNOPSIS

Allows users to request creation of new courses.

This is part of the LearningOnline Network with CAPA project
described at http://www.lon-capa.org.

=head1 SUBROUTINES

=over

=item handler()

=item get_breadcrumbs()

=item header()

=item form_elements()

=item onload_action()

=item print_main_menu()

=item request_administration()

=item close_popup_form()

=item get_instcode()

=item print_request_form()

=item print_enrollment_menu()

=item show_invalid_crosslists()

=item inst_section_selector()

=item date_setting_table()

=item print_personnel_menu()

=item print_request_status()

=item print_request_logs()

=item print_review()

=item dates_from_form()

=item courseinfo_form()

=item clone_form()

=item clone_text()

=item coursecode_form()

=item get_course_dom()

=item display_navbuttons()

=item print_request_outcome()

=item check_autolimit()

=item retrieve_settings()

=item get_request_settings()

=item extract_instcode() 

=item generate_date_items()

=back

=cut

package Apache::lonrequestcourse;

use strict;
use Apache::Constants qw(:common :http);
use Apache::lonnet;
use Apache::loncommon;
use Apache::lonlocal;
use Apache::loncoursequeueadmin;
use Apache::lonuserutils;
use LONCAPA qw(:DEFAULT :match);

sub handler {
    my ($r) = @_;
    &Apache::loncommon::content_type($r,'text/html');
    $r->send_http_header;
    if ($r->header_only) {
        return OK;
    }

    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
        ['action','showdom','cnum','state','crstype','queue']);
    &Apache::lonhtmlcommon::clear_breadcrumbs();
    my $dom = &get_course_dom();
    my $action = $env{'form.action'};
    my $state = $env{'form.state'};
    my (%states,%stored);
    my ($jscript,$uname,$udom,$result,$warning);

    $states{'display'} = ['details'];
    $states{'view'} = ['pick_request','details','cancel','removal'];
    $states{'log'} = ['display'];
    $states{'new'} = ['courseinfo','enrollment','personnel','review','process'];

    if (($action eq 'new') && ($env{'form.crstype'} eq 'official')) {
        unless ($env{'form.state'} eq 'crstype') {
            unshift(@{$states{'new'}},'codepick');
        }
    }

    foreach my $key (keys(%states)) {
        if (ref($states{$key}) eq 'ARRAY') {
            unshift (@{$states{$key}},'crstype');
        }
    }

    my @invalidcrosslist;
    my %trail = (
                 crstype       => 'Request Action',
                 codepick      => 'Category',
                 courseinfo    => 'Description',
                 enrollment    => 'Access Dates',
                 personnel     => 'Personnel',
                 review        => 'Review',
                 process       => 'Result',
                 pick_request  => 'Display Summary',
                 details       => 'Request Details',
                 cancel        => 'Cancel Request',
                 removal       => 'Outcome',
                 display       => 'Request Logs',
                );

    if (($env{'form.crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) {
        $trail{'enrollment'} = 'Enrollment';
    }

    my ($page,$crumb,$newinstcode,$codechk,$checkedcode,$description) = 
        &get_breadcrumbs($dom,$action,\$state,\%states,\%trail);
    if ($action eq 'display') {
        if (($dom eq $env{'request.role.domain'}) && (&Apache::lonnet::allowed('ccc',$dom))) {
            if ($env{'form.cnum'} ne '') {
                my $cnum = $env{'form.cnum'};
                my $queue = $env{'form.queue'};
                my $reqkey = $cnum.'_'.$queue;
                my $namespace = 'courserequestqueue';
                my $domconfig = &Apache::lonnet::get_domainconfiguser($dom);
                my %queued =
                    &Apache::lonnet::get($namespace,[$reqkey],$dom,$domconfig);
                if (ref($queued{$reqkey}) eq 'HASH') {
                    $uname = $queued{$reqkey}{'ownername'};
                    $udom  = $queued{$reqkey}{'ownerdom'};
                    if (($udom =~ /^$match_domain$/) && ($uname =~ /^$match_username$/)) {
                        $result = &retrieve_settings($dom,$cnum,$udom,$uname);
                    } else {
                        if ($env{'form.crstype'} eq 'community') {
                            $warning = &mt('Invalid username or domain for community requestor');
                        } else {
                            $warning = &mt('Invalid username or domain for course requestor');
                        }
                    }
                } else {
                    if ($env{'form.crstype'} eq 'community') {
                        $warning = &mt('No information was found for this community request.');
                    } else {
                        $warning = &mt('No information was found for this course request.');
                    }
                }
            } else {
                $warning = &mt('No course request ID provided.');
            }
        } else {
            if ($env{'form.crstype'} eq 'any') {
               $warning = &mt('You do not have rights to view course or community request information.');
            } elsif ($env{'form.crstype'} eq 'community') {
                $warning = &mt('You do not have rights to view community request information.');
            } else {
                $warning = &mt('You do not have rights to view course request information.');
            }
        }
    } elsif ((defined($state)) && (defined($action))) {
        if (($action eq 'view') && ($state eq 'details')) {
            if ((defined($env{'form.showdom'})) && (defined($env{'form.cnum'}))) {
                my $result = &retrieve_settings($env{'form.showdom'},$env{'form.cnum'});
            }
        } elsif ($env{'form.crstype'} eq 'official') {
            if (&Apache::lonnet::auto_run('',$dom)) {
                if (($action eq 'new') && (($state eq 'enrollment') || 
                    ($state eq 'personnel'))) {
                    my $checkcrosslist = 0;
                    for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
                        if ($env{'form.crosslist_'.$i}) {
                            $checkcrosslist ++;
                        }
                    }
                    if ($checkcrosslist) {
                        my %codechk;
                        my (@codetitles,%cat_titles,%cat_order,@code_order,$lastitem);
                        &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,
                                                                 \%cat_titles,
                                                                 \%cat_order,
                                                                 \@code_order);
                        my $numtitles = scalar(@codetitles);
                        if ($numtitles) {
                            for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
                                if ($env{'form.crosslist_'.$i}) {
                                    my $codecheck;
                                    my $crosslistcode = '';
                                    foreach my $item (@code_order) {
                                        $crosslistcode .= $env{'form.crosslist_'.$i.'_'.$item}; 
                                    }
                                    if ($crosslistcode ne '') { 
                                         ($codechk{$i}, my $rest) = 
                                            &Apache::lonnet::auto_validate_instcode('',$dom,$crosslistcode);
                                    }
                                    unless ($codechk{$i} eq 'valid') {
                                        $env{'form.crosslist_'.$i} = '';
                                        push(@invalidcrosslist,$crosslistcode);
                                    } 
                                }
                            }
                        }
                    }
                }
            }
        }
        my %elements =  &form_elements($dom);
        my $elementsref = {};
        if (ref($elements{$action}) eq 'HASH') {
            if (ref($elements{$action}{$state}) eq 'HASH') {
                $elementsref = $elements{$action}{$state};
            }
        }
        if (($state eq 'courseinfo') && ($env{'form.clonedom'} eq '')) {
            $env{'form.clonedom'} = $dom;
        }
        if ($state eq 'crstype') {
            $jscript = &mainmenu_javascript();
        } else {
            $jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored);
            if ($state eq 'courseinfo') {
                $jscript .= &cloning_javascript();
            }
        }
    }

    if ($state eq 'personnel') {
        $jscript .= "\n".&Apache::loncommon::userbrowser_javascript();
    }

    my $loaditems = &onload_action($action,$state);

    my (%can_request,%request_domains);
    my $canreq = 
        &Apache::lonnet::check_can_request($dom,\%can_request,\%request_domains);
    if ($action eq 'new') {
        if ($canreq) {
            if ($state eq 'crstype') {
                &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems,
                                 $crumb,\%request_domains);
            } else {
                &request_administration($r,$action,$state,$page,\%states,$dom,
                                        $jscript,$loaditems,$crumb,$newinstcode,
                                        $codechk,$checkedcode,$description,
                                        \@invalidcrosslist);
            }
        } else {
            $r->print(&header('Course/Community Requests').$crumb.
                      '<div class="LC_warning">'.
                      &mt('You do not have privileges to request creation of courses or communities.').
                      '</div>'.&Apache::loncommon::end_page());
        }
    } elsif ($action eq 'view') {
        if ($state eq 'crstype') {
            &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems,$crumb,\%request_domains);
        } else {
            &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
                                    $loaditems,$crumb);
        }
    } elsif ($action eq 'display') {
        if ($warning ne '') {
            my $args = { only_body => 1 };
            $r->print(&header('Course/Community Requests','','' ,'',$args).$crumb.
                      '<h3>'.&mt('Course/Community Request Details').'</h3>'.
                      '<div class="LC_warning">'.$warning.'</div>'.
                      &close_popup_form());
        } else {
            &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
                                    $loaditems,$crumb,'','','','','',$uname,$udom);
        }
    } elsif ($action eq 'log') {
        if ($state eq 'crstype') {
            &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb,\%request_domains);
        } else {
            $jscript .= <<ENDJS;

function backPage(formname,prevstate) {
    formname.state.value = prevstate;
    formname.submit();
}

function setPage(formname) {
    formname.page.value = '1';
    return;
}

ENDJS
            &print_request_logs($r,$dom,$jscript,$loaditems,$crumb);
        }
    } else {
        &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb,\%request_domains);
    }
    return OK;
}

sub mainmenu_javascript {
    return <<"END";
function setType(courseForm) {
    for (var i=0; i<courseForm.crstype.length; i++) {
        if (courseForm.crstype.options[i].value == "$env{'form.crstype'}") {
            courseForm.crstype.options[i].selected = true;
        } else {
            courseForm.crstype.options[i].selected = false;
        }
    }
}

function setAction(courseForm) {
    for (var i=0; i<courseForm.action.length; i++) {
        if (courseForm.action.options[i].value == "$env{'form.action'}") {
            courseForm.action.options[i].selected = true;
        } else {
            courseForm.action.options[i].selected = false;
        }
    }
}
END
}

sub cloning_javascript {
    return <<"END";
function setCloneDisplay(courseForm) {
    if (courseForm.cloning.length > 1) {    
        for (var i=0; i<courseForm.cloning.length; i++) {
            if (courseForm.cloning[i].checked) {
                if (courseForm.cloning[i].value == 1) {
                    document.getElementById('cloneoptions').style.display="block";;
                }
            }
        }
    }
}
END
}

sub get_breadcrumbs {
    my ($dom,$action,$state,$states,$trail) = @_;
    my ($crumb,$newinstcode,$codechk,$checkedcode,$numtitles,$description);
    my $page = 0;
    if ((ref($states) eq 'HASH') && (ref($trail) eq 'HASH') && (ref($state))) {
        if (defined($action)) {
            my $done = 0;
            my $i=0;
            if (ref($states->{$action}) eq 'ARRAY') {
                while ($i<@{$states->{$action}} && !$done) {
                    if ($states->{$action}[$i] eq $$state) {
                        $page = $i;
                        $done = 1;
                    }
                    $i++;
                }
            }
            if ($env{'form.crstype'} eq 'official') {
                if ($page > 1) {
                    if ($states->{$action}[$page-1] eq 'codepick') {
                        if ($env{'form.instcode'} eq '') {
                            ($newinstcode,$numtitles) = &get_instcode($dom);
                            if ($numtitles) {
                                if ($newinstcode eq '') {
                                    $$state = 'codepick';
                                    $page --;
                                } else {
                                    ($codechk,$description) = 
                                        &Apache::lonnet::auto_validate_instcode('',
                                            $dom,$newinstcode);
                                    if ($codechk ne 'valid') {
                                        $$state = 'codepick';
                                        $page --;
                                    }
                                    $checkedcode = 1;
                                }
                            }
                        }
                    }
                }
            }
            for (my $i=0; $i<@{$states->{$action}}; $i++) {
                if ($$state eq $states->{$action}[$i]) {
                    &Apache::lonhtmlcommon::add_breadcrumb(
                       {text=>"$trail->{$$state}"});
                    $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course/Community Requests','Course_Requests');
                    last;
                } else {
                    if (($$state eq 'process') || ($$state eq 'removal')) {
                        &Apache::lonhtmlcommon::add_breadcrumb(
                            { href => '/adm/requestcourse',
                              text => "$trail->{$states->{$action}[$i]}",
                            }
                        );
                    } else {
                        &Apache::lonhtmlcommon::add_breadcrumb(
     { href => "javascript:backPage(document.requestcrs,'$states->{$action}[$i]')",
       text => "$trail->{$states->{$action}[$i]}", }
                       );
                   }
               }
           }
        } else {
            &Apache::lonhtmlcommon::add_breadcrumb(
                    {text=>'Pick Action'});
            $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course/Community Requests','Course_Requests');
        }
    } else {
        &Apache::lonhtmlcommon::add_breadcrumb(
                {text=>'Pick Action'});
        $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course/Community Requests','Course_Requests');
    }
    return ($page,$crumb,$newinstcode,$codechk,$checkedcode,$description);
}

sub header {
    my ($bodytitle,$jscript,$loaditems,$jsextra,$args) = @_;
    if ($jscript) {
        $jscript = '<script type="text/javascript">'."\n".
                   '// <![CDATA['."\n".
                   $jscript."\n".'// ]]>'."\n".'</script>'."\n";
    }
    if ($loaditems) {
        if (ref($args) eq 'HASH') {
            my %loadhash = (
                             'add_entries' => $loaditems,
                           );
            my %arghash = (%loadhash,%{$args});
            $args = \%arghash;                  
        } else {
            $args = {'add_entries' => $loaditems,};
        }
    }
    return &Apache::loncommon::start_page($bodytitle,$jscript.$jsextra,$args);
}

sub form_elements {
    my ($dom) = @_;
    my %elements =
    (
        new => {
            crstype => {
                crstype => 'selectbox',
                action  => 'selectbox',
                origcnum => 'hidden', 
            },
            courseinfo => {
                cdescr           => 'text',
                cloning          => 'radio', 
                clonecrs         => 'text',
                clonedom         => 'selectbox',
                datemode         => 'radio',
                dateshift        => 'text',
            },
            enrollment  => {
                accessstart_month  => 'selectbox',
                accessstart_hour   => 'selectbox',
                accessend_month    => 'selectbox',
                accessend_hour     => 'selectbox',
                accessstart_day    => 'text',
                accessstart_year   => 'text',
                accessstart_minute => 'text',
                accessstart_second => 'text',
                accessend_day      => 'text',
                accessend_year     => 'text',
                accessend_minute   => 'text',
                accessend_second   => 'text',
                no_end_date      => 'checkbox',
            },
            personnel => {
                addperson   => 'checkbox', 
            },
            review => {
                cnum => 'hidden',
            },
         },
         view => {
            crstype => {
                crstype => 'selectbox',
                action  => 'selectbox',
            },
         },
    );
    my %servers = &Apache::lonnet::get_servers($dom,'library');
    my $numlib = keys(%servers);
    if ($numlib > 1) {
        $elements{'new'}{'courseinfo'}{'chome'} = 'selectbox';
    } else {
        $elements{'new'}{'courseinfo'}{'chome'} = 'hidden';
    }
    my (@codetitles,%cat_titles,%cat_order,@code_order,$lastitem);
    &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                             \%cat_order,\@code_order);
    my $numtitles = scalar(@codetitles);
    if ($numtitles) {
        my %extras;
        $lastitem = pop(@codetitles);
        $extras{'instcode_'.$lastitem} = 'text'; 
        foreach my $item (@codetitles) {
            $extras{'instcode_'.$item} = 'selectbox';   
        }
        $elements{'new'}{'codepick'} = \%extras;
    }
    if (&Apache::lonnet::auto_run('',$dom)) {
        my %extras = (
                       sectotal           => 'hidden',
                       enrollstart_month  => 'selectbox',
                       enrollstart_hour   => 'selectbox',
                       enrollend_month    => 'selectbox',
                       enrollend_hour     => 'selectbox',
                       enrollstart_day    => 'text',
                       enrollstart_year   => 'text',
                       enrollstart_minute => 'text',
                       enrollstart_second => 'text',
                       enrollend_day      => 'text',
                       enrollend_year     => 'text',
                       enrollend_minute   => 'text',
                       enrollend_second   => 'text',
                       addcrosslist       => 'checkbox',
                       autoadds           => 'radio',
                       autodrops          => 'radio',
                     );
        if ($env{'form.sectotal'} > 0) {
            for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
                $extras{'sec_'.$i} = 'radio';
                $extras{'secnum_'.$i} = 'text';
                $extras{'loncapasec_'.$i} = 'text';
            }
        }
        my $crosslisttotal = $env{'form.crosslisttotal'};
        if ($env{'form.addcrosslist'}) {
            $crosslisttotal ++;
        }
        if (!$crosslisttotal) {
            $crosslisttotal = 1;
        }

        for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
            if ($numtitles) {
                $extras{'crosslist_'.$i.'_'.$lastitem} = 'text';
            }
            if (@codetitles > 0) {
                foreach my $item (@codetitles) {
                    $extras{'crosslist_'.$i.'_'.$item} = 'selectbox';
                }
            }
            $extras{'crosslist_'.$i} = 'checkbox';
            $extras{'crosslist_'.$i.'_instsec'} = 'text',
            $extras{'crosslist_'.$i.'_lcsec'} = 'text',
        }
        my %mergedhash = (%{$elements{'new'}{'enrollment'}},%extras);
        %{$elements{'new'}{'enrollment'}} = %mergedhash;
    }
    my %people;
    my $persontotal = $env{'form.persontotal'};
    if ($env{'form.addperson'}) {
        $persontotal ++;
    }
    if ((!defined($persontotal)) || (!$persontotal)) {
        $persontotal = 1;
    }
    for (my $i=0; $i<$persontotal; $i++) {
        $people{'person_'.$i.'_uname'}     = 'text',
        $people{'person_'.$i.'_dom'}       = 'selectbox',
        $people{'person_'.$i.'_hidedom'}   = 'hidden',
        $people{'person_'.$i.'_firstname'} = 'text',
        $people{'person_'.$i.'_lastname'}  = 'text',
        $people{'person_'.$i.'_emailaddr'} = 'text',
        $people{'person_'.$i.'_role'}      = 'selectbox',
        $people{'person_'.$i.'_sec'}       = 'selectbox',
        $people{'person_'.$i.'_newsec'}    = 'text',
    }
    my %personnelhash = (%{$elements{'new'}{'personnel'}},%people);
    %{$elements{'new'}{'personnel'}} = %personnelhash;
    return %elements;
}

sub onload_action {
    my ($action,$state) = @_;
    my %loaditems;
    if (($action eq 'new') || ($action eq 'view')) {
        if ($state eq 'crstype') {
            $loaditems{'onload'} = 'javascript:setAction(document.mainmenu_action);javascript:setType(document.mainmenu_coursetype)';
        } else {
            $loaditems{'onload'} = 'javascript:setFormElements(document.requestcrs);';
        }
        if ($state eq 'courseinfo') {
            $loaditems{'onload'} .= 'javascript:setCloneDisplay(document.requestcrs);';
        }
    }
    return \%loaditems;
}

sub print_main_menu {
    my ($r,$can_request,$states,$dom,$jscript,$loaditems,$crumb,$request_domains) = @_;
    my ($types,$typename) = &Apache::loncommon::course_types();
    my $onchange = 'this.form.submit()';
    my $nextstate_setter = "\n";
    if (ref($states) eq 'HASH') {
        foreach my $key (keys(%{$states})) {
            if (ref($states->{$key}) eq 'ARRAY') {
                $nextstate_setter .= 
"             if (actionchoice == '$key') {
                  nextstate = '".$states->{$key}[1]."';
             }
";
            }
        }
    }

    my $js = <<"END";

function nextPage(formname) {
    var crschoice = document.mainmenu_coursetype.crstype.value;
    var actionchoice = document.mainmenu_action.action.value;
    if (check_can_request(crschoice,actionchoice) == true) {
        if ((actionchoice == 'new') && (crschoice == 'official')) {
            nextstate = 'codepick';
        } else {
$nextstate_setter 
        }
        formname.crstype.value = crschoice;
        formname.action.value = actionchoice; 
        formname.state.value= nextstate;
        formname.submit();
    }
    return;
}

function check_can_request(crschoice,actionchoice) {
    var official = '';
    var unofficial = '';
    var community = '';    
END
    if (ref($can_request) eq 'HASH') {
        foreach my $item (keys(%{$can_request})) {
                $js .= " 
        $item = 1;
";
        }
    }
    my %lt = &Apache::lonlocal::texthash(
        official => 'You are not permitted to request creation of an official course in this domain.',
        unofficial => 'You are not permitted to request creation of an unofficial course in this domain.',
        community => 'You are not permitted to request creation of a community this domain.',
        all => 'You must choose a specific course type when making a new course request.\\n\"All types\" is not allowed.',
    ); 
    $js .= <<END;
    if (crschoice == 'official') {
        if (official != 1) {
            alert("$lt{'official'}");
            return false;
        }
    } else {
        if (crschoice == 'unofficial') {
            if (unofficial != 1) {
                alert("$lt{'unofficial'}");
                return false;
            }
        } else {
            if (crschoice == 'community') {
                if (community != 1) {
                    alert("$lt{'community'}");
                    return false;
                }
            } else {
                if (actionchoice == 'new') {
                    alert("$lt{'all'}");
                    return false;
                }               
            }
        }
    }
    return true;
}
END
    my ($pagetitle,$pageinfo,$domaintitle);
    if (ref($can_request) eq 'HASH') {
        if (($can_request->{'official'}) || ($can_request->{'unofficial'})) {
            if ($can_request->{'community'}) {
                $pagetitle = 'Course/Community Requests';
                $pageinfo = &mt('Request creation of a new course or community, or review your pending requests.');
                $domaintitle = &mt('Course/Community Domain');
            } else {
                $pagetitle = 'Course Requests';
                $pageinfo = &mt('Request creation of a new course, or review your pending course requests.');
                $domaintitle = &mt('Course Domain');
            }
        } elsif ($can_request->{'community'}) {
            $pagetitle = 'Community Requests';
            $pageinfo = &mt('Request creation of a new course, or review your pending requests.');
            $domaintitle = &mt('Community Domain');
        } else {
            $pagetitle = 'Course/Community Requests';
            $pageinfo = &mt('You do not have rights to request creation of courses in this domain; please choose a different domain.');
            $domaintitle = &mt('Course/Community Domain');
        }
    }
    my @incdoms;
    if (ref($request_domains) eq 'HASH') {
        foreach my $item (keys(%{$request_domains})) {
            if (ref($request_domains->{$item}) eq 'ARRAY') {
                foreach my $possdom (@{$request_domains->{$item}}) {
                    unless(grep(/^\Q$possdom\E$/,@incdoms)) {
                        push(@incdoms,$possdom);
                    } 
                } 
            }
        }
    }
    $r->print(&header($pagetitle,$js.$jscript,$loaditems).$crumb.
             '<p>'.$pageinfo.'</p>'.
             '<div>'.
              &Apache::lonhtmlcommon::start_pick_box().
              &Apache::lonhtmlcommon::row_title($domaintitle).
              '<form name="domforcourse" method="post" action="/adm/requestcourse">'.
              &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange,\@incdoms));
    if (!$onchange) {
        $r->print('&nbsp;<input type="submit" name="godom" value="'.
                   &mt('Change').'" />');
    }
    unless ((ref($can_request) eq 'HASH') && (keys(%{$can_request}) > 0)) {
        $r->print(&Apache::lonhtmlcommon::row_closure(1)."\n".
                  &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n".
                  &Apache::loncommon::end_page());
        return;
    }
    $r->print('</form>'.&Apache::lonhtmlcommon::row_closure());
    my $formname = 'requestcrs';
    my $nexttext = &mt('Next');
    $r->print(&Apache::lonhtmlcommon::row_title(&mt('Action')).'
<form name="mainmenu_action" method="post" action=""> 
<select size="1" name="action" >
 <option value="new">'.&mt('New request').'</option>
 <option value="view">'.&mt('View/Modify/Cancel pending requests').'</option>
 <option value="log">'.&mt('View request history').'</option>
</select></form>'.
              &Apache::lonhtmlcommon::row_closure().
              &Apache::lonhtmlcommon::row_title(&mt('Type')).'
<form name="mainmenu_coursetype" method="post" action="">
<select size="1" name="crstype">');
    if (ref($can_request) eq 'HASH') {
        if (keys(%{$can_request}) > 1) {
            $r->print(' <option value="any">'.&mt('All types').'</option>');
        }
        if ((ref($types) eq 'ARRAY') && (ref($typename) eq 'HASH')) {
            foreach my $type (@{$types}) {
                next unless($can_request->{$type});
                my $selected = '';
                if ($env{'form.crstype'} eq '') {
                    if ($type eq 'official') {
                        $selected = ' selected="selected"';
                    }
                } else {
                    if ($type eq $env{'form.crstype'}) {
                        $selected = ' selected="selected"';
                    }
                }
                $r->print('<option value="'.$type.'"'.$selected.'>'.&mt($typename->{$type}).
                          '</option>'."\n");
            }
        }
    }
    $r->print('</select></form>'."\n".
              &Apache::lonhtmlcommon::row_closure(1)."\n".
              &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n".
              '<div><form name="'.$formname.'" method="post" action="/adm/requestcourse">'."\n".
              '<input type="hidden" name="state" value="crstype" />'."\n".
              '<input type="hidden" name="showdom" value="'.$dom.'" />'."\n".
              '<input type="hidden" name="crstype" value="" />'."\n".
              '<input type="hidden" name="action" value="" />'."\n".
              '<input type="button" name="next" value="'.$nexttext.
              '" onclick="javascript:nextPage(document.'.$formname.')" />'."\n".
              '</form></div>');
    $r->print(&Apache::loncommon::end_page());
    return;
}

sub request_administration {
    my ($r,$action,$state,$page,$states,$dom,$jscript,$loaditems,$crumb,
        $newinstcode,$codechk,$checkedcode,$description,$invalidcrosslist,
        $uname,$udom) = @_;
    my $js;
    if (($action eq 'new') || (($action eq 'view') && ($state eq 'pick_request'))) {
        $js =  <<END;

function nextPage(formname,nextstate) {
    formname.state.value= nextstate;
    formname.submit();
}

END
    }
    if (($action eq 'new') || ($action eq 'view')) {
        $js .= <<END;   

function backPage(formname,prevstate) {
    formname.state.value = prevstate;
    formname.submit();
}

END
    }
    if ($action eq 'new') {
        my $jsextra;
        if (($state eq 'courseinfo') || ($state eq 'codepick')) {
            $jsextra = "\n".&Apache::loncommon::coursebrowser_javascript($dom);
        } elsif ($state eq 'enrollment') {
            if (($env{'form.crstype'} eq 'official') && 
                (&Apache::lonnet::auto_run('',$dom))) {
                $js .= "\n".&section_check_javascript()."\n".&enrollment_lcsec_js();
            }
        } elsif ($state eq 'personnel') {
            $js .= "\n".&section_check_javascript()."\n".&personnel_lcsec_js();
        }
        my $title;
        if ($env{'form.crstype'} eq 'community') {
            $title = 'Request a community';
        } else {
            $title = 'Request a course';
        }
        $r->print(&header($title,$js.$jscript,$loaditems,$jsextra).$crumb);
        &print_request_form($r,$action,$state,$page,$states,$dom,$newinstcode,
                            $codechk,$checkedcode,$description,$invalidcrosslist);
    } elsif ($action eq 'view') {
        my $jsextra;
        my $formname = 'requestcrs';
        my $prev = $states->{$action}[$page-1];
        my $next = $states->{$action}[$page+1];
        if ($state eq 'pick_request') {
            $next = $states->{$action}[$page+1];
            $jsextra = &viewrequest_javascript($formname,$next);
        } elsif ($state eq 'details') {
            $jsextra = &viewdetails_javascript($formname);

        } elsif ($state eq 'cancel') {
            $jsextra = &viewcancel_javascript($formname);
        }
        my $title;
        if ($env{'form.crstype'} eq 'community') {
            $title = 'Manage community requests';
        } else {
            $title = 'Manage course requests';
        }
        $r->print(&header($title,$js.$jscript.$jsextra,$loaditems).$crumb);
        my $form = '<form method="post" name="'.$formname.'" action="/adm/requestcourse" />';
        if ($state eq 'pick_request') {
            my $title;
            if ($env{'form.crstype'} eq 'community') {
                $title = &mt('Pending community requests');
            } elsif ($env{'form.crstype'} eq 'official') {
                $title = &mt('Pending requests for official courses');
            } elsif ($env{'form.crstype'} eq 'unofficial') {
                $title = &mt('Pending requests for unofficial courses');
            } else {
                $title = &mt('Pending course/community requests'); 
            }
            $r->print('<h3>'.$title.'</h3><div>'."\n".$form."\n".
                      &print_request_status($dom,$action).'</form></div>');
        } elsif ($state eq 'details') {
            my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
            my $origcnum = $env{'form.cnum'};
            if ($origcnum eq '') {
                $origcnum = $env{'form.origcnum'};   
            }
            if ($env{'form.crstype'} eq 'official') {
                &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                                         \%cat_order,\@code_order);
            }
            my $title;
            if ($env{'form.crstype'} eq 'community') {
                $title = &mt('Community Request Details');
            } else {
                $title = &mt('Course Request Details');
            }
            $r->print('<h3>'.$title.'</h3><div>'."\n".$form."\n".
                      &print_review($dom,\@codetitles,\%cat_titles,\%cat_order,
                                    \@code_order)."\n".
                      '<input name="origcnum" value="'.$origcnum.'" type="hidden" />'."\n");
            my @excluded = &get_excluded_elements($dom,$states,'new','review');
            push(@excluded,'origcnum');
            $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</div>');
            my $other = 'modify';
            my %navtxt = &Apache::lonlocal::texthash (
                                                      prev => 'Back',
                                                      other => 'Modify Request',
                                                      next => 'Cancel Request',
                                                     );
            &display_navbuttons($r,$dom,$formname,$prev,$navtxt{'prev'},$next,
                                $navtxt{'next'},$state,$other,$navtxt{'other'});
            $r->print('</form>');
        } elsif ($state eq 'cancel') {
            my $title;
            if ($env{'form.crstype'} eq 'community') {
                $title = &mt('Cancel community request');
            } else {
                $title = &mt('Cancel course request');
            }
            my ($result,$output) = &print_cancel_request($dom,$env{'form.origcnum'});
            $r->print('<h3>'.$title.'</h3><div>'."\n".$form."\n".
                      $output);
            my @excluded = &get_excluded_elements($dom,$states,'view','cancel');
            $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</div>');
            my %navtxt = &Apache::lonlocal::texthash (
                                                      prev => 'Back',
                                                      next => 'Confirm Cancellation',
                                                     );
            if ($result eq 'ok') {
                &display_navbuttons($r,$dom,$formname,$prev,$navtxt{'prev'},$next,
                                    $navtxt{'next'},$state);
            } else {
                &display_navbuttons($r,$dom,$formname,$prev,$navtxt{'prev'},undef,
                                    '',$state);
            }
            $r->print('</form>');
        } elsif ($state eq 'removal') {
            my $cnum = $env{'form.origcnum'};
            my $statuskey = 'status:'.$dom.':'.$cnum;
            my %userreqhash = &Apache::lonnet::get('courserequests',[$statuskey],
                                                   $env{'user.domain'},$env{'user.name'});
            my $currstatus = $userreqhash{$statuskey};
            my ($result,$error); 
            if (($currstatus eq 'approval') || ($currstatus eq 'pending')) { 
                my %status = (
                                 $statuskey => 'cancelled',
                             );
                my $statusresult = &Apache::lonnet::put('courserequests',\%status);
                if ($statusresult eq 'ok') {
                    my $delresult = 
                        &Apache::lonnet::del_dom('courserequestqueue',
                                                 [$cnum.'_'.$currstatus],$dom);
                    if ($delresult eq 'ok') {
                        $result = 'ok';
                    } else {
                        $error = &mt('An error occurred when updating the pending requests queue: [_1]',$delresult);
                    }
                } else {
                    $error = &mt("An error occurred when updating the status of this request in the requestor's records: [_1]",$statusresult);
                }
            } else {
                $error = &mt('The current status of this request could not be verified as pending approval/institutional action.');  
            }
            $r->print('<h3>'.&mt('Request Cancellation').'</h3><div>'."\n".$form."\n".
                      '<input type="hidden" name="state" value="'.$state.'" />'."\n".
                      '<input type="hidden" name="action" value="'.$action.'" />'."\n".
                      '<input type="hidden" name="showdom" value="'.$dom.'" />'."\n".
                      '<input type="hidden" name="orignum" value="'.$cnum.'" />'."\n");
            if ($result eq 'ok') {
                if ($env{'form.crstype'} eq 'community') {
                    $r->print(&mt('Your community request has been cancelled.'));
                } else {
                    $r->print(&mt('Your course request has been cancelled.'));
                }
            } else {
                $r->print('<div class="LC_error">'.
                          &mt('The request cancellation process was not complete.').
                          '<br />'.$error.'</div>');
            }
            $r->print('</form>');
        }
    } elsif ($action eq 'display') {
        my $formname = 'requestcrs';
        my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
        if ($env{'form.crstype'} eq 'official') {
            &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                                     \%cat_order,\@code_order);
        }
        my ($title,$header);
        if ($env{'form.crstype'} eq 'community') {
            $title = 'Community Request';
            $header = &mt('Community Request');
        } else {
            $title = 'Course Request';
            $header = &mt('Course Request');
        }
        $r->print(&header($title,'','','',{ 'only_body' => 1}).
                  $crumb."\n".'<h3>'.$header.'</h3>'.
                  &print_review($dom,\@codetitles,\%cat_titles,\%cat_order,
                                \@code_order,$uname,$udom)."\n".'</div>'.
                  &close_popup_form());
    }
    $r->print(&Apache::loncommon::end_page());
    return;
}

sub enrollment_lcsec_js {
    my %alerts = &section_check_alerts();
    my $secname = $alerts{'badsec'};
    my $secnone = $alerts{'reserved'};
    my $output = '
function validateEnrollSections(formname,nextstate) {
    var badsectotal = 0;
    var reservedtotal = 0;
    var secTest = "";
';
    for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
        $output .= "
    var selSec = 0;
    for (var j=0; j<document.requestcrs.sec_".$i.".length; j++) {
        if (document.requestcrs.sec_".$i."[j].checked) {
            selSec = document.requestcrs.sec_".$i."[j].value;
        }
        if (selSec == 1) {
            secTest = validsection(document.requestcrs.loncapasec_".$i.");
            if (secTest == 'badsec') {
                badsectotal++;
            }
            if (secTest == 'reserved') {
                reservedtotal++;
            }
        }
    }
";
    }
    for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
        $output .= "
    if (document.requestcrs.crosslist_".$i.".checked) {
        secTest = validsection(document.requestcrs.crosslist_".$i."_lcsec);
        if (secTest == 'badsec') {
            badsectotal++;
        }
        if (secTest == 'reserved') {
            reservedtotal++;
        }
    }
";
    }
    $output .= "
    if (badsectotal>0) {
        alert('$secname');
        return false;
    }
    if (reservedtotal>0) {
        alert('$secnone');
        return false;
    }
    formname.state.value= nextstate;
    formname.submit();
    return;
}
";
    return $output;
}

sub personnel_lcsec_js {
    my %alerts = &section_check_alerts();
    my $secname = $alerts{'badsec'}.'\\n'.$alerts{'separate'};
    my $secnone = $alerts{'reserved'};
    my $output = '
function validatePersonnelSections(formname,nextstate) {
    var badsectotal = 0;
    var reservedtotal = 0;
    var secTest = "";
';
    for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
        $output .= "
    if (document.requestcrs.person_".$i."_uname.value != '') {
        secTest = validsection(document.requestcrs.person_".$i."_newsec,'1');
        if (secTest == 'badsec') {
            badsectotal++; 
        }
        if (secTest == 'reserved') {
            reservedtotal++;
        }
    }
";
    }
    $output .= "
    if (badsectotal > 0) {
        alert('$secname');
        return false;
    } else {
        if (reservedtotal > 0) {
            alert('$secnone');
            return false;
        }
    }
    formname.state.value = nextstate;
    formname.submit();
    return;
}
";
    return $output;
}

sub section_check_alerts {
    my %lt = 
        &Apache::lonlocal::texthash(
            reserved => "You need to change one or more LON-CAPA section names - none is a reserved word in the system, and may not be used.",
            badsec => 'You need to change one or more LON-CAPA section names - names may only contain letters or numbers.',
            separate => 'Separate multiple sections with a comma.'
        );
    return %lt;
}

sub section_check_javascript {
    return <<"END";
function validsection(field,mult) {
    var str = field.value;
    var badsec=0;
    var reserved=0;
    if (window.RegExp) {
        var badsecnum=0;
        var reservednum=0;
        var pattern=/[^a-zA-Z0-9]/; 
        str = str.replace(/(^\\s*)|(\\s*\$)/gi,"");
        str = str.replace(/[ ]{2,}/gi," ");
        if (mult == '1') {
            var sections = new Array();
            sections = str.split(/\\s*[\\s,;:]\\s*/);
            var i;
            for (i=0; i<sections.length; i++) {
                if ((sections[i] != '') && (sections[i] != undefined) && (sections[i] != null)) {
                    if (pattern.test(sections[i])) {
                        badsecnum++;
                    } else {
                        if (sections[i] == 'none') {
                            reservednum++;
                        }
                    }
                }
            }
        } else {
            if ((str != '') && (str != undefined) && (str != null)) {
                if (pattern.test(str)) {
                    badsecnum++;
                } else {
                    if (str == 'none') {
                        reservednum++;
                    }
                }
            }
        }
        if (badsecnum > 0) {
            return 'badsec';
        }
        if (reservednum > 0) {
            return 'reserved';
        }
    }
    return;
}
END
}

sub close_popup_form {
    my $close= &mt('Close Window');
    return << "END";
<p><form name="displayreq" action="" method="post">
<input type="button" name="closeme" value="$close" onclick="javascript:self.close();" />
</form></p>
END
}

sub get_instcode {
    my ($dom) = @_;
    my ($instcode,$numtitles);
    my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
    &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                             \%cat_order,\@code_order);
    $numtitles = scalar(@codetitles);
    if (@code_order > 0) {
        my $message;
        foreach my $item (@code_order) {
            $instcode .= $env{'form.instcode_'.$item};
        }
    }
    return ($instcode,$numtitles);
}

sub print_request_form {
    my ($r,$action,$state,$page,$states,$dom,$newinstcode,$codechk,$checkedcode,
        $description,$invalidcrosslist) = @_;
    my $formname = 'requestcrs';
    my ($next,$prev,$message,$output,$codepicker,$crstype);
    $prev = $states->{$action}[$page-1];
    $next = $states->{$action}[$page+1];
    my %navtxt = &Apache::lonlocal::texthash (
                                               prev => 'Back',
                                               next => 'Next',
                                             );
    $crstype = $env{'form.crstype'};
    $r->print('<br /><form name="'.$formname.'" method="post" action="/adm/requestcourse">');
    my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk,
        @disallowed);
    if ($crstype eq 'official') {
        if ($env{'form.instcode'} ne '') {
            $instcode = $env{'form.instcode'};
        } elsif ($newinstcode ne '') {
            $instcode = $newinstcode;
        }
        if ($checkedcode) {
            if ($codechk eq 'valid') {
                $message = '<div class="LC_info">'.
                           &mt('The chosen course category [_1] is valid.','<b>'.
                           $instcode.'</b>').
                           '<input type="hidden" name="instcode" value="'.
                           $instcode.'" /></div>';
            } else {
                $message = '<div class="LC_warning">'.
                            &mt('No course was found matching your choice of institutional course category.');
                if ($codechk ne '') {
                    $message .= '<br />'.$codechk;
                }
                $message .= '</div>';
                $prev = 'crstype';
            }
            $r->print($message);
        }
    }
    if ($prev eq 'crstype') {
        if ($crstype eq 'official') {
            &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                                     \%cat_order,\@code_order);
        }
        if (@code_order > 0) {
            $codepicker = &coursecode_form($dom,'instcode',\@codetitles,
                                           \%cat_titles,\%cat_order);
            if ($codepicker) {
                $r->print(&mt('Specify the course to be created.').
                          '<div>'.&Apache::lonhtmlcommon::start_pick_box().
                          $codepicker.
                          &Apache::lonhtmlcommon::end_pick_box().'</div>');
            } else {
                $next = $states->{$action}[$page+2];
                $r->print(&courseinfo_form($dom,$formname,$crstype,$next));
            }
        } else {
            if ($crstype eq 'official') {
                $next = $states->{$action}[$page+2];
            }
            $r->print(&courseinfo_form($dom,$formname,$crstype,$next));
        }
    } elsif ($prev eq 'codepick') {
        if ($instcode eq '') {
            $prev = $states->{$action}[$page-2];
        }
        $r->print(&courseinfo_form($dom,$formname,$crstype,$next,$description));
    } elsif ($state eq 'enrollment') {
        if ($crstype eq 'official') {
            &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                                     \%cat_order,\@code_order);
        }
        $r->print(&print_enrollment_menu($formname,$instcode,$dom,\@codetitles,
                                         \%cat_titles,\%cat_order,\@code_order,
                                         $invalidcrosslist));
    } elsif ($state eq 'personnel') {
        $r->print(&print_personnel_menu($dom,$formname,$crstype,$invalidcrosslist));
    } elsif ($state eq 'review') {
        my (%alerts,%rulematch,%inst_results,%curr_rules,%got_rules,%disallowmsg);
        my $now = time;
        for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
            my $personname = $env{'form.person_'.$i.'_uname'};
            my $persondom = $env{'form.person_'.$i.'_dom'};
            if (($personname =~ /^$match_username$/) && 
                ($persondom =~ /^$match_domain$/)) {
                if (&Apache::lonnet::domain($persondom)) {
                    my $personhome = 
                        &Apache::lonnet::homeserver($personname,$persondom);
                    if ($personhome eq 'no_host') {
                        if ($persondom ne $dom) {
                            my $skipuser = 1;
                            if ($env{'user.role.dc./'.$persondom.'/'}) {
                                my ($start,$end) = split('.',$env{'user.role.dc./'.$persondom.'/'});
                                if (((!$start) || ($start < $now)) && 
                                    ((!$end) || ($end > $now))) {
                                    $skipuser = 0;
                                }
                            }
                            if ($skipuser) {
                                push(@disallowed,$i);
                                $disallowmsg{$i} = &mt('[_1] was excluded because new users need to be from the course domain','<tt>'.$personname.':'.$persondom.'</tt>');
                                next;
                            }
                        }
                        my $usertype = &get_usertype($persondom,$personname,\%curr_rules,\%got_rules);
                        if (&Apache::lonuserutils::can_create_user($dom,'requestcrs',$usertype)) {
                            my ($allowed,$msg,$authtype,$authparam) = 
                                &check_newuser_rules($persondom,$personname,
                                    \%alerts,\%rulematch,\%inst_results,
                                    \%curr_rules,\%got_rules);
                            if ($allowed) {
                                my %domdefaults = &Apache::lonnet::get_domain_defaults($persondom);
                                if ($usertype eq 'official') {
                                    if ($authtype eq '') {
                                        $authtype = $domdefaults{'auth_def'};
                                        $authparam = $domdefaults{'auth_arg_def'};
                                    }
                                } elsif ($usertype eq 'unofficial') {
                                    if ($authtype eq '') {
                                        $authtype = 'internal';
                                        $authparam = '';
                                    }
                                } else {
                                    $authtype = $domdefaults{'auth_def'};
                                    $authparam = $domdefaults{'auth_arg_def'};
                                }
                                if (($authtype eq '') ||
                                    (($authtype =~/^krb/) && ($authparam eq ''))) {
                                    push(@disallowed,$i);
                                    $disallowmsg{$i} = &mt('[_1] was excluded because institutional information is incomplete for this new user.','<tt>'.$personname.':'.$persondom.'</tt>');
                                    next;
                                }
                                if (ref($inst_results{$personname.':'.$persondom}) eq 'HASH') {
                                    if ($inst_results{$personname.':'.$persondom}{'lastname'} ne '') {
                                        $env{'form.person_'.$i.'_lastname'} = $inst_results{$personname.':'.$persondom}{'lastname'};
                                    }
                                    if ($inst_results{$personname.':'.$persondom}{'firstname'} ne '') {
                                        $env{'form.person_'.$i.'_firstname'} = $inst_results{$personname.':'.$persondom}{'firstname'};
                                    }
                                    if ($inst_results{$personname.':'.$persondom}{'permanentemail'} ne '') {
                                        $env{'form.person_'.$i.'_emailaddr'} = $inst_results{$personname.':'.$persondom}{'permanentemail'};
                                    }
                                }
                            } else {
                                push(@disallowed,$i);
                                $disallowmsg{$i} = &mt('[_1] was excluded because the username violated format rules for the domain','<tt>'.$personname.':'.$persondom.'</tt>');  
                            }
                        } else {
                            push(@disallowed,$i);
                            $disallowmsg{$i} = &mt('[_1] was excluded because you may not request new users in the domain','<tt>'.$personname.':'.$persondom.'</tt>');
                        }
                    } else {
                        my %userenv = 
                            &Apache::lonnet::userenvironment($persondom,$personname,'lastname','firstname','permanentemail');
                        if ($env{'form.person_'.$i.'_lastname'} eq '') {
                            $env{'form.person_'.$i.'_lastname'} = $userenv{'lastname'};
                        }
                        if ($env{'form.person_'.$i.'_firstname'} eq '') {
                            $env{'form.person_'.$i.'_firstname'} = $userenv{'firstname'};
                        }
                        if ($env{'form.person_'.$i.'_emailaddr'} eq '') {
                            $env{'form.person_'.$i.'_emailaddr'} = $userenv{'permanentemail'};
                        }
                    }
                } elsif ($personname ne '') {
                    push(@disallowed,$i);
                    $disallowmsg{$i} = &mt('[_1] was excluded because the domain is invalid','<tt>'.$personname.':'.$persondom.'</tt>');
                }
            } elsif ($personname ne '') {
                push(@disallowed,$i);
                $disallowmsg{$i} = &mt('[_1] was excluded because the username or domain is invalid.','<tt>'.$personname.':'.$persondom.'</tt>');
            }
        }
        my $cnum;
        if ($env{'form.origcnum'} =~ /^($match_courseid)$/) {
            $cnum = $env{'form.origcnum'};
        } else {
            my $gentype = 'Course';
            if ($crstype eq 'community') {
                $gentype = 'Community';
            }
            $cnum = &Apache::lonnet::generate_coursenum($dom,$gentype);
        }
        &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                                 \%cat_order,\@code_order);
        if ($crstype eq 'community') {
            $r->print('<h3>'.&mt('Review community request details before submission').'</h3>');
        } else {
            $r->print('<h3>'.&mt('Review course request details before submission').'</h3>');
        }
        $r->print(&print_review($dom,\@codetitles,\%cat_titles,\%cat_order,\@code_order,'','',\@disallowed,\%disallowmsg).
                  '<input type="hidden" name="cnum" value="'.$cnum.'" />');
        if ($crstype eq 'community') {
            $navtxt{'next'} = &mt('Submit community request');
        } else {
            $navtxt{'next'} = &mt('Submit course request');
        }
    }  elsif ($state eq 'process') {
        if ($crstype eq 'official') {
            &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
                                                     \%cat_order,\@code_order);
        }
        my ($storeresult,$result) = &print_request_outcome($dom,\@codetitles,
                                                           \@code_order);
        $r->print($result);
        if (($storeresult eq 'ok') || ($storeresult eq 'created')) {
            $r->print('<p>');
            if ($storeresult eq 'ok') {
                $r->print('<a href="/adm/requestcourse?action=view&state=details&showdom='.$dom.'&cnum='. $env{'form.cnum'}.'">'.
                          &mt('Modify this request').'</a>'.('&nbsp;'x4));
            }
            $r->print('<a href="/adm/requestcourse">'.&mt('Make another request').'</a></p>');
            return;
        }
    }
    my @excluded = &get_excluded_elements($dom,$states,$action,$state);
    if ($state eq 'personnel') {
        push(@excluded,'persontotal');
    }
    if ($state eq 'review') {
        if (@disallowed > 0) {
            my @items = qw(uname dom lastname firstname emailaddr hidedom role newsec);
            my @currsecs = &current_lc_sections();
            if (@currsecs) {
                push(@items,'sec');
            }
            my $count = 0;
            for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
                unless ($env{'form.person_'.$i.'_uname'} eq '') {
                    if (grep(/^$i$/,@disallowed)) {
                        foreach my $item (@items) {
                            $env{'form.person_'.$i.'_'.$item} = '';
                        }
                    } else { 
                        foreach my $item (@items) {
                            $env{'form.person_'.$count.'_'.$item} = $env{'form.person_'.$i.'_'.$item};
                        }
                    }
                }
                $count ++;
            }
            $env{'form.persontotal'} = $count;
             
        }
    }
    if ($state eq 'enrollment') {
        push(@excluded,'crosslisttotal');
    }
    $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</form>');
    &display_navbuttons($r,$dom,$formname,$prev,$navtxt{'prev'},$next,
                        $navtxt{'next'},$state);
    return;
}

sub get_usertype {
    my ($persondom,$personname,$curr_rules,$got_rules) = @_;
    my ($rules,$ruleorder) =
        &Apache::lonnet::inst_userrules($persondom,'username');
    my $usertype = &Apache::lonuserutils::check_usertype($persondom,$personname,
                                                         $rules,$curr_rules,$got_rules);
    return $usertype;
}

sub check_newuser_rules {
    my ($persondom,$personname,$alerts,$rulematch,$inst_results,$curr_rules,
        $got_rules) = @_;
    my $allowed = 1;
    my $newuser = 1;
    my ($checkhash,$userchkmsg,$authtype,$authparam);
    my $checks = { 'username' => 1 };
    $checkhash->{$personname.':'.$persondom} = { 'newuser' => $newuser };
    &Apache::loncommon::user_rule_check($checkhash,$checks,$alerts,$rulematch,
                                        $inst_results,$curr_rules,$got_rules);
    if (ref($alerts->{'username'}) eq 'HASH') {
        if (ref($alerts->{'username'}{$persondom}) eq 'HASH') {
            my $domdesc =
                &Apache::lonnet::domain($persondom,'description');
            if ($alerts->{'username'}{$persondom}{$personname}) {
                if (ref($curr_rules->{$persondom}) eq 'HASH') {
                    $userchkmsg =
                        &Apache::loncommon::instrule_disallow_msg('username',
                                                                  $domdesc,1).
                        &Apache::loncommon::user_rule_formats($persondom,
                            $domdesc,$curr_rules->{$persondom}{'username'},
                            'username');
                }
                $allowed = 0;
            }
        }
    }
    if ($allowed) {
        if (ref($rulematch) eq 'HASH') {
            if (ref($rulematch->{$personname.':'.$persondom}) eq 'HASH') {
                my $matchedrule = $rulematch->{$personname.':'.$persondom}{'username'};
                my ($rules,$ruleorder) =
                    &Apache::lonnet::inst_userrules($persondom,'username');
                if (ref($rules) eq 'HASH') {
                    if (ref($rules->{$matchedrule}) eq 'HASH') {
                        $authtype = $rules->{$matchedrule}{'authtype'};
                        $authparam = $rules->{$matchedrule}{'authparm'};
                    }
                }
            }
        }
    }
    return ($allowed,$userchkmsg,$authtype,$authparam);
}

sub get_excluded_elements {
    my ($dom,$states,$action,$state) = @_;
    my @excluded = ('counter');
    my %elements = &form_elements($dom);
    if (ref($states) eq 'HASH') {
        if (ref($states->{$action}) eq 'ARRAY') {
            my @items = @{$states->{$action}};
            my $numitems = scalar(@items);
            if ($numitems) {
                for (my $i=$numitems-1; $i>=0; $i--) {
                    if (ref($elements{$action}) eq 'HASH') {
                        if (ref($elements{$action}{$items[$i]}) eq 'HASH') {
                            foreach my $key (keys(%{$elements{$action}{$items[$i]}})) {
                                push(@excluded,$key);
                            }
                        }
                    }
                    last if ($items[$i] eq $state);
                }
            }
        }
    }
    if (grep(/^instcode_/,@excluded)) {
        push(@excluded,'instcode');
    }
    return @excluded;
}

sub print_enrollment_menu {
    my ($formname,$instcode,$dom,$codetitles,$cat_titles,$cat_order,$code_order,
        $invalidcrosslist) =@_;
    my ($sections,$autoenroll,$access_dates,$output,$hasauto);
    my $starttime = time;
    my $endtime = time+(6*30*24*60*60); # 6 months from now, approx

    my %accesstitles = (
                          'start' => 'Default start access',
                           'end'   => 'Default end access',
                       );
    my %enrolltitles = (
                           'start' => 'Start auto-enrollment',
                           'end'   => 'End auto-enrollment',
                       );
    if ($env{'form.crstype'} eq 'official') {
        if (&Apache::lonnet::auto_run('',$dom)) {
            $output = &show_invalid_crosslists($invalidcrosslist);
            my ($section_form,$crosslist_form);
            $section_form = &inst_section_selector($dom,$instcode);
            if ($section_form) {
                $sections = &Apache::lonhtmlcommon::row_headline().
                            '<h3>'.&Apache::loncommon::help_open_topic('Course_Request_Sections').
                            '&nbsp;'.&mt('Sections for auto-enrollment').'</h3>'.
                            &Apache::lonhtmlcommon::row_closure(1).
                            $section_form;
            }
            my $crosslisttotal = $env{'form.crosslisttotal'};
            if (!$crosslisttotal) {
                $crosslisttotal = 1;
            }
            if ($env{'form.addcrosslist'}) {
                $crosslisttotal ++;
            }
            for (my $i=0; $i<$crosslisttotal; $i++) {
                $crosslist_form .= &coursecode_form($dom,'crosslist',$codetitles, 
                                                  $cat_titles,$cat_order,$i);
            }
            if ($crosslist_form) { 
                $crosslist_form .= 
                    &Apache::lonhtmlcommon::row_title(&mt('Add another')).
                    '<input name="crosslisttotal" type="hidden" value="'.$crosslisttotal.'" />'.
                    '<input name="addcrosslist" type="checkbox" value="'.$crosslisttotal.'"'.
                    ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
                   "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure();
                $sections .=  &Apache::lonhtmlcommon::row_headline.
                              '<h3>'.&mt('Crosslisted courses for auto-enrollment').'</h3>'.
                              &Apache::lonhtmlcommon::row_closure(1).
                              $crosslist_form;
            }
            $hasauto = 1;
            $autoenroll = 
                &Apache::lonhtmlcommon::row_title(&Apache::loncommon::help_open_topic('Course_Request_Autoadd').'&nbsp;'.&mt('Add registered students automatically')).
                '<span class="LC_nobreak"><label>'.
                '<input type="radio" name="autoadds" value="1">'.
                &mt('Yes').'</label>'.('&nbsp;'x3).'<label>'.
                '<input type="radio" name="autoadds" value="0" checked="checked">'.
                &mt('No').'</label></span>'.
                &Apache::lonhtmlcommon::row_closure(1).
                &Apache::lonhtmlcommon::row_title(&Apache::loncommon::help_open_topic('Course_Request_Autodrop').'&nbsp;'.&mt('Drop unregistered students automatically')).
                '<span class="LC_nobreak"><label>'.
                '<input type="radio" name="autodrops" value="1">'.
                &mt('Yes').'</label>'.('&nbsp;'x3).'<label>'.
                '<input type="radio" name="autodrops" value="0" checked="checked">'.
                &mt('No').'</label></span>'. 
                &Apache::lonhtmlcommon::row_closure(1).
                &date_setting_table($starttime,$endtime,$formname,'enroll',
                                    $hasauto,%enrolltitles);
        }
    }
    my $access_dates = 
        &date_setting_table($starttime,$endtime,$formname,'access',$hasauto,
                            %accesstitles);
    $output .= &Apache::lonhtmlcommon::start_pick_box();
    if ($sections) {
        $output .=  $sections;
    }
    if ($autoenroll) {
        $output .= &Apache::lonhtmlcommon::row_headline('Auto-enroll').
                   '<h3>'.&mt('Auto-enrollment settings').'</h3>'.
                   &Apache::lonhtmlcommon::row_closure(1).
                   $autoenroll;
    }
    if ($access_dates) {
        my $header = &mt('Access dates for students');
        if ($env{'form.crstype'} eq 'community') {
            $header = &mt('Access dates for community members');
        }
        $output .= &Apache::lonhtmlcommon::row_headline('Access').
                   '<h3>'.$header.'</h3>'.
                   &Apache::lonhtmlcommon::row_closure(1).
                   $access_dates
    }
    return '<div>'.&Apache::lonhtmlcommon::start_pick_box().$output.
           &Apache::lonhtmlcommon::end_pick_box().'</div>';
}

sub show_invalid_crosslists {
    my ($invalidcrosslist) = @_;
    my $output;
    if (ref($invalidcrosslist) eq 'ARRAY') {
        if (@{$invalidcrosslist} > 0) {
            $output = '<div class="LC_warning">'.
                      &mt('The following crosslisted courses were invalid:').'<ul>';
            foreach my $item (@{$invalidcrosslist}) {
                $output .= '<li>'.$item.'</li>';
            }
            $output .= '</ul></div><br />';
        }
    }
    return $output;
}


sub inst_section_selector {
    my ($dom,$instcode) = @_;
    my @sections = &Apache::lonnet::auto_get_sections(undef,$dom,$instcode);
    my $sectotal = scalar(@sections);
    my $output;
    if ($sectotal) {
        $output .=  &Apache::lonhtmlcommon::row_title(&mt('Sections of [_1]',$instcode)).
                    &Apache::loncommon::start_data_table().
                    &Apache::loncommon::start_data_table_row().
                    '<th>'.&mt('Include?').'<input type="hidden" name="sectotal" '.
                    'value="'.$sectotal.'"  /></th>'.
                    '<th>'.&mt('Institutional Section').'</th>'.
                    '<th>'.&Apache::loncommon::help_open_topic('Course_Request_LCSection').
                          '&nbsp;'.&mt('LON-CAPA section').'</th>'.
                    &Apache::loncommon::end_data_table_row();
        for (my $i=0; $i<@sections; $i++) {
            my $colflag = $i%2;
            my $secon = ' checked="checked"';
            my $secoff = '';
            if ($env{'form.origcnum'}) {
                $secoff = $secon;
                $secon='';
            }
            $output .= &Apache::loncommon::start_data_table_row().
                       '<td><label><input type="radio" name="sec_'.$i.
                       '"'.$secon.' value="1" />'.&mt('Yes').'</label>'.
                       ('&nbsp;'x2).'<label><input type="radio" name="sec_'.$i.
                        '"'.$secoff.' value="0" />'.&mt('No').'</label></td>'.
                       '<td align="center">'.$sections[$i].
                       '<input type="hidden" name="secnum_'.$i.'" value="'.
                       $sections[$i].'" /></td>'.
                       '<td><input type="text" size="10" name="loncapasec_'.$i.
                       '" value="'.$sections[$i].'" /></td>'.
                       &Apache::loncommon::end_data_table_row();
        }
        $output .= &Apache::loncommon::end_data_table().
                   &Apache::lonhtmlcommon::row_closure();
    }
    return $output;
}

sub date_setting_table {
    my ($starttime,$endtime,$formname,$prefix,$hasauto,%datetitles) = @_;
    my ($perpetual,$table);
    my $startform = &Apache::lonhtmlcommon::date_setter($formname,$prefix.'start',
                                                        $starttime,'','','',1,'','','',1);
    my $endform = &Apache::lonhtmlcommon::date_setter($formname,$prefix.'end',
                                                      $endtime,'','','',1,'','','',1);
    my $closure = '';
    if ($prefix eq 'access') {
        $perpetual = ' <span class="LC_nobreak"><label>'.
                     '<input type="checkbox" name="no_end_date" />'.
                     &mt('No end date').'</label></span>';
        $closure = '1';
    }

    my %help_item = (
                      access => {
                                  start => 'Course_Request_Access_Start', 
                                  end   => 'Course_Request_Access_End',
                                },
                      enroll => {
                                  start => 'Course_Request_Enroll_Start',
                                  end   => 'Course_Request_Enroll_End',
                                },
                     );
    if ($hasauto) {
        $help_item{'access'}{'start'} = 'Course_Request_RegAccess_Start';
        $help_item{'access'}{'end'}   = 'Course_Request_RegAccess_End';
    }

    $table = &Apache::lonhtmlcommon::row_title(&Apache::loncommon::help_open_topic($help_item{$prefix}{'start'}).
             '&nbsp;'.&mt($datetitles{'start'})).$startform.
             &Apache::lonhtmlcommon::row_closure(1).
             &Apache::lonhtmlcommon::row_title(&Apache::loncommon::help_open_topic($help_item{$prefix}{'end'}).
             '&nbsp;'.&mt($datetitles{'end'})).$endform.$perpetual.
             &Apache::lonhtmlcommon::row_closure($closure);
    return $table;
}

sub print_personnel_menu {
    my ($dom,$formname,$crstype,$invalidcrosslist) = @_;
    my $output;
    if ($crstype eq 'official') {
        if (&Apache::lonnet::auto_run('',$dom)) {
            $output .= &show_invalid_crosslists($invalidcrosslist);
        }  
    }
    $output .= '<div>'.&Apache::lonhtmlcommon::start_pick_box();
    my $persontotal = $env{'form.persontotal'};
    if ((!defined($persontotal)) || (!$persontotal)) {
        $persontotal = 1;
    }
    if ($env{'form.addperson'}) {
        $persontotal ++;
    }
    my @items = ('uname','dom','lastname','firstname','emailaddr','hidedom');

    my $type = 'Course';
    if ($crstype eq 'community') {
        $type = 'Community';
    }
    my $roleoptions;
    my @roles = &Apache::lonuserutils::roles_by_context('course','',$type);
    foreach my $role (@roles) {
        my $plrole = &Apache::lonnet::plaintext($role,$type);
        $roleoptions .= '  <option value="'.$role.'">'.$plrole.'</option>'."\n";
    }
    my %customroles=&Apache::lonuserutils::my_custom_roles();
    if (keys(%customroles) > 0) {
        foreach my $cust (sort(keys(%customroles))) {
            my $custrole="cr/$env{'user.domain'}/$env{'user.name'}/$cust";
            $roleoptions .= '  <option value="'.$custrole.'">'.$cust.'</option>'."\n";
        }
    }

    my @currsecs = &current_lc_sections();

    my ($existtitle,$existops,$existmult,$newtitle,$seccolspan);
    if (@currsecs) {
        my $existsize = scalar(@currsecs);
        if ($existsize > 3) {
            $existsize = 3;
        }
        if ($existsize > 1) {
            $existmult = ' multiple="multiple" size="'.$existsize.'" ';
        }
        @currsecs = sort { $a <=> $b } (@currsecs);
        $existtitle = &mt('Official').':&nbsp;';
        $existops = '<option value="">'.&mt('None').'</option>';
        foreach my $sec (@currsecs) {
            $existops .= '<option value="'.$sec.'">'.$sec.'</option>'."\n";
        }
        $seccolspan = ' colspan="2"';
        $newtitle = &mt('Other').':&nbsp;';
    }

    if ($persontotal) {
        my %lt = &Apache::lonlocal::texthash(
            community => 'Requestor is automatically assigned Coordinator role.',
            official => 'Requestor is automatically assigned Course Coordinator role.',
        );
        $lt{'unofficial'} = $lt{'official'};
        $output .= &Apache::lonhtmlcommon::row_headline().
                  '<h3>'.&Apache::loncommon::help_open_topic('Course_Request_Personnel').'&nbsp;'.$lt{$crstype}.' '.&mt('Include other personnel?').'</h3>';
    }
    for (my $i=0; $i<$persontotal; $i++) { 
        my @linkargs = map { 'person_'.$i.'_'.$_ } (@items);
        my $linkargstr = join("','",@linkargs);
        my $uname_form = '<input type="text" name="person_'.$i.'_uname" value="" size="20" />';
        my $onchange = 'javascript:fix_domain('."'$formname','person_".$i."_dom',".
                       "'person_".$i."_hidedom','person_".$i."_uname'".');';
        my $udom_form = &Apache::loncommon::select_dom_form($dom,'person_'.$i.'_dom','',
                                                            1,$onchange).
                        '<input type="hidden" name="person_'.$i.'_hidedom" value="" />';
        my %form_elems;
        foreach my $item (@items) {
            next if (($item eq 'dom') || ($item eq 'uname') || ($item eq 'hidedom'));
            $form_elems{$item} = '<input type="text" name="person_'.$i.'_'.$item.'" '.
                                 'value="" readonly="readonly" />';
        }
        my $roleselector = '<select name="person_'.$i.'_role">'."\n".
                           $roleoptions.'</select>';
        my $sectionselector;
        if (@currsecs) {
            $sectionselector = $existtitle.'<select name="person_'.$i.'_sec"'.
                               $existmult.'>'."\n".$existops.'</select>'.('&nbsp;' x3);
        }
        $sectionselector .= $newtitle.
            '<input type="text" name="person_'.$i.'_newsec" size="15" value="" />'."\n";
        my $usersrchlinktxt = &mt('Search for user');
        my $usersrchlink =  &Apache::loncommon::selectuser_link($formname,@linkargs,$dom,
                            $usersrchlinktxt);
        my $userchklinktxt = &mt('Check username');
        my $userchklink = &Apache::loncommon::selectuser_link($formname,@linkargs,$dom,
                            $userchklinktxt,'checkusername');
        $output .= 
            &Apache::lonhtmlcommon::row_title(&mt('Additional Personnel')).
            '<table><tr><td align="center" valign="middle"><b>'.$usersrchlink.'</b></td>'."\n".
            '<td align="left" valign="top" colspan="2"><span class="LC_nobreak">'.
            &mt('Username').':&nbsp;'.$uname_form.'&nbsp;'.$userchklink.'</span><br />'."\n".
            '<span class="LC_nobreak">'.&mt('Domain').':&nbsp;'.$udom_form.'</span></td>'.
            '</tr>'."\n".'<tr>'.
            '<td align="center" valign="top">'.&mt('First Name').'<br />'.$form_elems{'firstname'}.'</td>'."\n".
            '<td align="center" valign="top">'.&mt('Last Name').'<br />'.$form_elems{'lastname'}.'</td>'."\n".
            '<td align="center" valign="top">'.&mt('E-mail').'<br />'.$form_elems{'emailaddr'}.'</td></tr>'."\n".
            '<tr><td align="center" valign="top">'.&Apache::loncommon::help_open_topic('Course_Roles').'&nbsp;'.&mt('Role').'<br />'.$roleselector.'</td>'."\n".
            '<td'.$seccolspan.' align="center" valign="top">'.
            &Apache::loncommon::help_open_topic('Course_Request_Rolesection').'&nbsp;'.&mt('LON-CAPA Section(s)').'<br />'.$sectionselector.'</td>'."\n".
            '</tr></table>'.&Apache::lonhtmlcommon::row_closure();
    }
    $output .= &Apache::lonhtmlcommon::row_title(&mt('Add another')).
               '<input name="persontotal" type="hidden" value="'.$persontotal.'" />'.
               '<input name="addperson" type="checkbox" value="'.$persontotal.'"'.
               ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
               "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure(1).
               &Apache::lonhtmlcommon::end_pick_box().'</div>';
    if ($crstype eq 'community') {
        $output .= '<p>'.&mt('You may also add users later, once the community has been created, by using the "Manage community users" link, accessible from the "Main Menu".').'</p>';
    } else {
        $output .= '<p>'.&mt('You may also add users later, once the course has been created, by using the "Manage course users" link, accessible from the "Main Menu".').'</p>';
    }
    return $output;
}

sub current_lc_sections {
    my @currsecs;
    if ($env{'form.sectotal'}) {
        for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
            if ($env{'form.sec_'.$i}) { 
                if (defined($env{'form.loncapasec_'.$i})) {
                    my $lcsec = $env{'form.loncapasec_'.$i};
                    unless (grep(/^\Q$lcsec\E$/,@currsecs)) {
                        push(@currsecs,$lcsec);
                    }
                }
            }
        }
    }
    return @currsecs;
}

sub sorted_request_history {
    my ($dom,$action,$curr_req) = @_;
    my ($after,$before,$statusfilter,$crstypefilter);
    if ($env{'form.status'} ne '') {
        $statusfilter = $env{'form.status'};
    }
    if ($env{'form.crstype'} ne '') {
        $crstypefilter = $env{'form.crstype'};
    }
    if (ref($curr_req) eq 'HASH') {
        $after = $curr_req->{'requested_after_date'},
        $before = $curr_req->{'requested_before_date'};
        $statusfilter = $curr_req->{'status'};
        $crstypefilter = $curr_req->{'crstype'};
    }
    my %statusinfo = &Apache::lonnet::dump('courserequests',$env{'user.domain'},
                                           $env{'user.name'},'^status:'.$dom);
    my %queue_by_date;
    my ($types,$typenames) = &Apache::loncommon::course_types();
    foreach my $key (keys(%statusinfo)) {
        if ($action eq 'view') {
            next unless (($statusinfo{$key} eq 'approval') || ($statusinfo{$key} eq 'pending'));
        } else {
            next unless (($statusfilter eq 'any') ||
                          ($statusfilter eq $statusinfo{$key}));
        }
        (undef,my($cdom,$cnum)) = split(':',$key);
        next if ($cdom ne $dom);   
        my $requestkey = $cdom.'_'.$cnum;
        if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
            my %history = &Apache::lonnet::restore($requestkey,'courserequests',
                                                   $env{'user.domain'},$env{'user.name'});
            my $entry;
            my $reqtime = $history{'reqtime'};
            my $lastupdate = $history{'timestamp'};
            my $crstype = $history{'crstype'};
            my $disposition = $history{'disposition'};
            my $status = $history{'status'};
            if ($action eq 'view') {
                next if ((exists($history{'status'})) && ($history{'status'} eq 'created'));
            } else {
                next if (($reqtime < $after) || ($reqtime > $before));
            }
            next unless (($crstypefilter eq 'any') || 
                         ($crstypefilter eq $crstype));
            if ($action eq 'view') {
                next unless (($disposition eq 'approval') || 
                             ($disposition eq 'pending'));
            }
            if (ref($history{'details'}) eq 'HASH') {
                $entry = $requestkey.':'.$crstype.':'.
                         &escape($history{'details'}{'cdescr'});
                if ($action eq 'log') {
                    $entry .= ':'.$lastupdate.':';
                    if ($statusinfo{$key} ne '') {
                        $entry .= $statusinfo{$key};
                    } elsif ($status ne '') {
                        $entry .= $status;
                    } else {
                        $entry .= $disposition;
                    }
                }
                if ($crstype eq 'official') {
                    $entry .= ':'.&escape($history{'details'}{'instcode'}); 
                }
            }
            if ($entry ne '') {
                if (exists($queue_by_date{$reqtime})) {
                    if (ref($queue_by_date{$reqtime}) eq 'ARRAY') {
                        push(@{$queue_by_date{$reqtime}},$entry);
                    }
                } else {
                    @{$queue_by_date{$reqtime}} = ($entry);
                }
            }
        }
    }
    return %queue_by_date;
}

sub print_request_status {
    my ($dom,$action) = @_;
    my %queue_by_date = &sorted_request_history($dom,$action);
    my @sortedtimes = sort {$a <=> $b} (keys(%queue_by_date));
    my $formname = 'requestcrs';
    my ($types,$typenames) = &Apache::loncommon::course_types();
    my $output = '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n".

              '<input type="hidden" name="state" value="'.$env{'form.state'}.'" />'."\n".
              '<input type="hidden" name="crstype" value="'.$env{'form.crstype'}.'" />'."\n".
              '<input type="hidden" name="showdom" value="" />'."\n".
              '<input type="hidden" name="cnum" value="" />'."\n";
    if (@sortedtimes > 0) {
        my $desctitle;
        if ($env{'form.crstype'} eq 'any') {
            $desctitle = &mt('Course/Community Description')
        } elsif ($env{'form.crstype'} eq 'community') {
            $desctitle = &mt('Community Description')
        } else {
            $desctitle = &mt('Course Description');
        }
        $output .= &Apache::loncommon::start_data_table().
                   &Apache::loncommon::start_data_table_header_row().
                   '<th>'.&mt('Action').'</th>'.
                   '<th>'.$desctitle.'</th>'.
                   '<th>'.&mt('Domain').'</th>';
        if ($env{'form.crstype'} eq 'any') {
            $output .= '<th>'.&mt('Type').'</th>';
        }
        if (($env{'form.crstype'} eq 'any') || ($env{'form.crstype'} eq 'official')) {
            $output .= '<th>'.&mt('Institutional Code').'</th>';
        }
        $output .= '<th>'.&mt('Date requested').'</th>'.
                   &Apache::loncommon::end_data_table_header_row();
        my $count = 0;
        foreach my $item (@sortedtimes) {
            my $showtime = &Apache::lonlocal::locallocaltime($item);
            if (ref($queue_by_date{$item}) eq 'ARRAY') {
                foreach my $request (sort(@{$queue_by_date{$item}})) {
                    my ($key,$type,$desc,$instcode) = split(':',$request);
                    my ($cdom,$cnum) = split('_',$key);
                    $output .= &Apache::loncommon::start_data_table_row().
     '<td><input type="button" value="'.&mt('Select').'" onclick="javascript:chooseRequest('."'$cdom','$cnum'".')" /></td>'.
     '<td>'.&unescape($desc).'</td>'.
     '<td>'.$cdom.'</td>';
                    if ($env{'form.crstype'} eq 'any') {
                        my $typename;
                        if (ref($typenames) eq 'HASH') {
                            $typename = &mt($typenames->{$type});
                        }
                        if ($typename eq '') {
                            $typename = &mt('Unknown type');
                        }
                        $output .= '<td>'.$typename.'</td>';
                    }
                    if (($env{'form.crstype'} eq 'any') || 
                        ($env{'form.crstype'} eq 'official')) {
                        my $showinstcode;
                        if ($type eq 'official') {
                            $showinstcode = &unescape($instcode);
                        } else {
                            $showinstcode = &mt('Not applicable');
                        }
                        $output .= '<td>'.$showinstcode.'</td>';
                    }
                    $output .= '<td>'.$showtime.'</td>'.
                               &Apache::loncommon::end_data_table_row();
                }
            }
        }
        $output .= &Apache::loncommon::end_data_table();
    } else {
        if ($env{'form.crstype'} eq 'any') {
$output .= '<div>'.&mt('You have no matching course or community requests awaiting approval by a Domain Coordinator or held in a queue pending administrative action at your institution.').'</div>';
        } elsif ($env{'form.crstype'} eq 'community') {
            $output .= '<div>'.&mt('You have no matching community requests awaiting approval by a Domain Coordinator or held in a queue pending administrative action at your institution.').'</div>';
        } else {
            $output .= '<div>'.&mt('You have no matching course requests awaiting approval by a Domain Coordinator or held in a queue pending administrative action at your institution.').'</div>';
        }
    }
    $output .= '
<br /><input type="button" name="prev" value="'.&mt('Back').'" onclick="javascript:backPage(document.'.$formname.",'crstype'".')" />';
    return $output;
}

sub print_cancel_request {
    my ($dom,$cnum) = @_;
    my $requestkey = $dom.'_'.$cnum;
    my ($result,$output);
    if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
        my %history = &Apache::lonnet::restore($requestkey,'courserequests',
                                               $env{'user.domain'},$env{'user.name'});
        my $timestamp = $history{'reqtime'};
        my $crstype = $history{'crstype'};
        my $status = $history{'status'};
        if (($status eq 'cancelled') || ($status eq 'created')) { 
            if ($status eq 'cancelled') {
                $output = &mt('This request has already been cancelled.');
            } elsif ($status eq 'created') {
                $output = &mt('This request has already been processed, and a course created.');
            }
            $output = &mt('No further action will be taken');
        } elsif (ref($history{'details'}) eq 'HASH') {
            my ($types,$typename) = &Apache::loncommon::course_types();
            my $showtype = $crstype;
            if (defined($typename->{$crstype})) {
                $showtype = $typename->{$crstype}; 
            }
            $output = '<p>'.&Apache::loncommon::start_data_table().
                      &Apache::loncommon::start_data_table_header_row().
                      '<th>'.&mt('Description').'</th><th>'.&mt('Requested').'</th>'.
                      '<th>'.&mt('Type').'</th>'.
                      &Apache::loncommon::end_data_table_header_row().
                      &Apache::loncommon::start_data_table_row().
                      '<td>'.$history{details}{'cdescr'}.'</td><td>'.
                      &Apache::lonlocal::locallocaltime($timestamp).'</td>'.
                      '<td>'.$showtype.'</td>'.
                      &Apache::loncommon::end_data_table_row().
                      &Apache::loncommon::end_data_table().
                      '<br /><div class="LC_warning">';
            if ($crstype eq 'community') {
                $output .= &mt('Cancelling the request will remove it from the queue of pending community requests').'</div>';
            } else {
                $output .= &mt('Cancelling the request will remove it from the queue of pending course requests').'</div>';
            }
            $result = 'ok';
        } else {
            $output = '<div class="LC_error">'.&mt('No record exists for the course ID').'</div>';
        }
    } else {
        $output = '<div class="LC_error">'.&mt('Invalid course ID').'</div>';
    }
    return ($result,$output);
}

sub viewrequest_javascript {
    my ($formname,$next) = @_;
    return <<"ENDJS";

function chooseRequest(cdom,cnum) {
    document.$formname.showdom.value = cdom;
    document.$formname.cnum.value = cnum;
    nextPage(document.$formname,'$next');
}

ENDJS
}

sub viewdetails_javascript {
    my ($formname) = @_;
    return << "ENDJS";

function nextPage(formname,nextstate) {
    if (nextstate == "modify") { 
        formname.state.value = "personnel";
        formname.action.value = "new";
    } else {
        formname.state.value = nextstate;
    }
    formname.submit();
}

function backPage(formname,prevstate) {
    formname.state.value = prevstate;
    formname.submit();
}

ENDJS
}

sub viewcancel_javascript {
    my $alert = &mt('Are you sure you want to cancel this request?\\n'.
                    'Your request will be removed.');
    return << "ENDJS";
function nextPage(formname,nextstate) {
    if (confirm('$alert')) {
        formname.state.value = nextstate;
        formname.submit();
    }
    return;
}

ENDJS
}

sub print_request_logs {
    my ($r,$dom,$jscript,$loaditems,$crumb) = @_;
    my $title;
    if ($env{'form.crstype'} eq 'community') {
        $title = 'Community Request Logs';
    } elsif ($env{'form.crstype'} eq 'any') {
        $title = 'Course/Community Request Logs';
    } else {
        $title = 'Course Request Logs';
    }
    $r->print(&header($title,$jscript,$loaditems).$crumb);
    my $formname = 'requestcrs';
    $r->print('<form action="/adm/requestcourse" method="post" name="'.$formname.'" onsubmit="javascript:setPage(this);">'."\n".
              '<input type="hidden" name="action" value="log" />'."\n".
              '<input type="hidden" name="state" value="display" />'."\n");
    # set defaults
    my $now = time();
    my $defstart = $now - (7*24*3600); #7 days ago
    my %defaults = (
                     page                => '1',
                     show                => '10',
                     crstype             => 'any',
                     status              => 'any',
                     requested_before_date => $now,
                     requested_after_date  => $defstart,
                   );
    my ($types,$typenames) = &Apache::loncommon::course_types();
    my $more_records = 0;
    my %curr;
    foreach my $item ('show','page','crstype','status') {
        $curr{$item} = $env{'form.'.$item};
    }
    $curr{'requested_after_date'} = &Apache::lonhtmlcommon::get_date_from_form('requested_after_date');
    $curr{'requested_before_date'} = &Apache::lonhtmlcommon::get_date_from_form('requested_before_date');
    foreach my $key (keys(%defaults)) {
        if ($curr{$key} eq '') {
            $curr{$key} = $defaults{$key};
        }
    }
    my ($statuses,$statusnames) = &reqstatus_names($curr{'crstype'});
    $r->print('<input type="hidden" name="page" value="'.$curr{'page'}.'" />'.
              &requestlog_display_filter($formname,\%curr));
    my %queue_by_date = &sorted_request_history($dom,$env{'form.action'},\%curr);
    my @sortedtimes = sort {$a <=> $b} (keys(%queue_by_date));
    my $showntablehdr = 0;
    my $tablehdr = &Apache::loncommon::start_data_table().
                   &Apache::loncommon::start_data_table_header_row().
                   '<th>&nbsp;</th><th>'.&mt('Request Date').'</th>'.
                   '<th>'.&mt('Description').'</th>';
    if ($curr{'crstype'} eq 'any') {
        $tablehdr .= '<th>'.&mt('Course Type').'</th>';
    }
    if (($curr{'crstype'} eq 'official') || ($curr{'crstype'} eq 'any')) {
        $tablehdr .= '<th>'.&mt('Institutional Code').'</th>';
    }
    if ($curr{'status'} eq 'any') {
        $tablehdr .= '<th>'.&mt('Status').'</th>';
    } elsif ($curr{'status'} eq 'created') {
        $tablehdr .= '<th>'.&mt('Creation Date').'</th>';
    } elsif ($curr{'status'} eq 'cancelled') {
        $tablehdr .= '<th>'.&mt('Cancellation Date').'</th>';
    } elsif ($curr{'status'} eq 'rejected') {
        $tablehdr .= '<th>'.&mt('Rejection Date').'</th>';
    }
    $tablehdr .= &Apache::loncommon::end_data_table_header_row();
    my ($minshown,$maxshown);
    $minshown = 1;
    my $count = 0;
    if ($curr{'show'} ne &mt('all')) {
        $maxshown = $curr{'page'} * $curr{'show'};
        if ($curr{'page'} > 1) {
            $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'};
        }
    }
    my $norecords;
    if (@sortedtimes > 0) {
        foreach my $item (@sortedtimes) {
            if ($curr{'show'} ne &mt('all')) {
                if ($count >= $curr{'page'} * $curr{'show'}) {
                    $more_records = 1;
                    last;
                }
            }
            $count ++;
            next if ($count < $minshown);
            if (!$showntablehdr) {
                $r->print($tablehdr);
                $showntablehdr = 1;
            }
            my $showtime = &Apache::lonlocal::locallocaltime($item);
            if (ref($queue_by_date{$item}) eq 'ARRAY') {
                foreach my $request (sort(@{$queue_by_date{$item}})) {
                    my ($key,$crstype,$desc,$timestamp,$status,$instcode) = split(':',$request);
                    my ($cdom,$cnum) = split('_',$key);
                    my $output = &Apache::loncommon::start_data_table_row().
     '<td>'.$count.'</td>'.
     '<td>'.$showtime.'</td>'.
     '<td>'.&unescape($desc).'</td>';
                    if ($curr{'crstype'} eq 'any') {
                        my $typename;
                        if (ref($typenames) eq 'HASH') {
                            $typename = &mt($typenames->{$crstype});
                        }
                        if ($typename eq '') {
                            $typename = &mt('Unknown type');
                        }
                        $output .= '<td>'.$typename.'</td>';
                    }
                    if (($curr{'crstype'} eq 'any') ||
                        ($curr{'crstype'} eq 'official')) {
                        my $showinstcode;
                        if ($crstype eq 'official') {
                            $showinstcode = &unescape($instcode);
                        } else {
                            $showinstcode = &mt('Not applicable');
                        }
                        $output .= '<td>'.$showinstcode.'</td>';
                    }
                    if ($curr{'status'} eq 'any') {
                        my $statusname = &mt('Unknown status');
                        if (ref($statusnames) eq 'HASH') {
                            if ($statusnames->{$status} ne '') {
                                $statusname = $statusnames->{$status};
                            }
                        }
                        if (($status eq 'created') || ($status eq 'cancelled') ||
                            ($status eq 'rejected')) {
                            $statusname .= ' '.&Apache::lonlocal::locallocaltime($timestamp);
                        }
                        $output .= '<td>'.$statusname.'</td>';
                    } elsif (($status eq 'created') || ($status eq 'cancelled') ||
                             ($status eq 'rejected')) {
                         $output .= '<td>'.&Apache::lonlocal::locallocaltime($timestamp).'</td>';
                    }
                    $output .= &Apache::loncommon::end_data_table_row();
                    $r->print($output);
                }
            }
        }
        if ($showntablehdr) {  
            $r->print(&Apache::loncommon::end_data_table());
            if (($curr{'page'} > 1) || ($more_records)) {
                $r->print('<table><tr>');
                if ($curr{'page'} > 1) {
                    $r->print('<td><a href="javascript:chgPage('."'previous'".');">'.&mt('Previous [_1] changes',$curr{'show'}).'</a></td>');
                }
                if ($more_records) {
                    $r->print('<td><a href="javascript:chgPage('."'next'".');">'.&mt('Next [_1] changes',$curr{'show'}).'</a></td>');
                }
                $r->print('</tr></table>');
                $r->print(<<"ENDSCRIPT");
<script type="text/javascript">
// <![CDATA[
function chgPage(caller) {
    if (caller == 'previous') {
        document.$formname.page.value --;
    }
    if (caller == 'next') {
        document.$formname.page.value ++;
    }
    document.$formname.submit();
    return;
}
// ]]>
</script>
ENDSCRIPT
            }
        } else {
            $norecords = 1;
        }
    } else {
        $norecords = 1;
    }
    if ($norecords) {
        $r->print('<p class="LC_info">'.
                  &mt('There are no records to display').
                  '</p>');
    }
    $r->print('</form>'.
              &Apache::loncommon::end_page());
    return;
}

sub reqstatus_names {
    my ($crstype) = @_;
    my @statuses = qw(created approval pending rejected cancelled);
    my %statusnames =
            &Apache::lonlocal::texthash (
                        created   => 'Created',
                        approval  => 'Queued pending approval',
                        pending   => 'Queued pending validation',
                        rejected  => 'Request rejected',
                        cancelled => 'Request cancelled',
            );
    if (($crstype eq 'official') || ($crstype eq 'unofficial')) {
        $statusnames{'created'} = &mt('Course created');
    } elsif ($crstype eq 'community') {
        $statusnames{'created'} = &mt('Community created');
    }
    return (\@statuses,\%statusnames);
}

sub requestlog_display_filter {
    my ($formname,$curr) = @_;
    my $nolink = 1;
    my $output = '<table><tr><td valign="top">'.
                 '<span class="LC_nobreak"><b>'.&mt('Records/page:').'</b></span><br />'.
                 &Apache::lonmeta::selectbox('show',$curr->{'show'},undef,
                                              (&mt('all'),5,10,20,50,100,1000,10000)).
                 '</td><td>&nbsp;&nbsp;</td>';
    my $startform =
        &Apache::lonhtmlcommon::date_setter($formname,'requested_after_date',
                                            $curr->{'requested_after_date'},undef,
                                            undef,undef,undef,undef,undef,undef,$nolink);
    my $endform =
        &Apache::lonhtmlcommon::date_setter($formname,'requested_before_date',
                                            $curr->{'requested_before_date'},undef,
                                            undef,undef,undef,undef,undef,undef,$nolink);
    $output .= '<td valign="top"><b>'.&mt('Window during which course/community was requested:').'</b><br />'.
               '<table><tr><td>'.&mt('After:').
               '</td><td>'.$startform.'</td></tr>'.
               '<tr><td>'.&mt('Before:').'</td>'.
               '<td>'.$endform.'</td></tr></table>'.
               '</td>'.
               '<td>&nbsp;&nbsp;</td>';
    my ($types,$typenames) = &Apache::loncommon::course_types();
    if (ref($types) eq 'ARRAY') {
        if (@{$types} > 1) {
            $output .= '<td valign="top"><b>'.
                       &mt('Course Type:').'</b><br /><select name="crstype">';
            my $selstr = '';
            if ($curr->{'crstype'} eq 'any') {
                $selstr = ' selected="selected"';
            }
            $output .= '<option value="any"'.$selstr.'>'.&mt('All types').'</option>'."\n";
            foreach my $crstype (@{$types}) {
                my $selstr = '';
                if ($curr->{'crstype'} eq $crstype) {
                    $selstr = ' selected="selected"';
                }
                my $typename = $crstype;
                if (ref($typenames) eq 'HASH') {
                    if ($typenames->{$crstype} ne '') {
                        $typename = $typenames->{$crstype};
                    }
                }
                $output .= '<option value="'.$crstype.'"'.$selstr.'>'.$typename.'</option>'."\n";
            }
            $output .= '</select></td>';
        }
    }
    my ($statuses,$statusnames) = &reqstatus_names($curr->{'crstype'});
    if (ref($statuses) eq 'ARRAY') {
        if (@{$statuses} > 1) {
            $output .= '<td valign="top"><b>'.
                       &mt('Request Status:').'</b><br /><select name="status">';
            my $selstr = '';
            if ($curr->{'status'} eq 'any') {
                $selstr = ' selected="selected"';
            }
            $output .= '<option value="any"'.$selstr.'>'.&mt('Any status').'</option>'."\n";
            foreach my $status (@{$statuses}) {
                my $selstr = '';
                if ($curr->{'status'} eq $status) {
                    $selstr = ' selected="selected"';
                }
                my $statusname = $status;
                if (ref($statusnames) eq 'HASH') {
                    if ($statusnames->{$status} ne '') {
                        $statusname = $statusnames->{$status};
                    }
                }
                $output .= '<option value="'.$status.'"'.$selstr.'>'.$statusname.'</option>'."\n";
            }
            $output .= '</select></td>';
        }
    }
    $output .= '</tr></table>';

    # Update Display button
    $output .= '<p>'.
               '<input type="submit" value="'.&mt('Update Display').'" />'.
               '</p><hr />';
    return $output;
}

sub print_review {
    my ($dom,$codetitles,$cat_titles,$cat_order,$code_order,$uname,$udom,
        $disallowed,$disallowmsg) = @_;
    my ($types,$typename) = &Apache::loncommon::course_types();
    my ($owner,$ownername,$owneremail);
    if ($uname eq '' || $udom eq '') {
        $uname = $env{'user.name'};
        $udom = $env{'user.domain'};
    }
    $owner = $uname.':'.$udom;
    $ownername = &Apache::loncommon::plainname($uname,$udom,'first');
    my %emails = &Apache::loncommon::getemails($uname,$udom);
    foreach my $email ('permanentemail','critnotification','notification') {
        $owneremail = $emails{$email};
        last if ($owneremail ne '');
    }
    my ($inst_headers,$inst_values,$crstypename,$enroll_headers,$enroll_values,
        $section_headers,$section_values,$personnel_headers,$personnel_values);

    $crstypename = $env{'form.crstype'};
    if (ref($typename) eq 'HASH') {
        unless ($typename->{$env{'form.crstype'}} eq '') {
            $crstypename = &mt($typename->{$env{'form.crstype'}});
        }
    }
    my $category = 'Course';
    if ($env{'form.crstype'} eq 'community') {
        $category = 'Community';
    }

    $inst_headers = '<th>'.&mt('Description').'</th><th>'.&mt('Type').'</th>';
    $inst_values = '<td>'.$env{'form.cdescr'}.'</td><td>'.$crstypename.'</td>';

    my $enrollrow_title = &mt('Default Access Dates').'<br />'.
                          '('.&Apache::lonnet::plaintext('st',$category).')';
    if ($env{'form.crstype'} eq 'official') {
        if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH')) {
            foreach my $title (@{$codetitles}) {
                if ($env{'form.instcode_'.$title} ne '') {
                    $inst_headers .= '<th>'.$title.'</th>';
                    my $longitem = $env{'form.instcode_'.$title};
                    if (ref($cat_titles->{$title}) eq 'HASH') {
                        if ($cat_titles->{$title}{$env{'form.instcode_'.$title}} ne '') {
                            $longitem = $cat_titles->{$title}{$env{'form.instcode_'.$title}};
                        }
                    }
                    $inst_values .= '<td>'.$longitem.'</td>';
                }
            }
        }
        if (&Apache::lonnet::auto_run('',$dom)) {
            $enrollrow_title = &mt('Enrollment');
            $enroll_headers = '<th>'.&mt('Automatic Adds').'</th>'.
                              '<th>'.&mt('Automatic Drops').'</th>'.
                              '<th>'.&mt('Enrollment Starts').'</th>'.
                              '<th>'.&mt('Enrollment Ends').'</th>';
            $section_headers = '<th>'.&mt('Sections').'</th>'.
                               '<th>'.&mt('Crosslistings').'</th>';

            my ($enrollstart,$enrollend) = &dates_from_form('enrollstart','enrollend');
            my @autoroster = (&mt('No'),&mt('Yes'));
            $enroll_values = '<td>'.$autoroster[$env{'form.autoadds'}].'</td>'.
                             '<td>'.$autoroster[$env{'form.autodrops'}].'</td>'.
                             '<td>'.&Apache::lonlocal::locallocaltime($enrollstart).'</td>'.
                             '<td>'.&Apache::lonlocal::locallocaltime($enrollend).'</td>';
            $section_values = '<td><table class="LC_innerpickbox"><tr><th>'.
                              &mt('Institutional section').'</th>'.
                              '<th>'.&mt('LON-CAPA section').'</th></tr>';
            my $secinfo;
            if ($env{'form.sectotal'} > 0) {
                for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
                    if ($env{'form.sec_'.$i}) {
                        $secinfo .= '<tr><td>'.$env{'form.secnum_'.$i}.'</td><td>';
                        if ($env{'form.loncapasec_'.$i} ne '') {
                            $secinfo .= $env{'form.loncapasec_'.$i};
                        } else {
                            $secinfo .= &mt('None');
                        }
                        $secinfo .= '</td></tr>';
                    }
                }
            }
            if ($secinfo eq '') {
                $secinfo = '<tr><td colspan="2">'.&mt('None').'</td></tr>';
            }
            $section_values .= $secinfo.'</table></td><td>'.
                               '<table class="LC_innerpickbox"><tr><th>'.
                               &mt('Institutional course/section').'</th>'.
                               '<th>'.&mt('LON-CAPA section').'</th></tr>';
            my $xlistinfo;
            my $crosslisttotal = $env{'form.crosslisttotal'};
            if (!$crosslisttotal) {
                $crosslisttotal = 1;
            }
            for (my $i=0; $i<$crosslisttotal; $i++) {
                if ($env{'form.crosslist_'.$i}) {
                    $xlistinfo .= '<tr><td>';
                    if (ref($code_order) eq 'ARRAY') {
                        if (@{$code_order} > 0) {
                            foreach my $item (@{$code_order}) {
                                $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item};
                            }
                        }
                    }
                    $xlistinfo .= $env{'form.crosslist_'.$i.'_instsec'}.'</td><td>';
                    if ($env{'form.crosslist_'.$i.'_lcsec'}) {
                        $xlistinfo .= $env{'form.crosslist_'.$i.'_lcsec'};
                    } else {
                        $xlistinfo .= &mt('None');
                    }
                    $xlistinfo .= '</td></tr>';
                }
            }
            if ($xlistinfo eq '') {
                $xlistinfo = '<tr><td colspan="2">'.&mt('None').'</td></tr>';
            }
            $section_values .= $xlistinfo;
        }
        $section_values .= '</table></td>';
    }

    my %ctxt = &clone_text();
    $inst_headers .= '<th>'.&mt('Clone From').'</th>';
    if (($env{'form.cloning'}) &&
        ($env{'form.clonecrs'} =~ /^$match_name$/) && 
        ($env{'form.clonedom'} =~ /^$match_domain$/)) {
        my $canclone = &Apache::loncoursequeueadmin::can_clone_course($uname,
                           $udom,$env{'form.clonecrs'},$env{'form.clonedom'},
                           $env{'form.crstype'});
        if ($canclone) {
            my %courseenv = &Apache::lonnet::userenvironment($env{'form.clonedom'},
                              $env{'form.clonecrs'},('description','internal.coursecode'));
            if (keys(%courseenv) > 0) {
                $inst_headers .= '<th>'.$ctxt{'dsh'}.'</th>';
                $inst_values .= '<td>'.$courseenv{'description'}.'&nbsp;';
                my $cloneinst = $courseenv{'internal.coursecode'};
                if ($cloneinst ne '') {
                    $inst_values .= $cloneinst.' '.&mt('in').' '.$env{'form.clonedom'};
                } else {
                    $inst_values .= &mt('from').' '.$env{'form.clonedom'};
                }
                $inst_values .= '</td><td>';
                if ($env{'form.datemode'} eq 'preserve') {
                    $inst_values .= $ctxt{'prd'}; 
                } elsif ($env{'form.datemode'} eq 'shift') {
                    $inst_values .= &mt('Shift dates by [_1] days',$env{'form.dateshift'});
                } else {
                    $inst_values .= $ctxt{'ncd'};
                }
                $inst_values .= '</td>';
             } else {
                 $inst_values .= '<td>'.&mt('Unknown').'</td>';
             }
         } else {
             $inst_values .= '<td>'.&mt('Not permitted'),'</td>';
         }
    } else {
        $inst_values .= '<td>'.&mt('None').'</td>';
    }
    $enroll_headers .= '<th>'.&mt('Access Starts').'</th>'.
                       '<th>'.&mt('Access Ends').'</th>';
    my ($accessstart,$accessend) = &dates_from_form('accessstart','accessend');
    $enroll_values .= '<td>'.&Apache::lonlocal::locallocaltime($accessstart).'</td>';
    if ($accessend == 0) {
        $enroll_values .= '<td>'.&mt('No end date').'</td>';
    } else {
        $enroll_values .= '<td>'.&Apache::lonlocal::locallocaltime($accessend).'</td>';
    }

    my $container = 'Course';
    my $ccrole = 'cc';
    if ($env{'form.crstype'} eq 'community') {
        $container = 'Community';
        $ccrole = 'co';
    }

    $personnel_headers = '<th>'.&mt('Name').'</th><th>'.&mt('Username:Domain').
                         '</th><th>'.&mt('Role').'</th><th>'.&mt('LON-CAPA Sections').
                         '</th>';

    $personnel_values .= '<tr><td>'.$ownername.'</td><td>'.$owner.'</td>'.
                         '<td>'.&Apache::lonnet::plaintext($ccrole,$container).'</td>'.
                         '<td>'.&mt('None').'</td></tr>';
    for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
        if ($env{'form.person_'.$i.'_uname'} ne '') {
            if (ref($disallowed) eq 'ARRAY') {
                next if (grep(/^$i$/,@{$disallowed}));
            } 
            my @officialsecs = &Apache::loncommon::get_env_multiple('form.person_'.$i.'_sec');
            my @allsecs;
            foreach my $sec (@officialsecs) {
                next unless ($sec =~ /\w/);
                next if ($sec =~ /\W/);
                next if ($sec eq 'none');
                push(@allsecs,$sec);
            }
            my $newsec = $env{'form.person_'.$i.'_newsec'};
            $newsec =~ s/^\s+//;
            $newsec =~s/\s+$//;
            my @newsecs = split(/\s*[\s,;:]\s*/,$newsec);
            foreach my $sec (@newsecs) {
                next unless ($sec =~ /\w/); 
                next if ($sec =~ /\W/);
                next if ($sec eq 'none');
                if ($sec ne '') {
                    unless (grep(/^\Q$sec\E$/,@allsecs)) {
                        push(@allsecs,$sec); 
                    }
                }
            }
            my $showsec;
            if (@allsecs) {
                $showsec = join(', ',@allsecs);
            }
            if ($showsec eq '') {
                $showsec = &mt('None');
            }
            if ($env{'form.person_'.$i.'_role'} eq $ccrole) {
                $showsec = &mt('None');
            }
            my $role = $env{'form.person_'.$i.'_role'}; 
            $personnel_values .= 
                '<tr><td>'.$env{'form.person_'.$i.'_firstname'}.' '.
                $env{'form.person_'.$i.'_lastname'}.'</td>'.
                '<td>'.$env{'form.person_'.$i.'_uname'}.':'.
                $env{'form.person_'.$i.'_dom'}.'</td>'.
                '<td>'.&Apache::lonnet::plaintext($role,$container).'</td>'.
                '<td>'.$showsec.'</td></tr>';
        }
    }
    my $output;
    if (ref($disallowed) eq 'ARRAY') {
        if (@{$disallowed} > 0) {
            if (ref($disallowmsg) eq 'HASH') {
                $output = '<p class="LC_warning">'.
                          &mt('Not all requested personnel could be included.').'<ul>'; 
                foreach my $item (@{$disallowed}) {
                    $output .= '<li>'.$disallowmsg->{$item}.'</li>';
                }
                $output .= '</ul></p>';
            }
        }
    }
    $output .=    '<div>'.&Apache::lonhtmlcommon::start_pick_box().
                  &Apache::lonhtmlcommon::row_title(&mt('Owner')).
                  '<table class="LC_innerpickbox"><tr>'.
                  '<th>'.&mt('Name').'</th>'.
                  '<th>'.&mt('Username:Domain').'</th>'.
                  '<th>'.&mt('E-mail address').'</th>'.
                  '</tr><tr>'."\n".
                  '<td>'.$ownername.'</td><td>'.$owner.'</td>'.
                  '<td>'.$owneremail.'</td>'.
                  '</tr></table>'."\n".
                  &Apache::lonhtmlcommon::row_closure().
                  &Apache::lonhtmlcommon::row_title(&mt('Description')).
                  '<table class="LC_innerpickbox"><tr>'.$inst_headers.'</tr>'."\n".
                  '<tr>'.$inst_values.'</tr></table>'."\n".
                  &Apache::lonhtmlcommon::row_closure().
                  &Apache::lonhtmlcommon::row_title($enrollrow_title).
                  '<table class="LC_innerpickbox"><tr>'.$enroll_headers.'</tr>'."\n".
                  '<tr>'.$enroll_values.'</tr></table>'."\n".
                  &Apache::lonhtmlcommon::row_closure();
    if ($section_headers ne '') {
        $output .= &Apache::lonhtmlcommon::row_title(&mt('Sections')).
                   '<table class="LC_innerpickbox"><tr>'.$section_headers.'</tr>'."\n".
                   '<tr>'.$section_values.'</tr></table>'."\n".
                   &Apache::lonhtmlcommon::row_closure();
    }
    $output .= &Apache::lonhtmlcommon::row_title(&mt('Personnel')).
               '<table class="LC_innerpickbox"><tr>'.$personnel_headers.'</tr>'."\n".
               $personnel_values.'</table>'."\n".
               &Apache::lonhtmlcommon::row_closure(1).
               &Apache::lonhtmlcommon::end_pick_box().'</div>';
    return $output;
}

sub dates_from_form {
    my ($startname,$endname) = @_;
    my $startdate = &Apache::lonhtmlcommon::get_date_from_form($startname);
    my $enddate   = &Apache::lonhtmlcommon::get_date_from_form($endname);
    if ($endname eq 'accessend') {
        if (exists($env{'form.no_end_date'}) ) {
            $enddate = 0;
        }
    }
    return ($startdate,$enddate);
}

sub courseinfo_form {
    my ($dom,$formname,$crstype,$next,$description) = @_;
    my %lt = &Apache::lonlocal::texthash(
                official => 'You must provide a (brief) course description.',
                community => 'You must provide a (brief) community description.'
             );
    $lt{'unofficial'} = $lt{'official'};
    my $js_validate = <<"ENDJS";
<script type="text/javascript">
// <![CDATA['

function validateForm() {
    if ((document.$formname.cdescr.value == "")  || (document.$formname.cdescr.value == "undefined")) {
        alert('$lt{$crstype}');
        return;
    }
    nextPage(document.$formname,'$next');
}

function toggleCloning() {
    var willclone;
    if (document.$formname.cloning.length > 1) {
        for (var i=0; i<document.$formname.cloning.length; i++) {
            if (document.$formname.cloning[i].checked) {
                willclone = document.$formname.cloning[i].value;
            }
        }
    }
    if (willclone == 1) {
        document.getElementById('cloneoptions').style.display="block";
    } else {
        document.getElementById('cloneoptions').style.display="none";
        document.$formname.clonecrs.value = '';
    }
}

// ]]
</script>

ENDJS
    my $title = &mt('Brief Course Description');
    my $clonetitle = &mt('Clone content and settings from an existing course?');
    if ($crstype eq 'community') {
        $title = &mt('Brief Community Description');
        $clonetitle = &mt('Clone content and settings from an existing community?');
    }
    my $output .= $js_validate."\n".&Apache::lonhtmlcommon::start_pick_box().
                  &Apache::lonhtmlcommon::row_headline().
                  '<h3>'.&Apache::loncommon::help_open_topic('Course_Request_Description').'&nbsp;'.$title.'</h3>'.
                  &Apache::lonhtmlcommon::row_closure(1).
                  &Apache::lonhtmlcommon::row_title(&mt('Description')).
                 '<input type="text" size="60" name="cdescr" value="'.$description.'" />';
    my ($home_server_pick,$numlib) =
        &Apache::loncommon::home_server_form_item($dom,'chome',
                                                  'default','hide');
    if ($numlib > 1) {
        $output .= &Apache::lonhtmlcommon::row_closure().
                   &Apache::lonhtmlcommon::row_title(&mt('Home Server for Course'));
    }
    $output .= $home_server_pick.
               &Apache::lonhtmlcommon::row_closure().
               &Apache::lonhtmlcommon::row_headline().
               '<h3>'.&Apache::loncommon::help_open_topic('Course_Request_Clone').'&nbsp;'.$clonetitle.
               &Apache::lonhtmlcommon::row_closure(1).
               &Apache::lonhtmlcommon::row_title(&mt('Clone?')).
               '<label><input type="radio" name="cloning" value="1" '.
               'onclick="javascript:toggleCloning()" />'.
               &mt('Yes').('&nbsp;'x2).'</label><label>'.
               '<input type="radio" name="cloning" value="0" checked="checked" '.
               'onclick="javascript:toggleCloning()" />'.&mt('No').'</label>'.
               '</h3>'.
               &Apache::lonhtmlcommon::row_closure(1).
               &Apache::lonhtmlcommon::row_headline().
               '<div id="cloneoptions" style="display: none" >'.
               &Apache::lonhtmlcommon::start_pick_box().
               &clone_form($dom,$formname,$crstype).
               &Apache::lonhtmlcommon::end_pick_box().'</div>'.
               &Apache::lonhtmlcommon::end_pick_box()."\n";
    return $output;
}

sub clone_form {
    my ($dom,$formname,$crstype) = @_;
    my $type = 'Course';
    if ($crstype eq 'community') {
        $type = 'Community';
    }
    my %lt = &clone_text();
    my $output .= 
        &Apache::lonhtmlcommon::row_title($lt{'dmn'}).'<label>'.
        &Apache::loncommon::select_dom_form($dom,'clonedom').'</label>'.
        &Apache::lonhtmlcommon::row_closure(1).
        &Apache::lonhtmlcommon::row_title($lt{'cid'}).'<label>'.
        '<input type="text" size="25" name="clonecrs" value="" onfocus="this.blur();opencrsbrowser('."'$formname','clonecrs','clonedom','','','','','$type'".')" />'.
        '</label>&nbsp;'.
        &Apache::loncommon::selectcourse_link($formname,'clonecrs','clonedom','','','',$type).
        &Apache::lonhtmlcommon::row_closure(1).
        &Apache::lonhtmlcommon::row_title($lt{'dsh'}).'<label>'.
        '<input type="radio" name="datemode" value="delete" /> '.$lt{'ncd'}.
        '</label><br /><label>'.
        '<input type="radio" name="datemode" value="preserve" /> '.$lt{'prd'}.
        '</label><br /><label>'.
        '<input type="radio" name="datemode" value="shift" checked="checked" /> '.
        $lt{'shd'}.'</label>'.
        '<input type="text" size="5" name="dateshift" value="365" />'.
        &Apache::lonhtmlcommon::row_closure(1);
    return $output;
}

sub clone_text {
    return &Apache::lonlocal::texthash(
               'cid'  => 'Course ID',
               'dmn'  => 'Domain',
               'dsh'  => 'Date Shift',
               'ncd'  => 'Do not clone date parameters',
               'prd'  => 'Clone date parameters as-is',
               'shd'  => 'Shift date parameters by number of days',
        );
}

sub coursecode_form {
    my ($dom,$context,$codetitles,$cat_titles,$cat_order,$num) = @_;
    my $output;
    my %rowtitle = &Apache::lonlocal::texthash (
                    instcode  => 'Course Category',
                    crosslist => 'Cross Listed Course',
                   );
    my %helpitem = ( 
                     instcode => 'Course_Request_Category',
                     crosslist => 'Course_Request_Crosslist',
                   );
    if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH') && 
        (ref($cat_order))) {
        my ($sel,$instsec,$lcsec);
        $sel = $context;
        if ($context eq 'crosslist') {
            $sel .= '_'.$num;
            $instsec = &mt('Institutional section').'<br />'.
                       '<input type="text" size="10" name="'.$sel.'_instsec" />';
            $lcsec = &mt('LON-CAPA section').'<br />'.
                     '<input type="text" size="10" name="'.$sel.'_lcsec" />';
        }
        if (@{$codetitles} > 0) {
            my $lastitem = pop(@{$codetitles});
            my $lastinput = '<input type="text" size="5" name="'.$sel.'_'.                                            $lastitem.'" />';
            if (@{$codetitles} > 0) {
                $output = &Apache::lonhtmlcommon::row_title(&Apache::loncommon::help_open_topic($helpitem{$context}).'&nbsp;'.$rowtitle{$context}).
                          '<table><tr>';
                if ($context eq 'crosslist') {
                    $output .= '<td>'.&mt('Include?').'<br />'.
                               '<input type="checkbox" name="'.$sel.'" value="1" /></td>';
                }
                foreach my $title (@{$codetitles}) {
                    if (ref($cat_order->{$title}) eq 'ARRAY') {
                        if (@{$cat_order->{$title}} > 0) {
                            $output .= '<td align="center">'.$title.'<br />'."\n".
                                       '<select name="'.$sel.'_'.$title.'">'."\n".
                                       ' <option value="" selected="selected">'.
                                       &mt('Select').'</option>'."\n";
                            foreach my $item (@{$cat_order->{$title}}) {
                                my $longitem = $item;
                                if (ref($cat_titles->{$title}) eq 'HASH') {
                                    if ($cat_titles->{$title}{$item} ne '') {
                                        $longitem = $cat_titles->{$title}{$item};
                                    }
                                }
                                $output .= '<option value="'.$item.'">'.$longitem.
                                           '</option>'."\n";
                            }
                        }
                        $output .= '</select></td>'."\n";
                    }
                }
                if ($context eq 'crosslist') {
                    $output .= '<td align="center">'.$lastitem.'<br />'."\n".
                               $lastinput.'</td><td align="center">'.$instsec.'</td>'.
                               '<td align="center">'.$lcsec.'</td></tr></table>';
                } else {
                    $output .= '</tr></table>'.
                               &Apache::lonhtmlcommon::row_closure().
                               &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
                               $lastinput;
                }
            } else {
                if ($context eq 'crosslist') {
                    $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
                               '<table><tr>'.
                               '<td align="center">'.$lastitem.'<br />'.$lastinput.'</td>'.
                               '<td align="center">'.$instsec.'</td><td>'.$lcsec.'</td>'.
                               '</tr></table>';
                } else { 
                    $output .= &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
                               $lastinput;
                }
            }
            $output .=  &Apache::lonhtmlcommon::row_closure(1);
            push(@$codetitles,$lastitem);    
        } elsif ($context eq 'crosslist') {
            $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
                       '<table><tr><td align="center">'.
                       '<span class="LC_nobreak">'.&mt('Include?').
                       '<input type="checkbox" name="'.$sel.'" value="1" /></span>'.
                       '</td><td align="center">'.&mt('Institutional ID').'<br />'.
                       '<input type="text" size="10" name="'.$sel.'_instsec" />'.
                       '</td><td align="center">'.$lcsec.'</td></tr></table>'.
                       &Apache::lonhtmlcommon::row_closure(1);
        }
    }
    return $output;
}

sub get_course_dom {
    my $codedom = &Apache::lonnet::default_login_domain();
    if ($env{'form.showdom'} ne '') {
        if (&Apache::lonnet::domain($env{'form.showdom'}) ne '') {
            return $env{'form.showdom'};
        }
    }
    if (($env{'user.domain'} ne '') && ($env{'user.domain'} ne 'public')) {
        my ($types,$typename) = &Apache::loncommon::course_types();
        if (ref($types) eq 'ARRAY') {
            foreach my $type (@{$types}) {
                if (&Apache::lonnet::usertools_access($env{'user.name'},
                                                      $env{'user.domain'},$type,
                                                      undef,'requestcourses')) {
                    return $env{'user.domain'};
                }
            }
            my @possible_doms;
            foreach my $type (@{$types}) {
                my $dom_str = $env{'environment.reqcrsotherdom.'.$type};
                if ($dom_str ne '') {
                    my @domains = split(',',$dom_str);
                    foreach my $entry (@domains) {
                        my ($extdom,$extopt) = split(':',$entry);
                        if ($extdom eq $env{'request.role.domain'}) {
                            return $extdom;
                        } 
                        unless(grep(/^\Q$extdom\E$/,@possible_doms)) {
                            push(@possible_doms,$extdom);
                        }
                    }
                }
            }
            if (@possible_doms) {
                @possible_doms = sort(@possible_doms);
                return $possible_doms[0];
            }
        }
        $codedom = $env{'user.domain'};
        if ($env{'request.role.domain'} ne '') {
            $codedom = $env{'request.role.domain'};
        }
    }
    return $codedom;
}

sub display_navbuttons {
    my ($r,$dom,$formname,$prev,$prevtext,$next,$nexttext,$state,$other,$othertext) = @_;
    $r->print('<div class="LC_navbuttons">');
    if ($prev) {
        $r->print('<input type="button" name="previous" value = "'.$prevtext.'" '.
                  'onclick="javascript:backPage('."document.$formname,'$prev'".')"/>'.
                  ('&nbsp;'x3));
    } elsif ($prevtext) {
        $r->print('<input type="button" name="previous" value = "'.$prevtext.'" '.
                  'onclick="javascript:history.back()"/>'.('&nbsp;'x3));
    }
    if ($state eq 'details') {
        $r->print(' <input type="button" name="other" value="'.$othertext.'" '.
                  'onclick="javascript:nextPage('."document.$formname,'$other'".
                  ')" />');
    }
    my $gotnext;
    if ($state eq 'courseinfo') {
        $r->print('<input type="button" name="next" value="'.$nexttext.'" '.
                  'onclick="javascript:validateForm();" />');
        $gotnext = 1;
    } elsif ($state eq 'enrollment') {
        if (($env{'form.crstype'} eq 'official') && 
            (&Apache::lonnet::auto_run('',$dom))) {
            $r->print('<input type="button" name="next" value="'.$nexttext.'" '.
                      'onclick="javascript:validateEnrollSections('."document.$formname,'$next'".');" />');
                $gotnext = 1;
        }
    } elsif ($state eq 'personnel') {
        if ($env{'form.persontotal'} > 0) { 
            $r->print('<input type="button" name="next" value="'.$nexttext.'" '.
                      'onclick="javascript:validatePersonnelSections('."document.$formname,'$next'".');" />');
            $gotnext = 1;
        }
    }
    unless ($gotnext) {
        if ($next) {
            $r->print('
                      <input type="button" name="next" value="'.$nexttext.'" '.
      'onclick="javascript:nextPage('."document.$formname,'$next'".')" />');
        }
    }
    $r->print('</div>');
}

sub print_request_outcome {
    my ($dom,$codetitles,$code_order) = @_;
    my ($output,$cnum,$now,$req_notifylist,$crstype,$enrollstart,$enrollend,
        %sections,%crosslistings,%personnel,@baduname,@missingdom,%domconfig,);
    my $sectotal = $env{'form.sectotal'};
    my $crosslisttotal = 0;
    $cnum = $env{'form.cnum'};
    unless ($cnum =~ /^$match_courseid$/) {
        $output = &mt('Invalid LON-CAPA course number for the new course')."\n"; 
        return $output;
    }

    %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom);
    if (ref($domconfig{'requestcourses'}) eq 'HASH') {
        if (ref($domconfig{'requestcourses'}{'notify'}) eq 'HASH') {
            $req_notifylist = $domconfig{'requestcourses'}{'notify'}{'approval'};
        }
    }
    $now = time;
    $crstype = $env{'form.crstype'};
    my $ccrole = 'cc';
    if ($crstype eq 'community') {
        $ccrole = 'co';
    }
    my @instsections;
    if ($crstype eq 'official') {
        if (&Apache::lonnet::auto_run('',$dom)) {
            ($enrollstart,$enrollend)=&dates_from_form('enrollstart','enrollend');
        }
        for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
            if ($env{'form.sec_'.$i}) {
                if ($env{'form.secnum_'.$i} ne '') {
                    my $sec = $env{'form.secnum_'.$i};
                    $sections{$i}{'inst'} = $sec;
                    if (($sec ne '') && (!grep(/^\Q$sec\E$/,@instsections))) {
                        push(@instsections,$sec);
                    }
                    $sections{$i}{'loncapa'} = $env{'form.loncapasec_'.$i};
                    $sections{$i}{'loncapa'} =~ s/\W//g;
                    if ($sections{$i}{'loncapa'} eq 'none') {
                        $sections{$i}{'loncapa'} = '';
                    }
                }
            }
        }
        for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
            if ($env{'form.crosslist_'.$i}) {
                my $xlistinfo = '';
                if (ref($code_order) eq 'ARRAY') {
                    if (@{$code_order} > 0) {
                        foreach my $item (@{$code_order}) {
                            $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item};
                        }
                    }
                }
                $crosslistings{$i}{'instcode'} = $xlistinfo;
                if ($xlistinfo ne '') {
                    $crosslisttotal ++;
                }
                $crosslistings{$i}{'instsec'} = $env{'form.crosslist_'.$i.'_instsec'}; 
                $crosslistings{$i}{'loncapa'} = $env{'form.crosslist_'.$i.'_lcsec'};
            }
        }
    } else {
        $enrollstart = '';
        $enrollend = '';
    }
    my (%alerts,%rulematch,%inst_results,%curr_rules,%got_rules,%disallowmsg);
    for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
        my $uname = $env{'form.person_'.$i.'_uname'};
        my $udom = $env{'form.person_'.$i.'_dom'};
        if (($uname =~ /^$match_username$/) && ($udom =~ /^$match_domain$/)) {
            if (&Apache::lonnet::domain($udom) ne '') {
                unless (ref($personnel{$uname.':'.$udom}) eq 'HASH') {
                    $personnel{$uname.':'.$udom} = {
                             firstname    => $env{'form.person_'.$i.'_firstname'},
                             lastname     => $env{'form.person_'.$i.'_lastname'},
                             emailaddr    => $env{'form.person_'.$i.'_emailaddr'},
                                                   };
                    my $usertype = &get_usertype($udom,$uname,\%curr_rules,\%got_rules);
                    if (&Apache::lonuserutils::can_create_user($udom,'requestcrs',$usertype)) {
                        my ($allowed,$msg,$authtype,$authparam) =
                            &check_newuser_rules($udom,$uname,\%alerts,\%rulematch,
                                                 \%inst_results,\%curr_rules,\%got_rules);
                        if ($allowed) {
                            my %domdefaults = &Apache::lonnet::get_domain_defaults($udom);
                            if ($usertype eq 'official') {
                                if ($authtype eq '') {
                                    $authtype = $domdefaults{'auth_def'};
                                    $authparam = $domdefaults{'auth_arg_def'};
                                } else {
                                    if ($authtype eq 'loc') {
                                        $authtype = 'localauth';
                                    } elsif ($authtype eq 'int') {
                                        $authtype = 'internal';
                                    }
                                    if ($authtype !~ /^(krb4|krb5|internal|localauth)$/) {
                                        $authtype = $domdefaults{'auth_def'};
                                        $authparam = $domdefaults{'auth_arg_def'};
                                    }
                                }
                            } elsif ($usertype eq 'unofficial') {
                                if ($authtype eq '') {
                                    $authtype = 'internal';
                                    $authparam = '';
                                }
                            } else {
                                $authtype = $domdefaults{'auth_def'};
                                $authparam = $domdefaults{'auth_arg_def'};
                            }
                            if (($authtype eq '') ||
                                (($authtype =~/^krb(4|5)$/) && ($authparam eq '')) ||
                                ($authtype !~ /^(krb4|krb5|internal|localauth)$/)) {
                                next;
                            } else {
                                $personnel{$uname.':'.$udom}{'authtype'} = $authtype;
                                $personnel{$uname.':'.$udom}{'autharg'} = $authparam;
                            }
                        } else {
                            next;
                        }
                    } else {
                        next;
                    }
                }
                my $role = $env{'form.person_'.$i.'_role'};
                unless ($role eq '') {
                    if (ref($personnel{$uname.':'.$udom}{'roles'}) eq 'ARRAY') {
                        my @curr_roles = @{$personnel{$uname.':'.$udom}{'roles'}};
                        unless (grep(/^\Q$role\E$/,@curr_roles)) {
                            push(@{$personnel{$uname.':'.$udom}{'roles'}},$role);
                        }
                    } else {
                        @{$personnel{$uname.':'.$udom}{'roles'}} = ($role);
                    }
                    if ($role eq $ccrole) {
                        @{$personnel{$uname.':'.$udom}{$role}{'usec'}} = ();
                    } else {
                        my @currsec = &Apache::loncommon::get_env_multiple('form.person_'.$i.'_sec');
                        my @allsecs;
                        foreach my $sec (@currsec) {
                            next unless ($sec =~ /\w/);
                            next if ($sec =~ /\W/);
                            next if ($sec eq 'none');
                            push(@allsecs,$sec);
                        }
                        my $newsec = $env{'form.person_'.$i.'_newsec'};
                        $newsec =~ s/^\s+//;
                        $newsec =~s/\s+$//;
                        my @newsecs = split(/[\s,;]+/,$newsec);
                        foreach my $sec (@newsecs) {
                            next if ($sec =~ /\W/);
                            next if ($sec eq 'none');
                            if ($sec ne '') {
                                unless (grep(/^\Q$sec\E$/,@allsecs)) {
                                    push(@allsecs,$sec);
                                }
                            }
                        }
                        @{$personnel{$uname.':'.$udom}{$role}{'usec'}} = @allsecs;
                    }
                }
            } else {
                push(@missingdom,$uname.':'.$udom);
            }
        } else {
            push(@baduname,$uname.':'.$udom);
        }
    }
    my ($accessstart,$accessend) = &dates_from_form('accessstart','accessend');
    my $autodrops = 0;
    if ($env{'form.autodrops'}) {
        $autodrops = $env{'form.autodrops'}; 
    }
    my $autoadds = 0;
    if ($env{'form.autoadds'}) {
        $autoadds = $env{'form.autoadds'};
    }
    my $instcode = '';
    if (exists($env{'form.instcode'})) {
        $instcode = $env{'form.instcode'};
    }
    my $clonecrs = '';
    my $clonedom = '';
    if (($env{'form.cloning'}) &&
        ($env{'form.clonecrs'} =~ /^($match_courseid)$/) && 
        ($env{'form.clonedom'} =~ /^($match_domain)$/)) {
        my $clonehome = &Apache::lonnet::homeserver($env{'form.clonecrs'},
                                                    $env{'form.clonedom'});
        if ($clonehome ne 'no_host') {  
            my $canclone =  
                &Apache::loncoursequeueadmin::can_clone_course($env{'user.name'},
                        $env{'user.domain'},$env{'form.clonecrs'},$env{'form.clonedom'},
                        $crstype);
            if ($canclone) {
                $clonecrs = $env{'form.clonecrs'};
                $clonedom = $env{'form.clonedom'};
            }
        }
    }
    my $details = {
                    owner          => $env{'user.name'},
                    domain         => $env{'user.domain'}, 
                    cdom           => $dom,
                    cnum           => $cnum,
                    coursehome     => $env{'form.chome'},
                    cdescr         => $env{'form.cdescr'},
                    crstype        => $env{'form.crstype'},
                    instcode       => $instcode,
                    clonedom       => $clonedom,
                    clonecrs       => $clonecrs,
                    datemode       => $env{'form.datemode'},
                    dateshift      => $env{'form.dateshift'},
                    sectotal       => $sectotal,
                    sections       => \%sections,
                    crosslisttotal => $crosslisttotal,
                    crosslists     => \%crosslistings,
                    autoadds       => $autoadds,
                    autodrops      => $autodrops,
                    enrollstart    => $enrollstart,
                    enrollend      => $enrollend,
                    accessstart    => $accessstart,
                    accessend      => $accessend,
                    personnel      => \%personnel,
                  };
    my (@inststatuses,$storeresult,$creationresult);
    my $val = 
        &Apache::loncoursequeueadmin::get_processtype($env{'user.name'},$env{'user.domain'},
            $env{'user.adv'},$dom,$crstype,\@inststatuses,\%domconfig);
    if ($val eq '') {
        if ($crstype eq 'official') {
            $output = &mt('You are not permitted to request creation of official courses.');
        } elsif ($crstype eq 'unofficial') {
            $output = &mt('You are not permitted to request creation of unofficial courses.');
        } elsif ($crstype eq 'community') {
            $output = &mt('You are not permitted to request creation of communities');
        } else {
            $output = &mt('Unrecognized course type: [_1]',$crstype);
        }
        $storeresult = 'notpermitted'; 
    } else {
        my ($disposition,$message,$reqstatus);
        my %reqhash = (
                        reqtime   => $now,
                        crstype   => $crstype,
                        details   => $details,
                      );
        my $requestkey = $dom.'_'.$cnum;
        my $validationerror;
        if ($val eq 'autolimit=') {
            $disposition = 'process';
        } elsif ($val =~ /^autolimit=(\d+)$/) {
            my $limit = $1;
            $disposition = &check_autolimit($env{'user.name'},$env{'user.domain'},
                                            $dom,$crstype,$limit,\$message);
        } elsif ($val eq 'validate') {
            my ($inststatuslist,$validationchk,$validation);
            if (@inststatuses > 0) {
                $inststatuslist = join(',',@inststatuses);
            }
            my $instseclist;
            if (@instsections > 0) {
                $instseclist = join(',',@instsections);
            }
            $validationchk = 
                &Apache::lonnet::auto_courserequest_validation($dom,
                    $env{'user.name'}.':'.$env{'user.domain'},$crstype,
                    $inststatuslist,$instcode,$instseclist);
            if ($validationchk =~ /:/) {
                ($validation,$message) = split(':',$validationchk);
            } else {
                $validation = $validationchk;
            }
            if ($validation =~ /^error(.*)$/) {
                $disposition = 'approval';
                $validationerror = $1;
            } else {
                $disposition = $validation;
            }
        } else {
            $disposition = 'approval';
        }
        $reqhash{'disposition'} = $disposition;
        $reqstatus = $disposition;
        my ($modified,$queued);
        if ($disposition eq 'rejected') {
            if ($crstype eq 'community') {
                $output = &mt('Your community request was rejected.');
            } else {
                $output = &mt('Your course request was rejected.');
            }
            if ($message) {
                $output .= '<div class="LC_warning">'.$message.'</div>';
            }
            $storeresult = 'rejected';
        } elsif ($disposition eq 'process') {
            my %domdefs = &Apache::lonnet::get_domain_defaults($dom);
            my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,%longroles);
            my $type = 'Course';
            if ($crstype eq 'community') {
                $type = 'Community';
            }
            my @roles = &Apache::lonuserutils::roles_by_context('course','',$type);
            foreach my $role (@roles) {
                $longroles{$role}=&Apache::lonnet::plaintext($role,$type);
            }
            my $result = &Apache::loncoursequeueadmin::course_creation($dom,$cnum,
                                   'autocreate',$details,\$logmsg,\$newusermsg,\$addresult,
                                   \$enrollcount,\$response,\$keysmsg,\%domdefs,\%longroles);
            if ($result eq 'created') {
                $disposition = 'created';
                $reqstatus = 'created';
                my $role_result = &update_requestors_roles($dom,$cnum,$crstype,$details,
                                                           \%longroles);
                if ($crstype eq 'community') {
                    $output = '<p>'.&mt('Your community request has been processed and the community has been created.');
                } else {
                    $output = '<p>'.&mt('Your course request has been processed and the course has been created.');
                }
                $output .= '<br />'.$role_result.'</p>';
                $creationresult = 'created';
            } else {
                $output = '<span class="LC_error">';
                if ($crstype eq 'community') {
                    $output .= &mt('An error occurred when processing your community request.');
                } else {
                    $output .= &mt('An error occurred when processing your course request.');
                }
                $output .= '<br />'.
                           &mt('You may want to review the request details and submit the request again.').
                          '</span>';
                $creationresult = 'error';
            }
        } else {
            my $requestid = $cnum.'_'.$disposition;
            my $request = { 
                            $requestid => {
                                            timestamp   => $now,
                                            crstype     => $crstype,
                                            ownername   => $env{'user.name'},
                                            ownerdom    => $env{'user.domain'},
                                            description => $env{'form.cdescr'}, 
                                          },
                          };
            if ($crstype eq 'official') {
                $request->{$requestid}->{'instcode'} = $instcode;
            }
            my $statuskey = 'status:'.$dom.':'.$cnum;
            my %userreqhash = &Apache::lonnet::get('courserequests',[$statuskey],
                                                   $env{'user.domain'},$env{'user.name'});
            if ($userreqhash{$statuskey} ne '') {
                $modified = 1;
                my $uname = &Apache::lonnet::get_domainconfiguser($dom);
                my %queuehash = &Apache::lonnet::get('courserequestqueue',
                                                     [$cnum.'_approval',
                                                      $cnum.'_pending'],$dom,$uname);
                if (($queuehash{$cnum.'_approval'} ne '') || 
                    ($queuehash{$cnum.'_pending'} ne '')) {
                    $queued = 1;
                }
            }
            unless ($queued) {
                my $putresult = &Apache::lonnet::newput_dom('courserequestqueue',$request,
                                                            $dom);
                if ($putresult eq 'ok') {
                    if ($crstype eq 'community') {
                        $output .= &mt('Your community request has been recorded.');
                    } else {
                        $output .= &mt('Your course request has been recorded.') 
                    }
                    $output .= '<br />'.
                              &notification_information($disposition,$req_notifylist,
                                                        $cnum,$now);
                } else {
                    $reqstatus = 'domainerror';
                    $reqhash{'disposition'} = $disposition;
                    my $warning = &mt('An error occurred saving your request in the pending requests queue.');
                    $output = '<span class"LC_warning">'.$warning.'</span><br />';
                }
            }
        }
        ($storeresult,my $updateresult) = 
            &Apache::loncoursequeueadmin::update_coursereq_status(\%reqhash,$dom,
                $cnum,$reqstatus,'request');
        if ($modified && $queued && $storeresult eq 'ok') {
            if ($crstype eq 'community') {
                $output .= '<p>'.&mt('Your community request has been updated').'</p>';
            } else {
                $output .= '<p>'.&mt('Your course request has been updated').'</p>';
            }
            $output .= &notification_information($disposition,$req_notifylist,$cnum,$now);
        }
        if ($validationerror ne '') {
            $output .= '<p class="LC_warning">'.&mt('An error occurred validating your request with institutional data sources: [_1].',$validationerror).'</p>';
        }
        if ($updateresult) {
            $output .= $updateresult;
        }
    }
    if ($creationresult ne '') {
        return ($creationresult,$output);
    } else {
        return ($storeresult,$output);
    }
}

sub update_requestors_roles {
    my ($dom,$cnum,$crstype,$details,$longroles) = @_;
    my $now = time;
    my ($active,$future,$numactive,$numfuture,$output);
    my $owner = $env{'user.name'}.':'.$env{'user.domain'};
    if (ref($details) eq 'HASH') {
        if (ref($details->{'personnel'}) eq 'HASH') {
            my $ccrole = 'cc';
            if ($crstype eq 'community') {
                $ccrole = 'co';
            }
            unless (ref($details->{'personnel'}{$owner}) eq 'HASH') {
                $details->{'personnel'}{$owner} = {
                                                    'roles' => [$ccrole],
                                                    $ccrole => { 'usec' => [] },
                                                  };
            }
            my @roles;
            if (ref($details->{'personnel'}{$owner}{'roles'}) eq 'ARRAY') {
                @roles = sort(@{$details->{'personnel'}{$owner}{'roles'}});
                unless (grep(/^\Q$ccrole\E$/,@roles)) {
                    push(@roles,$ccrole);
                }
            } else {
                @roles = ($ccrole);
            }
            foreach my $role (@roles) {
                my $refresh=$env{'user.refresh.time'};
                if ($refresh eq '') {
                    $refresh = $env{'user.login.time'};
                }
                if ($refresh eq '') {
                    $refresh = $now;
                }
                my $start = $refresh-1;
                my $end = '0';
                if ($role eq 'st') {
                    if ($details->{'accessstart'} ne '') {
                        $start = $details->{'accessstart'};
                    }
                    if ($details->{'accessend'} ne '') {
                        $end = $details->{'accessend'};
                    }
                }
                my @usecs;
                if ($role ne $ccrole) {
                    if (ref($details->{'personnel'}{$owner}{$role}{'usec'}) eq 'ARRAY') {
                        @usecs = @{$details->{'personnel'}{$owner}{$role}{'usec'}};
                    }
                } 
                if ($role eq 'st') {
                    if (@usecs > 1) {
                        my $firstsec = $usecs[0];
                        @usecs = ($firstsec);
                    }
                }
                if (@usecs == 0) {
                    push(@usecs,'');
                }
                foreach my $usec (@usecs) {
                    my (%userroles,%newrole,%newgroups,$spec,$area);
                    my $area = '/'.$dom.'/'.$cnum;
                    my $spec = $role.'.'.$area;
                    if ($usec ne '') {
                       $spec .= '/'.$usec;
                       $area .= '/'.$usec;
                    }
                    if ($role =~ /^cr\//) {
                        &Apache::lonnet::custom_roleprivs(\%newrole,$role,$dom,
                                                          $cnum,$spec,$area);
                    } else {
                        &Apache::lonnet::standard_roleprivs(\%newrole,$role,$dom,
                                                            $spec,$cnum,$area);
                    }
                    &Apache::lonnet::set_userprivs(\%userroles,\%newrole,
                                                   \%newgroups);
                    $userroles{'user.role.'.$spec} = $start.'.'.$end;
                    &Apache::lonnet::appenv(\%userroles,[$role,'cm']);
                    if (($end == 0) || ($end > $now)) {
                        my $showrole = $role;
                        if ($role =~ /^cr\//) {
                            $showrole = &Apache::lonnet::plaintext($role,$crstype);
                        } elsif (ref($longroles) eq 'HASH') {
                            if ($longroles->{$role} ne '') {
                                $showrole = $longroles->{$role};
                            }
                        }
                        if ($start <= $now) {
                            $active .= '<li><a href="/adm/roles?selectrole=1&'.
                                       $spec.'=1">'.$showrole;
                            if ($usec ne '') {
                                $active .= ' - '.&mt('section:').' '.$usec; 
                            }
                            $active .= '</a></li>';
                            $numactive ++;
                        } else { 
                            $future .= '<li>'.$showrole;
                            if ($usec ne '') {
                                $future .= ' - '.&mt('section:').' '.$usec;
                            }
                            $future .= '</li>';
                            $numfuture ++;
                        }
                    }
                }
            }
        }
    }
    if ($active) {
        if ($numactive == 1) {
            if ($crstype eq 'Community') {
                $output = &mt('Use the following link to enter the community:');
            } else {
                $output = &mt('Use the following link to enter the course:'); 
            }
        } else {
            if ($crstype eq 'Community') {
                $output = &mt('Use the following links to your new roles to enter the community:');
            } else {
                $output = &mt('Use the following links to your new roles to enter the course:');
            }
        }
        $output .= ' <ul>'.$active.'</ul><br />';
    }
    if ($future) {
        if ($crstype eq 'Community') {
            $output .= &mt('The following community [quant,_1,role] will become available for selection from your [_2]roles page[_3], once the default student access start date - [_4] - has been reached:',$numfuture,'<a href="/adm/roles">','</a>',&Apache::lonlocal::locallocaltime($details->{'accessstart'}))
        } else {
            $output .= &mt('The following course [quant,_1,role] will become available for selection from your [_2]roles page[_3], once the default student access start date - [_4] - has been reached:',$numfuture,'<a href="/adm/roles">','</a>',&Apache::lonlocal::locallocaltime($details->{'accessstart'}));
        }
        $output .= ' <ul>'.$future.'</ul>';
    }
    return $output;
}

sub notification_information {
    my ($disposition,$req_notifylist,$cnum,$now) = @_;
    my %emails = &Apache::loncommon::getemails();
    my $address;
    if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) {
        $address = $emails{'permanentemail'};
        if ($address eq '') {
            $address = $emails{'notification'};
        }
    }
    my $output;
    if ($disposition eq 'approval') {
        $output .= &mt('A message will be sent to your LON-CAPA account when a domain coordinator takes action on your request.').'<br />'.
                   &mt('To access your LON-CAPA message, go to the Main Menu and click on "Send and Receive Messages".').'<br />';
        if ($address ne '') {
            $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address).'<br />';
        }
        if ($req_notifylist) {
            my $fullname = &Apache::loncommon::plainname($env{'user.name'},
                                                                     $env{'user.domain'});
            my $sender = $env{'user.name'}.':'.$env{'user.domain'};
            &Apache::loncoursequeueadmin::send_selfserve_notification($req_notifylist,"$fullname ($env{'user.name'}:$env{'user.domain'})",$cnum,$env{'form.cdescr'},$now,'coursereq',$sender);
        }
    } elsif ($disposition eq 'pending') {
        $output .= '<div class="LC_info">'.
&mt('Your request has been placed in a queue pending administrative action.').'<br />'.
&mt("Usually this means that your institution's information systems do not list you among the instructional personnel for this course.").'<br />'.
&mt('The list of instructional personnel for the course will be automatically checked daily, and once you are listed the request will be processed.').
                   '</div>';
    } else {
        $output .= '<div class="LC_warning">'.
                   &mt('Your request status is: [_1].',$disposition).
                   '</div>';
    }
    return $output;
}

sub check_autolimit {
    my ($uname,$udom,$dom,$crstype,$limit,$message) = @_;
    my %crsroles = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},
                       'userroles',['active','future'],['cc','co'],[$dom]);
    my ($types,$typename) = &Apache::loncommon::course_types();
    my %requests = &Apache::lonnet::dumpstore('courserequests',$udom,$uname);
    my $count = 0;
    foreach my $key (keys(%requests)) {
        my ($cdom,$cnum) = split('_',$key);
        if (ref($requests{$key}) eq 'HASH') {
            next if ($requests{$key}{'crstype'} ne $crstype);
            if (($crstype eq 'community') && 
                (exists($crsroles{$cnum.':'.$cdom.':co'}))) {
                $count ++;
            } elsif ((($crstype eq 'official') || ($crstype eq 'unofficial')) &&
                     (exists($crsroles{$cnum.':'.$cdom.':cc'}))) {
                $count ++;
            }
        }
    }
    if ($count < $limit) {
        return 'process';
    } else {
        if (ref($typename) eq 'HASH') {
            if ($crstype eq 'community') {
                $$message = &mt('Your request has not been processed because you have reached the limit for the number of communities.').
                            '<br />'.&mt("Your limit is [_1].",$limit);
            } else {
                $$message = &mt('Your request has not been processed because you have reached the limit for the number of courses of this type.').
                            '<br />'.&mt("Your $typename->{$crstype} limit is [_1].",$limit);
            }
        }
        return 'rejected';
    }
    return;
}

sub retrieve_settings {
    my ($dom,$cnum,$udom,$uname) = @_;
    if ($udom eq '' || $uname eq '') {
        $udom = $env{'user.domain'};
        $uname = $env{'user.name'};
    }
    my ($result,%reqinfo) = &get_request_settings($dom,$cnum,$udom,$uname);
    if ($result eq 'ok') {
        if (($udom eq $reqinfo{'domain'}) &&  ($uname eq $reqinfo{'owner'})) {
            $env{'form.chome'} = $reqinfo{'coursehome'};
            $env{'form.cdescr'} = $reqinfo{'cdescr'};
            $env{'form.crstype'} = $reqinfo{'crstype'}; 
            &generate_date_items($reqinfo{'accessstart'},'accessstart');
            &generate_date_items($reqinfo{'accessend'},'accessend');
            if ($reqinfo{'accessend'} == 0) {
                $env{'form.no_end_date'} = 1;
            }
            if (($reqinfo{'crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) {
                &generate_date_items($reqinfo{'enrollstart'},'enrollstart');
                &generate_date_items($reqinfo{'enrollend'},'enrollend');
            }
            $env{'form.clonecrs'} = $reqinfo{'clonecrs'};
            $env{'form.clonedom'} = $reqinfo{'clonedom'};
            if (($reqinfo{'clonecrs'} ne '') && ($reqinfo{'clonedom'} ne '')) {
                $env{'form.cloning'} = 1;
            }
            $env{'form.datemode'} = $reqinfo{'datemode'};
            $env{'form.dateshift'} = $reqinfo{'dateshift'};
            if ($reqinfo{'crstype'} eq 'official') {
                $env{'form.autoadds'} = $reqinfo{'autoadds'};
                $env{'form.autodrops'} = $reqinfo{'autodrops'};
                if ($reqinfo{'instcode'} ne '') { 
                    $env{'form.sectotal'} = $reqinfo{'sectotal'};
                    $env{'form.crosslisttotal'} = $reqinfo{'crosslisttotal'};
                    $env{'form.instcode'} = $reqinfo{'instcode'};
                    my $crscode = { 
                                    $cnum => $reqinfo{'instcode'},
                                  };
                    &extract_instcode($dom,'instcode',$crscode,$cnum);
                }
            }
            my @currsec;
            if (ref($reqinfo{'sections'}) eq 'HASH') {
                foreach my $i (sort(keys(%{$reqinfo{'sections'}}))) {
                    if (ref($reqinfo{'sections'}{$i}) eq 'HASH') {
                        my $sec = $reqinfo{'sections'}{$i}{'inst'};
                        $env{'form.secnum_'.$i} = $sec;
                        $env{'form.sec_'.$i} = '1';
                        if (!grep(/^\Q$sec\E$/,@currsec)) {
                            push(@currsec,$sec);
                        }
                        $env{'form.loncapasec_'.$i} = $reqinfo{'sections'}{$i}{'loncapa'};
                    }
                }
            }
            if (ref($reqinfo{'crosslists'}) eq 'HASH') {
                foreach my $i (sort(keys(%{$reqinfo{'crosslists'}}))) {
                    if (ref($reqinfo{'crosslists'}{$i}) eq 'HASH') {
                        $env{'form.crosslist_'.$i} = '1';
                        $env{'form.crosslist_'.$i.'_instsec'} = $reqinfo{'crosslists'}{$i}{'instsec'};
                        $env{'form.crosslist_'.$i.'_lcsec'} = $reqinfo{'crosslists'}{$i}{'loncapa'};
                        if ($reqinfo{'crosslists'}{$i}{'instcode'} ne '') {
                            my $key = $cnum.$i; 
                            my $crscode = {
                                              $key => $reqinfo{'crosslists'}{$i}{'instcode'},
                                          };
                            &extract_instcode($dom,'crosslist',$crscode,$key,$i);
                        }
                    }
                }
            }
            if (ref($reqinfo{'personnel'}) eq 'HASH') {
                my $i = 0;
                foreach my $user (sort(keys(%{$reqinfo{'personnel'}}))) {
                    my ($uname,$udom) = split(':',$user);
                    if (ref($reqinfo{'personnel'}{$user}) eq 'HASH') {
                        if (ref($reqinfo{'personnel'}{$user}{'roles'}) eq 'ARRAY') {
                            foreach my $role (sort(@{$reqinfo{'personnel'}{$user}{'roles'}})) {
                                $env{'form.person_'.$i.'_role'} = $role;
                                $env{'form.person_'.$i.'_firstname'} = $reqinfo{'personnel'}{$user}{'firstname'};
                                $env{'form.person_'.$i.'_lastname'} = $reqinfo{'personnel'}{$user}{'lastname'}; ;
                                $env{'form.person_'.$i.'_emailaddr'} = $reqinfo{'personnel'}{$user}{'emailaddr'};
                                $env{'form.person_'.$i.'_uname'} = $uname;
                                $env{'form.person_'.$i.'_dom'} = $udom;
                                if (ref($reqinfo{'personnel'}{$user}{$role}) eq 'HASH') {
                                    if (ref($reqinfo{'personnel'}{$user}{$role}{'usec'}) eq 'ARRAY') {
                                        my @usecs = @{$reqinfo{'personnel'}{$user}{$role}{'usec'}};
                                        my @newsecs;
                                        if (@usecs > 0) {
                                            foreach my $sec (@usecs) {
                                                if (grep(/^\Q$sec\E/,@currsec)) {
                                                    $env{'form.person_'.$i.'_sec'} = $sec;
                                                } else {
                                                    push(@newsecs,$sec);
                                                }
                                            }
                                        }
                                        if (@newsecs > 0) {
                                            $env{'form.person_'.$i.'_newsec'} = join(',',@newsecs); 
                                        }
                                    }
                                }
                                $i ++;
                            }
                        }
                    }
                }
                $env{'form.persontotal'} = $i;
            }
        }
    }
    return $result;
}

sub get_request_settings {
    my ($dom,$cnum,$udom,$uname) = @_;
    my $requestkey = $dom.'_'.$cnum;
    my ($result,%reqinfo);
    if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
        my %history = &Apache::lonnet::restore($requestkey,'courserequests',$udom,$uname);
        my $disposition = $history{'disposition'};
        if (($disposition eq 'approval') || ($disposition eq 'pending')) { 
            if (ref($history{'details'}) eq 'HASH') {
                %reqinfo = %{$history{'details'}};
                $result = 'ok';
            } else {
                $result = 'nothash';
            }
        } else {
            $result = 'notqueued';
        }
    } else {
        $result = 'invalid';
    }
    return ($result,%reqinfo);
}

sub extract_instcode {
    my ($cdom,$element,$crscode,$crskey,$counter) = @_;
    my (%codes,@codetitles,%cat_titles,%cat_order);
    if (&Apache::lonnet::auto_instcode_format('requests',$cdom,$crscode,\%codes,
                                              \@codetitles,\%cat_titles,
                                              \%cat_order) eq 'ok') {
        if (ref($codes{$crskey}) eq 'HASH') {
            if (@codetitles > 0) {
                my $sel = $element;
                if ($element eq 'crosslist') {
                    $sel .= '_'.$counter;
                }
                foreach my $title (@codetitles) {
                    $env{'form.'.$sel.'_'.$title} = $codes{$crskey}{$title};
                }
            }
        }
    }
    return;
}

sub generate_date_items {
    my ($currentval,$item) = @_;
    if ($currentval =~ /\d+/) {
        my ($tzname,$sec,$min,$hour,$mday,$month,$year) = 
            &Apache::lonhtmlcommon::get_timedates($currentval);
        $env{'form.'.$item.'_day'} = $mday;
        $env{'form.'.$item.'_month'} = $month+1;
        $env{'form.'.$item.'_year'} = $year;
    }
    return;
}

1;


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