--- loncom/interface/loncommon.pm 2003/11/08 01:45:26 1.145 +++ loncom/interface/loncommon.pm 2004/01/02 19:23:47 1.169 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.145 2003/11/08 01:45:26 www Exp $ +# $Id: loncommon.pm,v 1.169 2004/01/02 19:23:47 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,13 +25,6 @@ # # http://www.lon-capa.org/ # -# YEAR=2001 -# 2/13-12/7 Guy Albertelli -# 12/21 Gerd Kortemeyer -# 12/25,12/28 Gerd Kortemeyer -# YEAR=2002 -# 1/4 Gerd Kortemeyer -# 6/24,7/2 H. K. Ng # Makes a table out of the previous attempts # Inputs result_from_symbread, user, domain, course_id @@ -73,11 +66,9 @@ use HTML::Entities; my $readit; -=pod - -=head1 Global Variables - -=cut +## +## Global Variables +## # ----------------------------------------------- Filetypes/Languages/Copyright my %language; @@ -111,32 +102,34 @@ 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); + } } # -------------------------------------------------------------- domain designs @@ -147,15 +140,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); + } } } @@ -164,32 +158,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( "INFO: Read file types"); @@ -204,10 +201,6 @@ BEGIN { =pod -=head1 General Subroutines - -=over 4 - =head1 HTML and Javascript Functions =over 4 @@ -219,8 +212,6 @@ containing javascript with two functions C. Returned string does not contain EscriptE tags. -=over 4 - =item * openbrowser(formname,elementname,only,omit) [javascript] inputs: formname, elementname, only, omit @@ -241,8 +232,6 @@ Inputs: formname, elementname formname and elementname specify the name of the html form and the name of the element the selection from the search results will be placed in. -=back - =cut sub browser_and_searcher_javascript { @@ -565,6 +554,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'))"; @@ -735,11 +726,40 @@ 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,%domains); + } else { + return &select_form($name,$value,%domains); + } +} + +sub multiple_select_form { + my ($name,$value,%hash)=@_; + my %selected = map { $_ => 1 } ref($value)?@{$value}:($value); + my $output=''; + my $size =(scalar keys %hash<4?scalar keys %hash:4); + $output.="\n\n"; + return $output; +} + #------------------------------------------- =pod @@ -771,6 +791,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 = ""; + return $selectform; +} #------------------------------------------- @@ -887,6 +943,8 @@ Outputs: =back +=back + =cut ############################################################### @@ -925,12 +983,6 @@ sub decode_user_agent { $clientunicode,$clientos,); } -=pod - -=back - -=cut - ############################################################### ## Authentication changing form generation subroutines ## ############################################################### @@ -971,6 +1023,8 @@ See loncreateuser.pm for invocation and =back +=back + =cut #------------------------------------------- @@ -998,10 +1052,25 @@ END $Javascript_toUpperCase = ""; } + my $radioval = "'nochange'"; + 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'; @@ -1088,20 +1157,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', '', + 'onclick="'.$jscall.'" onchange="'.$jscall.'"'.$krbcheck.' />', '', '', ''); @@ -1114,13 +1195,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])', - '', - ''); + '', + ''); return $result; } @@ -1130,12 +1223,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]', - '', - ''); + my $result.=&mt('[_1] Local Authentication with argument [_2]', + '', + ''); return $result; } @@ -1155,12 +1260,6 @@ sub authform_filesystem{ return $result; } -=pod - -=back - -=cut - ############################################################### ## Get Authentication Defaults for Domain ## ############################################################### @@ -1315,7 +1414,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. @@ -1451,8 +1550,9 @@ sub noteswrapper { # ------------------------------------------------------------- Aboutme Wrapper sub aboutmewrapper { - my ($link,$username,$domain)=@_; - return "$link"; + my ($link,$username,$domain,$target)=@_; + return "$link"; } # ------------------------------------------------------------ Syllabus Wrapper @@ -1530,7 +1630,7 @@ returns description of a specified copyr =cut sub copyrightdescription { - return $cprtag{shift(@_)}; + return &mt($cprtag{shift(@_)}); } =pod @@ -1570,6 +1670,14 @@ sub fileembstyle { return $fe{lc(shift(@_))}; } + +sub filecategoryselect { + my ($name,$value)=@_; + return &select_form($name,$value, + '' => &mt('Any category'), + map { $_,$_ } sort(keys(%category_extensions))); +} + =pod =item * filedescription() @@ -1579,7 +1687,7 @@ returns description for a specified file =cut sub filedescription { - return $fd{lc(shift(@_))}; + return &mt($fd{lc(shift(@_))}); } =pod @@ -1593,7 +1701,7 @@ extra formatting sub filedescriptionex { my $ex=shift; - return '.'.$ex.' '.$fd{lc($ex)}; + return '.'.$ex.' '.&mt($fd{lc($ex)}); } # End of .tab access @@ -1921,21 +2029,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 { @@ -2007,7 +2100,7 @@ sub domainlogo { my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'}; if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; } return ''; + '/adm/lonDomLogos/'.$domain.'.gif" alt="'.$domain.'" />'; } elsif(exists($Apache::lonnet::domaindescription{$domain})) { return $Apache::lonnet::domaindescription{$domain}; } else { @@ -2118,8 +2211,9 @@ sub bodytag { my $sidebg=&designparm($function.'.sidebg',$domain); # Accessibility font enhance unless ($addentries) { $addentries=''; } + my $addstyle=''; if ($ENV{'browser.fontenhance'} eq 'on') { - $addentries.=' style="font-size: x-large"'; + $addstyle=' font-size: x-large;'; } # role and realm my ($role,$realm) @@ -2137,11 +2231,15 @@ sub bodytag { if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; } # construct main body tag my $bodytag = < +h1, h2, h3, th { font-family: Arial, Helvetica, sans-serif } +a:focus { color: red; background: yellow } + +style="margin-top: 0px;$addstyle" $addentries> END my $upperleft=''; + $lonhttpdPort.$img.'" alt="'.$function.'" />'; if ($bodyonly) { return $bodytag; } elsif ($ENV{'browser.interface'} eq 'textual') { @@ -2153,7 +2251,7 @@ END # No Remote return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web', $forcereg). - ' - +
'.$title. + '
'.$title. '
'; } @@ -2169,9 +2267,9 @@ $upperleft
$title - -$title + + $ENV{'environment.firstname'} $ENV{'environment.middlename'} $ENV{'environment.lastname'} @@ -2180,10 +2278,10 @@ $upperleft
-$role  +$role 
$realm 
$realm 

