--- loncom/interface/loncommon.pm	2003/12/01 14:36:22	1.157
+++ loncom/interface/loncommon.pm	2004/06/11 02:21:45	1.192
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.157 2003/12/01 14:36:22 matthew Exp $
+# $Id: loncommon.pm,v 1.192 2004/06/11 02:21:45 taceyjo1 Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -74,6 +74,7 @@ my $readit;
 my %language;
 my %supported_language;
 my %cprtag;
+my %scprtag;
 my %fe; my %fd;
 my %category_extensions;
 
@@ -102,32 +103,48 @@ BEGIN {
     unless ($readit) {
 # ------------------------------------------------------------------- languages
     {
-	my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.
-				 '/language.tab');
-	if ($fh) {
-	    while (<$fh>) {
-		next if /^\#/;
-		chomp;
-		my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_));
-		$language{$key}=$val.' - '.$enc;
-		if ($sup) {
-		    $supported_language{$key}=$sup;
-		}
-	    }
-	}
+        my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}.
+                                   '/language.tab';
+        if ( open(my $fh,"<$langtabfile") ) {
+            while (<$fh>) {
+                next if /^\#/;
+                chomp;
+                my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_));
+                $language{$key}=$val.' - '.$enc;
+                if ($sup) {
+                    $supported_language{$key}=$sup;
+                }
+            }
+            close($fh);
+        }
     }
 # ------------------------------------------------------------------ copyrights
     {
-	my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonIncludes'}.
-				  '/copyright.tab');
-	if ($fh) {
-	    while (<$fh>) {
-		next if /^\#/;
-		chomp;
-		my ($key,$val)=(split(/\s+/,$_,2));
-		$cprtag{$key}=$val;
-	    }
-	}
+        my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
+                                  '/copyright.tab';
+        if ( open (my $fh,"<$copyrightfile") ) {
+            while (<$fh>) {
+                next if /^\#/;
+                chomp;
+                my ($key,$val)=(split(/\s+/,$_,2));
+                $cprtag{$key}=$val;
+            }
+            close($fh);
+        }
+    }
+# ------------------------------------------------------------------ source copyrights
+    {
+        my $sourcecopyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
+                                  '/source_copyright.tab';
+        if ( open (my $fh,"<$sourcecopyrightfile") ) {
+            while (<$fh>) {
+                next if /^\#/;
+                chomp;
+                my ($key,$val)=(split(/\s+/,$_,2));
+                $scprtag{$key}=$val;
+            }
+            close($fh);
+        }
     }
 
 # -------------------------------------------------------------- domain designs
@@ -138,15 +155,16 @@ BEGIN {
     while ($filename=readdir(DIR)) {
 	my ($domain)=($filename=~/^(\w+)\./);
     {
-	my $fh=Apache::File->new($designdir.'/'.$filename);
-	if ($fh) {
-	    while (<$fh>) {
-		next if /^\#/;
-		chomp;
-		my ($key,$val)=(split(/\=/,$_));
-		if ($val) { $designhash{$domain.'.'.$key}=$val; }
-	    }
-	}
+        my $designfile = $designdir.'/'.$filename;
+        if ( open (my $fh,"<$designfile") ) {
+            while (<$fh>) {
+                next if /^\#/;
+                chomp;
+                my ($key,$val)=(split(/\=/,$_));
+                if ($val) { $designhash{$domain.'.'.$key}=$val; }
+            }
+            close($fh);
+        }
     }
 
     }
@@ -155,32 +173,35 @@ BEGIN {
 
 # ------------------------------------------------------------- file categories
     {
-	my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.
-				  '/filecategories.tab');
-	if ($fh) {
-	    while (<$fh>) {
-		next if /^\#/;
-		chomp;
-		my ($extension,$category)=(split(/\s+/,$_,2));
-		push @{$category_extensions{lc($category)}},$extension;
-	    }
-	}
+        my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}.
+                                  '/filecategories.tab';
+        if ( open (my $fh,"<$categoryfile") ) {
+            while (<$fh>) {
+                next if /^\#/;
+                chomp;
+                my ($extension,$category)=(split(/\s+/,$_,2));
+                push @{$category_extensions{lc($category)}},$extension;
+            }
+            close($fh);
+        }
+
     }
 # ------------------------------------------------------------------ file types
     {
-	my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.
-	       '/filetypes.tab');
-	if ($fh) {
+        my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}.
+               '/filetypes.tab';
+        if ( open (my $fh,"<$typesfile") ) {
             while (<$fh>) {
-		next if (/^\#/);
-		chomp;
-		my ($ending,$emb,$descr)=split(/\s+/,$_,3);
-		if ($descr ne '') { 
-		    $fe{$ending}=lc($emb);
-		    $fd{$ending}=$descr;
-		}
-	    }
-	}
+                next if (/^\#/);
+                chomp;
+                my ($ending,$emb,$descr)=split(/\s+/,$_,3);
+                if ($descr ne '') {
+                    $fe{$ending}=lc($emb);
+                    $fd{$ending}=$descr;
+                }
+            }
+            close($fh);
+        }
     }
     &Apache::lonnet::logthis(
               "<font color=yellow>INFO: Read file types</font>");
@@ -214,10 +235,10 @@ formname and elementname indicate the na
 the element that the results of the browsing selection are to be placed in. 
 
 Specifying 'only' will restrict the browser to displaying only files
-with the given extension.  Can be a comma seperated list.
+with the given extension.  Can be a comma separated list.
 
 Specifying 'omit' will restrict the browser to NOT displaying files
-with the given extension.  Can be a comma seperated list.
+with the given extension.  Can be a comma separated list.
 
 =item * opensearcher(formname, elementname) [javascript]
 
@@ -229,10 +250,11 @@ of the element the selection from the se
 =cut
 
 sub browser_and_searcher_javascript {
+    my $resurl=&lastresurl();
     return <<END;
     var editbrowser = null;
     function openbrowser(formname,elementname,only,omit,titleelement) {
-        var url = '/res/?';
+        var url = '$resurl/?';
         if (editbrowser == null) {
             url += 'launch=1&';
         }
@@ -277,6 +299,23 @@ sub browser_and_searcher_javascript {
 END
 }
 
+sub lastresurl {
+    if ($ENV{'environment.lastresurl'}) {
+	return $ENV{'environment.lastresurl'}
+    } else {
+	return '/res';
+    }
+}
+
+sub storeresurl {
+    my $resurl=&Apache::lonnet::clutter(shift);
+    unless ($resurl=~/^\/res/) { return 0; }
+    $resurl=~s/\/$//;
+    &Apache::lonnet::put('environment',{'lastresurl' => $resurl});
+    &Apache::lonnet::appenv('environment.lastresurl' => $resurl);
+    return 1;
+}
+
 sub studentbrowser_javascript {
    unless (
             (($ENV{'request.course.id'}) && 
@@ -329,7 +368,7 @@ sub coursebrowser_javascript {
    return (<<ENDSTDBRW);
 <script type="text/javascript" language="Javascript" >
     var stdeditbrowser;
-    function opencrsbrowser(formname,uname,udom) {
+    function opencrsbrowser(formname,uname,udom,desc) {
         var url = '/adm/pickcourse?';
         var filter;
         if (filter != null) {
@@ -344,7 +383,8 @@ sub coursebrowser_javascript {
 	   }
         }
         url += 'form=' + formname + '&cnumelement='+uname+
-                                    '&cdomelement='+udom;
+	                            '&cdomelement='+udom+
+                                    '&cnameelement='+desc;
         var title = 'Course_Browser';
         var options = 'scrollbars=1,resizable=1,menubar=0';
         options += ',width=700,height=600';
@@ -356,9 +396,9 @@ ENDSTDBRW
 }
 
 sub selectcourse_link {
-   my ($form,$unameele,$udomele)=@_;
+   my ($form,$unameele,$udomele,$desc)=@_;
     return "<a href='".'javascript:opencrsbrowser("'.$form.'","'.$unameele.
-        '","'.$udomele.'");'."'>".&mt('Select Course')."</a>";
+        '","'.$udomele.'","'.$desc.'");'."'>".&mt('Select Course')."</a>";
 }
 
 =pod
@@ -548,6 +588,8 @@ sub help_open_topic {
     my $template = "";
     my $link;
 
+    $topic=~s/\W/\_/g;
+
     if (!$stayOnPage)
     {
 	$link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
@@ -566,8 +608,9 @@ sub help_open_topic {
     }
 
     # Add the graphic
+    my $title = &mt('Online Help');
     $template .= <<"ENDTEMPLATE";
- <a href="$link"><image src="/adm/help/gif/smallHelp.gif" border="0" alt="(Help: $topic)" /></a>
+ <a href="$link" title="$title"><image src="/adm/help/gif/smallHelp.gif" border="0" alt="(Help: $topic)" /></a>
 ENDTEMPLATE
     if ($text ne '') { $template.='</td></tr></table>' };
     return $template;
@@ -594,15 +637,108 @@ sub helpLatexCheatsheet {
 	.'</td></tr></table>';
 }
 
+sub help_open_bug {
+    my ($topic, $text, $stayOnPage, $width, $height) = @_;
+    unless ($ENV{'user.adv'}) { return ''; }
+    unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }
+    $text = "" if (not defined $text);
+    $stayOnPage = 0 if (not defined $stayOnPage);
+    if ($ENV{'browser.interface'} eq 'textual' ||
+	$ENV{'environment.remote'} eq 'off' ) {
+	$stayOnPage=1;
+    }
+    $width = 600 if (not defined $width);
+    $height = 600 if (not defined $height);
+
+    $topic=~s/\W+/\+/g;
+    my $link='';
+    my $template='';
+    my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='.
+	&Apache::lonnet::escape($ENV{'REQUEST_URI'}).'&component='.$topic;
+    if (!$stayOnPage)
+    {
+	$link = "javascript:void(open('$url', 'Bugzilla', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
+    }
+    else
+    {
+	$link = $url;
+    }
+    # Add the text
+    if ($text ne "")
+    {
+	$template .= 
+  "<table bgcolor='#AA3333' cellspacing='1' cellpadding='1' border='0'><tr>".
+  "<td bgcolor='#FF5555'><a href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
+    }
+
+    # Add the graphic
+    my $title = &mt('Report a Bug');
+    $template .= <<"ENDTEMPLATE";
+ <a href="$link" title="$title"><image src="/adm/lonMisc/smallBug.gif" border="0" alt="(Bug: $topic)" /></a>
+ENDTEMPLATE
+    if ($text ne '') { $template.='</td></tr></table>' };
+    return $template;
+
+}
+
+sub help_open_faq {
+    my ($topic, $text, $stayOnPage, $width, $height) = @_;
+    unless ($ENV{'user.adv'}) { return ''; }
+    unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }
+    $text = "" if (not defined $text);
+    $stayOnPage = 0 if (not defined $stayOnPage);
+    if ($ENV{'browser.interface'} eq 'textual' ||
+	$ENV{'environment.remote'} eq 'off' ) {
+	$stayOnPage=1;
+    }
+    $width = 350 if (not defined $width);
+    $height = 400 if (not defined $height);
+
+    $topic=~s/\W+/\+/g;
+    my $link='';
+    my $template='';
+    my $url=$Apache::lonnet::perlvar{'FAQHost'}.'/fom/cache/'.$topic.'.html';
+    if (!$stayOnPage)
+    {
+	$link = "javascript:void(open('$url', 'FAQ-O-Matic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
+    }
+    else
+    {
+	$link = $url;
+    }
+
+    # Add the text
+    if ($text ne "")
+    {
+	$template .= 
+  "<table bgcolor='#337733' cellspacing='1' cellpadding='1' border='0'><tr>".
+  "<td bgcolor='#448844'><a href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
+    }
+
+    # Add the graphic
+    my $title = &mt('View the FAQ');
+    $template .= <<"ENDTEMPLATE";
+ <a href="$link" title="$title"><image src="/adm/lonMisc/smallFAQ.gif" border="0" alt="(FAQ: $topic)" /></a>
+ENDTEMPLATE
+    if ($text ne '') { $template.='</td></tr></table>' };
+    return $template;
+
+}
+
+###############################################################
+###############################################################
+
 =pod
 
 =item * csv_translate($text) 
 
-Translate $text to allow it to be output as a 'comma seperated values' 
+Translate $text to allow it to be output as a 'comma separated values' 
 format.
 
 =cut
 
+###############################################################
+###############################################################
 sub csv_translate {
     my $text = shift;
     $text =~ s/\"/\"\"/g;
@@ -610,6 +746,60 @@ sub csv_translate {
     return $text;
 }
 
+
+###############################################################
+###############################################################
+
+=pod
+
+=item * define_excel_formats
+
+Define some commonly used Excel cell formats.
+
+Currently supported formats:
+
+=over 4
+
+=item header
+
+=item bold
+
+=item h1
+
+=item h2
+
+=item h3
+
+=item date
+
+=back
+
+Inputs: $workbook
+
+Returns: $format, a hash reference.
+
+=cut
+
+###############################################################
+###############################################################
+sub define_excel_formats {
+    my ($workbook) = @_;
+    my $format;
+    $format->{'header'} = $workbook->add_format(bold      => 1, 
+                                                bottom    => 1,
+                                                align     => 'center');
+    $format->{'bold'} = $workbook->add_format(bold=>1);
+    $format->{'h1'}   = $workbook->add_format(bold=>1, size=>18);
+    $format->{'h2'}   = $workbook->add_format(bold=>1, size=>16);
+    $format->{'h3'}   = $workbook->add_format(bold=>1, size=>14);
+    $format->{'date'} = $workbook->add_format(num_format=>
+                                            'mmm d yyyy hh:mm AM/PM');
+    return $format;
+}
+
+###############################################################
+###############################################################
+
 =pod
 
 =item * change_content_javascript():
@@ -718,11 +908,46 @@ sub get_domains {
     my @domains;
     my %seen;
     foreach (sort values(%Apache::lonnet::hostdom)) {
-        push (@domains,$_) unless $seen{$_}++;
+	push (@domains,$_) unless $seen{$_}++;
     }
     return @domains;
 }
 
+# ------------------------------------------
+
+sub domain_select {
+    my ($name,$value,$multiple)=@_;
+    my %domains=map { 
+	$_ => $_.' '.$Apache::lonnet::domaindescription{$_} 
+    } &get_domains;
+    if ($multiple) {
+	$domains{''}=&mt('Any domain');
+	return &multiple_select_form($name,$value,4,%domains);
+    } else {
+	return &select_form($name,$value,%domains);
+    }
+}
+
+sub multiple_select_form {
+    my ($name,$value,$size,%hash)=@_;
+    my %selected = map { $_ => 1 } ref($value)?@{$value}:($value);
+    my $output='';
+    if (! defined($size)) {
+        $size = 4;
+        if (scalar(keys(%hash))<4) {
+            $size = scalar(keys(%hash));
+        }
+    }
+    $output.="\n<select name='$name' size='$size' multiple='1'>";
+    foreach (sort(keys(%hash))) {
+        $output.='<option value="'.$_.'" ';
+        $output.='selected ' if ($selected{$_});
+        $output.='>'.$hash{$_}."</option>\n";
+    }
+    $output.="</select>\n";
+    return $output;
+}
+
 #-------------------------------------------
 
 =pod
@@ -754,6 +979,42 @@ sub select_form {
     return $selectform;
 }
 
+sub gradeleveldescription {
+    my $gradelevel=shift;
+    my %gradelevels=(0 => 'Not specified',
+		     1 => 'Grade 1',
+		     2 => 'Grade 2',
+		     3 => 'Grade 3',
+		     4 => 'Grade 4',
+		     5 => 'Grade 5',
+		     6 => 'Grade 6',
+		     7 => 'Grade 7',
+		     8 => 'Grade 8',
+		     9 => 'Grade 9',
+		     10 => 'Grade 10',
+		     11 => 'Grade 11',
+		     12 => 'Grade 12',
+		     13 => 'Grade 13',
+		     14 => '100 Level',
+		     15 => '200 Level',
+		     16 => '300 Level',
+		     17 => '400 Level',
+		     18 => 'Graduate Level');
+    return &mt($gradelevels{$gradelevel});
+}
+
+sub select_level_form {
+    my ($deflevel,$name)=@_;
+    unless ($deflevel) { $deflevel=0; }
+    my $selectform = "<select name=\"$name\" size=\"1\">\n";
+    for (my $i=0; $i<=18; $i++) {
+        $selectform.="<option value=\"$i\" ".
+            ($i==$deflevel ? 'selected' : '').
+                ">".&gradeleveldescription($i)."</option>\n";
+    }
+    $selectform.="</select>";
+    return $selectform;
+}
 
 #-------------------------------------------
 
@@ -979,10 +1240,30 @@ END
         $Javascript_toUpperCase = "";
     }
 
+    my $radioval = "'nochange'";
+    if (exists($in{'curr_authtype'}) &&
+        defined($in{'curr_authtype'}) &&
+        $in{'curr_authtype'} ne '') {
+        $radioval = "'$in{'curr_authtype'}arg'";
+    }
+    my $argfield = 'null';
+    if ( grep/^mode$/,(keys %in) ) {
+        if ($in{'mode'} eq 'modifycourse')  {
+            if ( grep/^curr_authtype$/,(keys %in) ) {
+                $radioval = "'$in{'curr_authtype'}'";
+            }
+            if ( grep/^curr_autharg$/,(keys %in) ) {
+                unless ($in{'curr_autharg'} eq '') {
+                    $argfield = "'$in{'curr_autharg'}'";
+                }
+            }
+        }
+    }
+
     $result.=<<"END";
 var current = new Object();
-current.radiovalue = 'nochange';
-current.argfield = null;
+current.radiovalue = $radioval;
+current.argfield = $argfield;
 
 function changed_radio(choice,currentform) {
     var choicearg = choice + 'arg';
@@ -1069,20 +1350,32 @@ sub authform_kerberos{
               kerb_def_auth => 'krb4',
               @_,
               );
-    my ($check4,$check5);
+    my ($check4,$check5,$krbarg);
     if ($in{'kerb_def_auth'} eq 'krb5') {
        $check5 = " checked=\"on\"";
     } else {
        $check4 = " checked=\"on\"";
     }
+    $krbarg = $in{'kerb_def_dom'};
+
+    my $krbcheck = "";
+    if ( grep/^curr_authtype$/,(keys %in) ) {
+        if ($in{'curr_authtype'} =~ m/^krb/) {
+            $krbcheck = " checked=\"on\"";
+            if ( grep/^curr_autharg$/,(keys %in) ) {
+                $krbarg = $in{'curr_autharg'};
+            }
+        }
+    }
+
     my $jscall = "javascript:changed_radio('krb',$in{'formname'});";
     my $result .= &mt
         ('[_1] Kerberos authenticated with domain [_2] '.
          '[_3] Version 4 [_4] Version 5',
          '<input type="radio" name="login" value="krb" '.
-             'onclick="'.$jscall.'" onchange="'.$jscall.'" />',
+             'onclick="'.$jscall.'" onchange="'.$jscall.'"'.$krbcheck.' />',
          '<input type="text" size="10" name="krbarg" '.
-             'value="'.$in{'kerb_def_dom'}.'" '.
+             'value="'.$krbarg.'" '.
              'onchange="'.$jscall.'" />',
          '<input type="radio" name="krbver" value="4" '.$check4.' />',
          '<input type="radio" name="krbver" value="5" '.$check5.' />');
@@ -1095,13 +1388,25 @@ sub authform_internal{
                 kerb_def_dom => 'MSU.EDU',
                 @_,
                 );
+
+    my $intcheck = "";
+    my $intarg = 'value=""';
+    if ( grep/^curr_authtype$/,(keys %args) ) {
+        if ($args{'curr_authtype'} eq 'int') {
+            $intcheck = " checked=\"on\"";
+            if ( grep/^curr_autharg$/,(keys %args) ) {
+                $intarg = "value=\"$args{'curr_autharg'}\"";
+            }
+        }
+    }
+
     my $jscall = "javascript:changed_radio('int',$args{'formname'});";
     my $result.=&mt
         ('[_1] Internally authenticated (with initial password [_2])',
-         '<input type="radio" name="login" value="int" '.
-             'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
-         '<input type="text" size="10" name="intarg" value="" '.
-             'onchange="'.$jscall.'" />');
+         '<input type="radio" name="login" value="int" '.$intcheck.
+             ' onchange="'.$jscall.'" onclick="'.$jscall.'" />',
+         '<input type="text" size="10" name="intarg" '.$intarg.
+             ' onchange="'.$jscall.'" />');
     return $result;
 }
 
@@ -1111,12 +1416,24 @@ sub authform_local{
               kerb_def_dom => 'MSU.EDU',
               @_,
               );
+
+    my $loccheck = "";
+    my $locarg = 'value=""';
+    if ( grep/^curr_authtype$/,(keys %in) ) {
+        if ($in{'curr_authtype'} eq 'loc') {
+            $loccheck = " checked=\"on\"";
+            if ( grep/^curr_autharg$/,(keys %in) ) {
+                $locarg = "value=\"$in{'curr_autharg'}\"";
+            }
+        }
+    }
+
     my $jscall = "javascript:changed_radio('loc',$in{'formname'});";
-    my $result.=&mt('[_1] Local Authentication with arguement [_2]',
-                    '<input type="radio" name="login" value="loc" '.
-                        'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
-                    '<input type="text" size="10" name="locarg" value="" '.
-                        'onchange="'.$jscall.'" />');
+    my $result.=&mt('[_1] Local Authentication with argument [_2]',
+                    '<input type="radio" name="login" value="loc" '.$loccheck.
+                        ' onchange="'.$jscall.'" onclick="'.$jscall.'" />',
+                    '<input type="text" size="10" name="locarg" '.$locarg.
+                        ' onchange="'.$jscall.'" />');
     return $result;
 }
 
@@ -1290,7 +1607,7 @@ sub keyword {
 
 =item * get_related_words
 
-Look up a word in the thesaurus.  Takes a scalar arguement and returns
+Look up a word in the thesaurus.  Takes a scalar argument and returns
 an array of words.  If the keyword is not in the thesaurus, an empty array
 will be returned.  The order of the words returned is determined by the
 database which holds them.
@@ -1355,6 +1672,7 @@ sub plainname {
 	$names{'lastname'}.' '.$names{'generation'};
     $name=~s/\s+$//;
     $name=~s/\s+/ /g;
+    if ($name !~ /\S/) { $name=$uname.'@'.$udom; }
     return $name;
 }
 
@@ -1426,8 +1744,9 @@ sub noteswrapper {
 # ------------------------------------------------------------- Aboutme Wrapper
 
 sub aboutmewrapper {
-    my ($link,$username,$domain)=@_;
-    return "<a href='/adm/$domain/$username/aboutme'>$link</a>";
+    my ($link,$username,$domain,$target)=@_;
+    return "<a href='/adm/$domain/$username/aboutme'".
+	($target?" target='$target'":'').">$link</a>";
 }
 
 # ------------------------------------------------------------ Syllabus Wrapper
@@ -1505,7 +1824,28 @@ returns description of a specified copyr
 =cut
 
 sub copyrightdescription {
-    return $cprtag{shift(@_)};
+    return &mt($cprtag{shift(@_)});
+}
+=item * source_copyrightids() 
+
+returns list of all source copyrights
+
+=cut
+
+sub source_copyrightids {
+    return sort(keys(%scprtag));
+}
+
+=pod
+
+=item * source_copyrightdescription() 
+
+returns description of a specified source copyright id
+
+=cut
+
+sub source_copyrightdescription {
+    return &mt($scprtag{shift(@_)});
 }
 
 =pod
@@ -1545,6 +1885,14 @@ sub fileembstyle {
     return $fe{lc(shift(@_))};
 }
 
+
+sub filecategoryselect {
+    my ($name,$value)=@_;
+    return &select_form($value,$name,
+			'' => &mt('Any category'),
+			map { $_,$_ } sort(keys(%category_extensions)));
+}
+
 =pod
 
 =item * filedescription() 
@@ -1554,7 +1902,9 @@ returns description for a specified file
 =cut
 
 sub filedescription {
-    return $fd{lc(shift(@_))};
+    my $file_description = $fd{lc(shift())};
+    $file_description =~ s:([\[\]]):~$1:g;
+    return &mt($file_description);
 }
 
 =pod
@@ -1568,7 +1918,9 @@ extra formatting
 
 sub filedescriptionex {
     my $ex=shift;
-    return '.'.$ex.' '.$fd{lc($ex)};
+    my $file_description = $fd{lc($ex)};
+    $file_description =~ s:([\[\]]):~$1:g;
+    return '.'.$ex.' '.&mt($file_description);
 }
 
 # End of .tab access
@@ -1603,13 +1955,13 @@ sub display_languages {
 
 sub preferred_languages {
     my @languages=();
-    if ($ENV{'environment.languages'}) {
-	@languages=split(/\s*(\,|\;|\:)\s*/,$ENV{'environment.languages'});
-    }
     if ($ENV{'course.'.$ENV{'request.course.id'}.'.languages'}) {
 	@languages=(@languages,split(/\s*(\,|\;|\:)\s*/,
 	         $ENV{'course.'.$ENV{'request.course.id'}.'.languages'}));
     }
+    if ($ENV{'environment.languages'}) {
+	@languages=split(/\s*(\,|\;|\:)\s*/,$ENV{'environment.languages'});
+    }
     my $browser=(split(/\;/,$ENV{'HTTP_ACCEPT_LANGUAGE'}))[0];
     if ($browser) {
 	@languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$browser));
@@ -1789,22 +2141,19 @@ show a snapshot of what student was look
 =cut
 
 sub get_student_view {
-  my ($symb,$username,$domain,$courseid,$target) = @_;
+  my ($symb,$username,$domain,$courseid,$target,$moreenv) = @_;
   my ($map,$id,$feedurl) = &Apache::lonnet::decode_symb($symb);
-  my (%old,%moreenv);
+  my (%form);
   my @elements=('symb','courseid','domain','username');
   foreach my $element (@elements) {
-    $old{$element}=$ENV{'form.grade_'.$element};
-    $moreenv{'form.grade_'.$element}=eval '$'.$element #'
+      $form{'grade_'.$element}=eval '$'.$element #'
   }
-  if ($target eq 'tex') {$moreenv{'form.grade_target'} = 'tex';}
-  &Apache::lonnet::appenv(%moreenv);
-  $feedurl=&Apache::lonnet::clutter($feedurl);
-  my $userview=&Apache::lonnet::ssi_body($feedurl);
-  &Apache::lonnet::delenv('form.grade_');
-  foreach my $element (@elements) {
-    $ENV{'form.grade_'.$element}=$old{$element};
+  if (defined($moreenv)) {
+      %form=(%form,%{$moreenv});
   }
+  if ($target eq 'tex') {$form{'grade_target'} = 'tex';}
+  $feedurl=&Apache::lonnet::clutter($feedurl);
+  my $userview=&Apache::lonnet::ssi_body($feedurl,%form);
   $userview=~s/\<body[^\>]*\>//gi;
   $userview=~s/\<\/body\>//gi;
   $userview=~s/\<html\>//gi;
@@ -1827,19 +2176,14 @@ show a snapshot of how student was answe
 sub get_student_answers {
   my ($symb,$username,$domain,$courseid,%form) = @_;
   my ($map,$id,$feedurl) = &Apache::lonnet::decode_symb($symb);
-  my (%old,%moreenv);
+  my (%moreenv);
   my @elements=('symb','courseid','domain','username');
   foreach my $element (@elements) {
-    $old{$element}=$ENV{'form.grade_'.$element};
-    $moreenv{'form.grade_'.$element}=eval '$'.$element #'
-  }
-  $moreenv{'form.grade_target'}='answer';
-  &Apache::lonnet::appenv(%moreenv);
-  my $userview=&Apache::lonnet::ssi('/res/'.$feedurl,%form);
-  &Apache::lonnet::delenv('form.grade_');
-  foreach my $element (@elements) {
-    $ENV{'form.grade_'.$element}=$old{$element};
+    $moreenv{'grade_'.$element}=eval '$'.$element #'
   }
+  $moreenv{'grade_target'}='answer';
+  %moreenv=(%form,%moreenv);
+  my $userview=&Apache::lonnet::ssi('/res/'.$feedurl,%moreenv);
   return $userview;
 }
 
@@ -1896,21 +2240,6 @@ sub maketime {
          $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,$th{'dlsav'}));
 }
 
-
-#########################################
-#
-# Retro-fixing of un-backward-compatible time format
-
-sub unsqltime {
-    my $timestamp=shift;
-    if ($timestamp=~/^(\d+)\-(\d+)\-(\d+)\s+(\d+)\:(\d+)\:(\d+)$/) {
-       $timestamp=&maketime(
-	   'year'=>$1,'month'=>$2,'day'=>$3,
-           'hours'=>$4,'minutes'=>$5,'seconds'=>$6);
-    }
-    return $timestamp;
-}
-
 #########################################
 
 sub findallcourses {
@@ -2070,19 +2399,7 @@ other decorations will be returned.
 sub bodytag {
     my ($title,$function,$addentries,$bodyonly,$domain,$forcereg)=@_;
     $title=&mt($title);
-    unless ($function) {
-	$function='student';
-        if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {
-	    $function='coordinator';
-        }
-	if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {
-            $function='admin';
-        }
-        if (($ENV{'request.role'}=~/^(au|ca)/) ||
-            ($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
-            $function='author';
-        }
-    }
+    $function = &get_users_function() if (!$function);
     my $img=&designparm($function.'.img',$domain);
     my $pgbg=&designparm($function.'.pgbg',$domain);
     my $tabbg=&designparm($function.'.tabbg',$domain);
@@ -2170,6 +2487,33 @@ ENDBODY
 
 ###############################################
 
+=pod
+
+=item get_users_function
+
+Used by &bodytag to determine the current users primary role.
+Returns either 'student','coordinator','admin', or 'author'.
+
+=cut
+
+###############################################
+sub get_users_function {
+    my $function = 'student';
+    if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {
+        $function='coordinator';
+    }
+    if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {
+        $function='admin';
+    }
+    if (($ENV{'request.role'}=~/^(au|ca)/) ||
+        ($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
+        $function='author';
+    }
+    return $function;
+}
+
+###############################################
+
 sub get_posted_cgi {
     my $r=shift;
 
@@ -2304,11 +2648,16 @@ sub no_cache {
 }
 
 sub content_type {
-  my ($r,$type,$charset) = @_;
-  unless ($charset) {
-      $charset=&Apache::lonlocal::current_encoding;
-  }
-  $r->content_type($type.($charset?'; charset='.$charset:''));
+    my ($r,$type,$charset) = @_;
+    unless ($charset) {
+	$charset=&Apache::lonlocal::current_encoding;
+    }
+    if ($charset) { $type.='; charset='.$charset; }
+    if ($r) {
+	$r->content_type($type);
+    } else {
+	print("Content-type: $type\n\n");
+    }
 }
 
 =pod
@@ -2390,9 +2739,12 @@ sub upfile_store {
     my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.
 	'_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;
     {
-	my $fh=Apache::File->new('>'.$r->dir_config('lonDaemons').
-				 '/tmp/'.$datatoken.'.tmp');
-	print $fh $ENV{'form.upfile'};
+        my $datafile = $r->dir_config('lonDaemons').
+                           '/tmp/'.$datatoken.'.tmp';
+        if ( open(my $fh,">$datafile") ) {
+            print $fh $ENV{'form.upfile'};
+            close($fh);
+        }
     }
     return $datatoken;
 }
@@ -2411,11 +2763,12 @@ sub load_tmp_file {
     my $r=shift;
     my @studentdata=();
     {
-	my $fh;
-	if ($fh=Apache::File->new($r->dir_config('lonDaemons').
-				  '/tmp/'.$ENV{'form.datatoken'}.'.tmp')) {
-	    @studentdata=<$fh>;
-	}
+        my $studentfile = $r->dir_config('lonDaemons').
+                              '/tmp/'.$ENV{'form.datatoken'}.'.tmp';
+        if ( open(my $fh,"<$studentfile") ) {
+            @studentdata=<$fh>;
+            close($fh);
+        }
     }
     $ENV{'form.upfile'}=join('',@studentdata);
 }
@@ -2460,7 +2813,7 @@ sub record_sep {
         }
     } elsif ($ENV{'form.upfiletype'} eq 'tab') {
         my $i=0;
-        foreach (split(/\t+/,$record)) {
+        foreach (split(/\t/,$record)) {
             my $field=$_;
             $field=~s/^(\"|\')//;
             $field=~s/(\"|\')$//;
@@ -2568,7 +2921,7 @@ Prints a table to create associations be
 
 $r is an Apache Request ref,
 $records is an arrayref from &Apache::loncommon::upfile_record_sep,
-$d is an array of 2 element arrays (internal name, displayed name)
+$d is an array of 2 element arrays (internal name, displayed name,defaultcol)
 
 =cut
 
@@ -2583,14 +2936,16 @@ sub csv_print_select_table {
               '<th>'.&mt('Attribute').'</th>'.
               '<th>'.&mt('Column').'</th></tr>'."\n");
     foreach (@$d) {
-	my ($value,$display)=@{ $_ };
+	my ($value,$display,$defaultcol)=@{ $_ };
 	$r->print('<tr><td>'.$display.'</td>');
 
 	$r->print('<td><select name=f'.$i.
 		  ' onchange="javascript:flip(this.form,'.$i.');">');
 	$r->print('<option value="none"></option>');
 	foreach (sort({$a <=> $b} keys(%sone))) {
-	    $r->print('<option value="'.$_.'">Column '.($_+1).'</option>');
+	    $r->print('<option value="'.$_.'"'.
+                      ($_ eq $defaultcol ? ' selected ' : '').
+                      '>Column '.($_+1).'</option>');
 	}
 	$r->print('</select></td></tr>'."\n");
 	$i++;
@@ -2631,8 +2986,10 @@ sub csv_samples_select_table {
 	$r->print('<tr><td><select name="f'.$i.'"'.
 		  ' onchange="javascript:flip(this.form,'.$i.');">');
 	foreach (@$d) {
-	    my ($value,$display)=@{ $_ };
-	    $r->print('<option value="'.$value.'">'.$display.'</option>');
+	    my ($value,$display,$defaultcol)=@{ $_ };
+	    $r->print('<option value="'.$value.'"'.
+                      ($i eq $defaultcol ? ' selected ':'').'>'.
+                      $display.'</option>');
 	}
 	$r->print('</select></td><td>');
 	if (defined($sone{$_})) { $r->print($sone{$_}."</br>\n"); }
@@ -2757,6 +3114,8 @@ If $Max is < any data point, the graph w
 =item $colors: array ref holding the colors to be used for the data sets when
 they are plotted.  If undefined, default values will be used.
 
+=item $labels: array ref holding the labels to use on the x-axis for the bars.
+
 =item @Values: An array of array references.  Each array reference holds data
 to be plotted in a stacked bar chart.
 
@@ -2772,7 +3131,7 @@ information for the plot.
 ############################################################
 ############################################################
 sub DrawBarGraph {
-    my ($Title,$xlabel,$ylabel,$Max,$colors,@Values)=@_;
+    my ($Title,$xlabel,$ylabel,$Max,$colors,$labels,@Values)=@_;
     #
     if (! defined($colors)) {
         $colors = ['#33ff00', 
@@ -2815,8 +3174,12 @@ sub DrawBarGraph {
     }
     #
     my @Labels;
-    for (my $i=0;$i<@{$Values[0]};$i++) {
-        push (@Labels,$i+1);
+    if (defined($labels)) {
+        @Labels = @$labels;
+    } else {
+        for (my $i=0;$i<@{$Values[0]};$i++) {
+            push (@Labels,$i+1);
+        }
     }
     #
     $Max = 1 if ($Max < 1);
@@ -2875,7 +3238,7 @@ plotted in.  If undefined, default value
 =item $Xlabels: Array ref containing the labels to be used for the X-axis.
 
 =item $Ydata: Array ref containing Array refs.  
-Each of the contained arrays will be plotted as a seperate curve.
+Each of the contained arrays will be plotted as a separate curve.
 
 =item %Values: hash indicating or overriding any default values which are 
 passed to graph.png.  
@@ -3123,7 +3486,7 @@ sub store_course_settings {
     my %SaveHash;
     my %AppHash;
     while (my ($setting,$type) = each(%$Settings)) {
-        my $basename = 'env.internal.'.$prefix.'.'.$setting;
+        my $basename = 'internal.'.$prefix.'.'.$setting;
         my $envname = 'course.'.$courseid.'.'.$basename;
         if (exists($ENV{'form.'.$setting})) {
             # Save this value away
@@ -3168,7 +3531,7 @@ sub restore_course_settings {
     my ($prefix,$Settings) = @_;
     while (my ($setting,$type) = each(%$Settings)) {
         next if (exists($ENV{'form.'.$setting}));
-        my $envname = 'course.'.$courseid.'.env.internal.'.$prefix.
+        my $envname = 'course.'.$courseid.'.internal.'.$prefix.
             '.'.$setting;
         if (exists($ENV{$envname})) {
             if ($type eq 'scalar') {
@@ -3199,14 +3562,18 @@ sub propath {
 
 sub icon {
     my ($file)=@_;
-    my @file_ext = split(/\./,$file);
-    my $curfext = $file_ext[-1];
-    my $iconname="unknown.gif";
+    my $curfext = (split(/\./,$file))[-1];
+    my $iconname=$Apache::lonnet::perlvar{'lonIconsURL'}.'/unknown.gif';
     my $embstyle = &Apache::loncommon::fileembstyle($curfext);
-    # The unless conditional that follows is a bit of overkill
-    $iconname = $curfext.".gif" unless
-	(!defined($embstyle) || $embstyle eq 'unk' || $embstyle eq 'hdn');
-    return $Apache::lonnet::perlvar{'lonIconsURL'}."/$iconname";
+    if (!(!defined($embstyle) || $embstyle eq 'unk' || $embstyle eq 'hdn')) {
+	if (-e  $Apache::lonnet::perlvar{'lonDocRoot'}.'/'.
+	          $Apache::lonnet::perlvar{'lonIconsURL'}.'/'.
+	            $curfext.".gif") {
+	    $iconname=$Apache::lonnet::perlvar{'lonIconsURL'}.'/'.
+		$curfext.".gif";
+	}
+    }
+    return $iconname;
 } 
 
 =pod