ENDBODY } @@ -2360,6 +2458,32 @@ sub add_to_env { =pod +=item * get_env_multiple($name) + +gets $name from the %ENV hash, it seemlessly handles the cases where multiple +values may be defined and end up as an array ref. + +returns an array of values + +=cut + +sub get_env_multiple { + my ($name) = @_; + my @values; + if (defined($ENV{$name})) { + # exists is it an array + if (ref($ENV{$name})) { + @values=@{ $ENV{$name} }; + } else { + $values[0]=$ENV{$name}; + } + } + return(@values); +} + + +=pod + =back =head1 CSV Upload/Handling functions @@ -2384,9 +2508,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; } @@ -2405,11 +2532,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); } @@ -2698,8 +2826,12 @@ sub check_if_partid_hidden { =pod +=back + =head1 cgi-bin script and graphing routines +=over 4 + =item get_cgi_id Inputs: none @@ -2713,9 +2845,10 @@ the routine &Apache::lonnet::transfer_pr ############################################################ ############################################################ - +my $uniq=0; sub get_cgi_id { - return (time.'_'.int(rand(1000))); + $uniq=($uniq+1)%100000; + return (time.'_'.$uniq); } ############################################################ @@ -3031,10 +3164,14 @@ sub DrawXYYGraph { =pod +=back + =head1 Statistics helper routines? Bad place for them but what the hell. +=over 4 + =item &chartlink Returns a link to the chart for a specific student. @@ -3051,6 +3188,8 @@ Inputs: =back +=back + =cut ############################################################ @@ -3063,9 +3202,139 @@ sub chartlink { '">'.$linktext.''; } +####################################################### +####################################################### + +=pod + +=head1 Course Environment Routines + +=over 4 + +=item &restore_course_settings + +=item &store_course_settings + +Restores/Store indicated form parameters from the course environment. +Will not overwrite existing values of the form parameters. + +Inputs: +a scalar describing the data (e.g. 'chart', 'problem_analysis') + +a hash ref describing the data to be stored. For example: + +%Save_Parameters = ('Status' => 'scalar', + 'chartoutputmode' => 'scalar', + 'chartoutputdata' => 'scalar', + 'Section' => 'array', + 'StudentData' => 'array', + 'Maps' => 'array'); + +Returns: both routines return nothing + +=cut + +####################################################### +####################################################### +sub store_course_settings { + # save to the environment + # appenv the same items, just to be safe + my $courseid = $ENV{'request.course.id'}; + my $coursedom = $ENV{'course.'.$courseid.'.domain'}; + my ($prefix,$Settings) = @_; + my %SaveHash; + my %AppHash; + while (my ($setting,$type) = each(%$Settings)) { + my $basename = 'env.internal.'.$prefix.'.'.$setting; + my $envname = 'course.'.$courseid.'.'.$basename; + if (exists($ENV{'form.'.$setting})) { + # Save this value away + if ($type eq 'scalar' && + (! exists($ENV{$envname}) || + $ENV{$envname} ne $ENV{'form.'.$setting})) { + $SaveHash{$basename} = $ENV{'form.'.$setting}; + $AppHash{$envname} = $ENV{'form.'.$setting}; + } elsif ($type eq 'array') { + my $stored_form; + if (ref($ENV{'form.'.$setting})) { + $stored_form = join(',', + map { + &Apache::lonnet::escape($_); + } sort(@{$ENV{'form.'.$setting}})); + } else { + $stored_form = + &Apache::lonnet::escape($ENV{'form.'.$setting}); + } + # Determine if the array contents are the same. + if ($stored_form ne $ENV{$envname}) { + $SaveHash{$basename} = $stored_form; + $AppHash{$envname} = $stored_form; + } + } + } + } + my $put_result = &Apache::lonnet::put('environment',\%SaveHash, + $coursedom, + $ENV{'course.'.$courseid.'.num'}); + if ($put_result !~ /^(ok|delayed)/) { + &Apache::lonnet::logthis('unable to save form parameters, '. + 'got error:'.$put_result); + } + # Make sure these settings stick around in this session, too + &Apache::lonnet::appenv(%AppHash); + return; +} + +sub restore_course_settings { + my $courseid = $ENV{'request.course.id'}; + my ($prefix,$Settings) = @_; + while (my ($setting,$type) = each(%$Settings)) { + next if (exists($ENV{'form.'.$setting})); + my $envname = 'course.'.$courseid.'.env.internal.'.$prefix. + '.'.$setting; + if (exists($ENV{$envname})) { + if ($type eq 'scalar') { + $ENV{'form.'.$setting} = $ENV{$envname}; + } elsif ($type eq 'array') { + $ENV{'form.'.$setting} = [ + map { + &Apache::lonnet::unescape($_); + } split(',',$ENV{$envname}) + ]; + } + } + } +} + ############################################################ ############################################################ +sub propath { + my ($udom,$uname)=@_; + $udom=~s/\W//g; + $uname=~s/\W//g; + my $subdir=$uname.'__'; + $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/; + my $proname="$Apache::lonnet::perlvar{'lonUsersDir'}/$udom/$subdir/$uname"; + return $proname; +} + +sub icon { + my ($file)=@_; + my $curfext = (split(/\./,$file))[-1]; + my $iconname=$Apache::lonnet::perlvar{'lonIconsURL'}.'/unknown.gif'; + my $embstyle = &Apache::loncommon::fileembstyle($curfext); + 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 =back