Diff for /loncom/interface/loncommon.pm between versions 1.116 and 1.163

version 1.116, 2003/09/11 22:37:54 version 1.163, 2003/12/26 16:27:20
Line 25 Line 25
 #  #
 # http://www.lon-capa.org/  # 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  # Makes a table out of the previous attempts
 # Inputs result_from_symbread, user, domain, course_id  # Inputs result_from_symbread, user, domain, course_id
Line 68  use POSIX qw(strftime mktime); Line 61  use POSIX qw(strftime mktime);
 use Apache::Constants qw(:common :http :methods);  use Apache::Constants qw(:common :http :methods);
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::lonmenu();  use Apache::lonmenu();
 my $readit;  use Apache::lonlocal;
   use HTML::Entities;
 =pod   
   
 =head1 Global Variables  my $readit;
   
 =cut  ##
   ## Global Variables
   ##
   
 # ----------------------------------------------- Filetypes/Languages/Copyright  # ----------------------------------------------- Filetypes/Languages/Copyright
 my %language;  my %language;
   my %supported_language;
 my %cprtag;  my %cprtag;
 my %fe; my %fd;  my %fe; my %fd;
 my %category_extensions;  my %category_extensions;
Line 87  my %category_extensions; Line 82  my %category_extensions;
 my %designhash;  my %designhash;
   
 # ---------------------------------------------- Thesaurus variables  # ---------------------------------------------- Thesaurus variables
   #
 # FIXME: I don't think it's necessary to document these things;  # %Keywords:
 # they're privately used - Jeremy  #      A hash used by &keyword to determine if a word is considered a keyword.
   # $thesaurus_db_file 
 =pod  #      Scalar containing the full path to the thesaurus database.
   
 =over 4  
   
 =item * %Keywords    
   
 A hash used by &keyword to determine if a word is considered a keyword.  
   
 =item * $thesaurus_db_file  
   
 Scalar containing the full path to the thesaurus database.                   
   
 =back  
   
 =cut  
   
 my %Keywords;  my %Keywords;
 my $thesaurus_db_file;  my $thesaurus_db_file;
   
 # ----------------------------------------------------------------------- BEGIN  #
   # Initialize values from language.tab, copyright.tab, filetypes.tab,
 # FIXME: I don't think this needs to be documented, it prepares  # thesaurus.tab, and filecategories.tab.
 # private data structures - Jeremy  #
 =pod  
   
 =head1 General Subroutines  
   
 =over 4  
   
 =item * BEGIN()   
   
 Initialize values from language.tab, copyright.tab, filetypes.tab,  
 thesaurus.tab, and filecategories.tab.  
   
 =back  
   
 =cut  
   
 # ----------------------------------------------------------------------- BEGIN  
   
 BEGIN {  BEGIN {
     # Variable initialization      # Variable initialization
     $thesaurus_db_file = $Apache::lonnet::perlvar{'lonTabDir'}."/thesaurus.db";      $thesaurus_db_file = $Apache::lonnet::perlvar{'lonTabDir'}."/thesaurus.db";
Line 138  BEGIN { Line 102  BEGIN {
     unless ($readit) {      unless ($readit) {
 # ------------------------------------------------------------------- languages  # ------------------------------------------------------------------- languages
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.          my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}.
  '/language.tab');                                     '/language.tab';
  if ($fh) {          if ( open(my $fh,"<$langtabfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($key,$two,$country,$three,$enc,$val)=(split(/\t/,$_));                  my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_));
  $language{$key}=$val.' - '.$enc;                  $language{$key}=$val.' - '.$enc;
     }                  if ($sup) {
  }                      $supported_language{$key}=$sup;
                   }
               }
               close($fh);
           }
     }      }
 # ------------------------------------------------------------------ copyrights  # ------------------------------------------------------------------ copyrights
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonIncludes'}.          my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
   '/copyright.tab');                                    '/copyright.tab';
  if ($fh) {          if ( open (my $fh,"<$copyrightfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($key,$val)=(split(/\s+/,$_,2));                  my ($key,$val)=(split(/\s+/,$_,2));
  $cprtag{$key}=$val;                  $cprtag{$key}=$val;
     }              }
  }              close($fh);
           }
     }      }
   
 # -------------------------------------------------------------- domain designs  # -------------------------------------------------------------- domain designs
Line 171  BEGIN { Line 140  BEGIN {
     while ($filename=readdir(DIR)) {      while ($filename=readdir(DIR)) {
  my ($domain)=($filename=~/^(\w+)\./);   my ($domain)=($filename=~/^(\w+)\./);
     {      {
  my $fh=Apache::File->new($designdir.'/'.$filename);          my $designfile = $designdir.'/'.$filename;
  if ($fh) {          if ( open (my $fh,"<$designfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($key,$val)=(split(/\=/,$_));                  my ($key,$val)=(split(/\=/,$_));
  if ($val) { $designhash{$domain.'.'.$key}=$val; }                  if ($val) { $designhash{$domain.'.'.$key}=$val; }
     }              }
  }              close($fh);
           }
     }      }
   
     }      }
Line 188  BEGIN { Line 158  BEGIN {
   
 # ------------------------------------------------------------- file categories  # ------------------------------------------------------------- file categories
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.          my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}.
   '/filecategories.tab');                                    '/filecategories.tab';
  if ($fh) {          if ( open (my $fh,"<$categoryfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($extension,$category)=(split(/\s+/,$_,2));                  my ($extension,$category)=(split(/\s+/,$_,2));
  push @{$category_extensions{lc($category)}},$extension;                  push @{$category_extensions{lc($category)}},$extension;
     }              }
  }              close($fh);
           }
   
     }      }
 # ------------------------------------------------------------------ file types  # ------------------------------------------------------------------ file types
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.          my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}.
        '/filetypes.tab');                 '/filetypes.tab';
  if ($fh) {          if ( open (my $fh,"<$typesfile") ) {
             while (<$fh>) {              while (<$fh>) {
  next if (/^\#/);                  next if (/^\#/);
  chomp;                  chomp;
  my ($ending,$emb,$descr)=split(/\s+/,$_,3);                  my ($ending,$emb,$descr)=split(/\s+/,$_,3);
  if ($descr ne '') {                   if ($descr ne '') {
     $fe{$ending}=lc($emb);                      $fe{$ending}=lc($emb);
     $fd{$ending}=$descr;                      $fd{$ending}=$descr;
  }                  }
     }              }
  }              close($fh);
           }
     }      }
     &Apache::lonnet::logthis(      &Apache::lonnet::logthis(
               "<font color=yellow>INFO: Read file types</font>");                "<font color=yellow>INFO: Read file types</font>");
Line 239  containing javascript with two functions Line 212  containing javascript with two functions
 C<opensearcher>. Returned string does not contain E<lt>scriptE<gt>  C<opensearcher>. Returned string does not contain E<lt>scriptE<gt>
 tags.  tags.
   
 =over 4  
   
 =item * openbrowser(formname,elementname,only,omit) [javascript]  =item * openbrowser(formname,elementname,only,omit) [javascript]
   
 inputs: formname, elementname, only, omit  inputs: formname, elementname, only, omit
Line 261  Inputs: formname, elementname Line 232  Inputs: formname, elementname
 formname and elementname specify the name of the html form and the name  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.  of the element the selection from the search results will be placed in.
   
 =back  
   
 =cut  =cut
   
 sub browser_and_searcher_javascript {  sub browser_and_searcher_javascript {
     return <<END;      return <<END;
     var editbrowser = null;      var editbrowser = null;
     function openbrowser(formname,elementname,only,omit) {      function openbrowser(formname,elementname,only,omit,titleelement) {
         var url = '/res/?';          var url = '/res/?';
         if (editbrowser == null) {          if (editbrowser == null) {
             url += 'launch=1&';              url += 'launch=1&';
Line 282  sub browser_and_searcher_javascript { Line 251  sub browser_and_searcher_javascript {
         if (omit != null) {          if (omit != null) {
             url += 'omit=' + omit + '&';              url += 'omit=' + omit + '&';
         }          }
           if (titleelement != null) {
               url += 'titleelement=' + titleelement + '&';
           }
         url += 'element=' + elementname + '';          url += 'element=' + elementname + '';
         var title = 'Browser';          var title = 'Browser';
         var options = 'scrollbars=1,resizable=1,menubar=0';          var options = 'scrollbars=1,resizable=1,menubar=0';
Line 290  sub browser_and_searcher_javascript { Line 262  sub browser_and_searcher_javascript {
         editbrowser.focus();          editbrowser.focus();
     }      }
     var editsearcher;      var editsearcher;
     function opensearcher(formname,elementname) {      function opensearcher(formname,elementname,titleelement) {
         var url = '/adm/searchcat?';          var url = '/adm/searchcat?';
         if (editsearcher == null) {          if (editsearcher == null) {
             url += 'launch=1&';              url += 'launch=1&';
Line 298  sub browser_and_searcher_javascript { Line 270  sub browser_and_searcher_javascript {
         url += 'catalogmode=interactive&';          url += 'catalogmode=interactive&';
         url += 'mode=edit&';          url += 'mode=edit&';
         url += 'form=' + formname + '&';          url += 'form=' + formname + '&';
           if (titleelement != null) {
               url += 'titleelement=' + titleelement + '&';
           }
         url += 'element=' + elementname + '';          url += 'element=' + elementname + '';
         var title = 'Search';          var title = 'Search';
         var options = 'scrollbars=1,resizable=1,menubar=0';          var options = 'scrollbars=1,resizable=1,menubar=0';
Line 346  sub selectstudent_link { Line 321  sub selectstudent_link {
    return '';     return '';
        }         }
        return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele.         return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele.
         '","'.$udomele.'");'."'>Select User</a>";          '","'.$udomele.'");'."'>".&mt('Select User')."</a>";
    }     }
    if ($ENV{'request.role'}=~/^(au|dc|su)/) {     if ($ENV{'request.role'}=~/^(au|dc|su)/) {
        return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele.         return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele.
         '","'.$udomele.'",1);'."'>Select User</a>";          '","'.$udomele.'",1);'."'>".&mt('Select User')."</a>";
    }     }
    return '';     return '';
 }  }
   
 sub coursebrowser_javascript {  sub coursebrowser_javascript {
    return (<<'ENDSTDBRW');      my ($domainfilter)=@_;
      return (<<ENDSTDBRW);
 <script type="text/javascript" language="Javascript" >  <script type="text/javascript" language="Javascript" >
     var stdeditbrowser;      var stdeditbrowser;
     function opencrsbrowser(formname,uname,udom) {      function opencrsbrowser(formname,uname,udom) {
Line 367  sub coursebrowser_javascript { Line 343  sub coursebrowser_javascript {
                url += 'filter='+filter+'&';                 url += 'filter='+filter+'&';
    }     }
         }          }
           var domainfilter='$domainfilter';
           if (domainfilter != null) {
              if (domainfilter != '') {
                  url += 'domainfilter='+domainfilter+'&';
      }
           }
         url += 'form=' + formname + '&cnumelement='+uname+          url += 'form=' + formname + '&cnumelement='+uname+
                                     '&cdomelement='+udom;                                      '&cdomelement='+udom;
         var title = 'Course_Browser';          var title = 'Course_Browser';
Line 382  ENDSTDBRW Line 364  ENDSTDBRW
 sub selectcourse_link {  sub selectcourse_link {
    my ($form,$unameele,$udomele)=@_;     my ($form,$unameele,$udomele)=@_;
     return "<a href='".'javascript:opencrsbrowser("'.$form.'","'.$unameele.      return "<a href='".'javascript:opencrsbrowser("'.$form.'","'.$unameele.
         '","'.$udomele.'");'."'>Select Course</a>";          '","'.$udomele.'");'."'>".&mt('Select Course')."</a>";
 }  }
   
 =pod  =pod
Line 501  function select1_changed() { Line 483  function select1_changed() {
     // in with the nuclear      // in with the nuclear
     for (i=0;i<values.length; i++) {      for (i=0;i<values.length; i++) {
         $second.options[i] = new Option(values[i]);          $second.options[i] = new Option(values[i]);
           $second.options[i].value = values[i];
         $second.options[i].text = texts[i];          $second.options[i].text = texts[i];
         if (values[i] == select2def) {          if (values[i] == select2def) {
             $second.options[i].selected = true;              $second.options[i].selected = true;
Line 514  END Line 497  END
     foreach my $value (sort(keys(%$hashref))) {      foreach my $value (sort(keys(%$hashref))) {
         $result.="    <option value=\"$value\" ";          $result.="    <option value=\"$value\" ";
         $result.=" selected=\"true\" " if ($value eq $firstdefault);          $result.=" selected=\"true\" " if ($value eq $firstdefault);
         $result.=">$hashref->{$value}->{'text'}</option>\n";          $result.=">".&mt($hashref->{$value}->{'text'})."</option>\n";
     }      }
     $result .= "</select>\n";      $result .= "</select>\n";
     my %select2 = %{$hashref->{$firstdefault}->{'select2'}};      my %select2 = %{$hashref->{$firstdefault}->{'select2'}};
Line 524  END Line 507  END
     foreach my $value (sort(keys(%select2))) {      foreach my $value (sort(keys(%select2))) {
         $result.="    <option value=\"$value\" ";                  $result.="    <option value=\"$value\" ";        
         $result.=" selected=\"true\" " if ($value eq $seconddefault);          $result.=" selected=\"true\" " if ($value eq $seconddefault);
         $result.=">$select2{$value}</option>\n";          $result.=">".&mt($select2{$value})."</option>\n";
     }      }
     $result .= "</select>\n";      $result .= "</select>\n";
     #    return $debug;      #    return $debug;
Line 571  sub help_open_topic { Line 554  sub help_open_topic {
     my $template = "";      my $template = "";
     my $link;      my $link;
   
       $topic=~s/\W/\_/g;
   
     if (!$stayOnPage)      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'))";   $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
Line 762  See lonrights.pm for an example invocati Line 747  See lonrights.pm for an example invocati
 sub select_form {  sub select_form {
     my ($def,$name,%hash) = @_;      my ($def,$name,%hash) = @_;
     my $selectform = "<select name=\"$name\" size=\"1\">\n";      my $selectform = "<select name=\"$name\" size=\"1\">\n";
     foreach (sort keys %hash) {      my @keys;
       if (exists($hash{'select_form_order'})) {
    @keys=@{$hash{'select_form_order'}};
       } else {
    @keys=sort(keys(%hash));
       }
       foreach (@keys) {
         $selectform.="<option value=\"$_\" ".          $selectform.="<option value=\"$_\" ".
             ($_ eq $def ? 'selected' : '').              ($_ eq $def ? 'selected' : '').
                 ">".$hash{$_}."</option>\n";                  ">".&mt($hash{$_})."</option>\n";
     }      }
     $selectform.="</select>";      $selectform.="</select>";
     return $selectform;      return $selectform;
 }  }
   
   sub select_level_form {
       my ($deflevel,$name)=@_;
       unless ($deflevel) { $deflevel=0; }
       return &select_form($deflevel,$name,(
    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'));
   }
 #-------------------------------------------  #-------------------------------------------
   
 =pod  =pod
Line 887  Outputs: Line 901  Outputs:
   
 =back  =back
   
   =back 
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 925  sub decode_user_agent { Line 941  sub decode_user_agent {
             $clientunicode,$clientos,);              $clientunicode,$clientos,);
 }  }
   
 =pod  
   
 =back  
   
 =cut  
   
 ###############################################################  ###############################################################
 ##    Authentication changing form generation subroutines    ##  ##    Authentication changing form generation subroutines    ##
 ###############################################################  ###############################################################
Line 971  See loncreateuser.pm for invocation and Line 981  See loncreateuser.pm for invocation and
   
 =back  =back
   
   =back 
   
 =cut  =cut
   
 #-------------------------------------------  #-------------------------------------------
Line 1061  END Line 1073  END
   
 sub authform_authorwarning{  sub authform_authorwarning{
     my $result='';      my $result='';
     $result=<<"END";      $result='<i>'.
 <i>As a general rule, only authors or co-authors should be filesystem          &mt('As a general rule, only authors or co-authors should be '.
 authenticated (which allows access to the server filesystem).</i>              'filesystem authenticated '.
 END              '(which allows access to the server filesystem).')."</i>\n";
     return $result;      return $result;
 }  }
   
Line 1074  sub authform_nochange{ Line 1086  sub authform_nochange{
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
           );            );
     my $result='';      my $result = &mt('[_1] Do not change login data',
     $result.=<<"END";                       '<input type="radio" name="login" value="nochange" '.
 <input type="radio" name="login" value="nochange" checked="checked"                       'checked="checked" onclick="'.
        onclick="javascript:changed_radio('nochange',$in{'formname'});" />              "javascript:changed_radio('nochange',$in{'formname'});".'" />');
 Do not change login data  
 END  
     return $result;      return $result;
 }  }
   
Line 1090  sub authform_kerberos{ Line 1100  sub authform_kerberos{
               kerb_def_auth => 'krb4',                kerb_def_auth => 'krb4',
               @_,                @_,
               );                );
     my $result='';      my ($check4,$check5);
     my $check4;  
     my $check5;  
     if ($in{'kerb_def_auth'} eq 'krb5') {      if ($in{'kerb_def_auth'} eq 'krb5') {
        $check5 = " checked=\"on\"";         $check5 = " checked=\"on\"";
     } else {      } else {
        $check4 = " checked=\"on\"";         $check4 = " checked=\"on\"";
     }      }
     $result.=<<"END";      my $jscall = "javascript:changed_radio('krb',$in{'formname'});";
 <input type="radio" name="login" value="krb"       my $result .= &mt
        onclick="javascript:changed_radio('krb',$in{'formname'});"          ('[_1] Kerberos authenticated with domain [_2] '.
        onchange="javascript:changed_radio('krb',$in{'formname'});" />           '[_3] Version 4 [_4] Version 5',
 Kerberos authenticated with domain           '<input type="radio" name="login" value="krb" '.
 <input type="text" size="10" name="krbarg" value="$in{'kerb_def_dom'}"               'onclick="'.$jscall.'" onchange="'.$jscall.'" />',
        onchange="javascript:changed_text('krb',$in{'formname'});" />           '<input type="text" size="10" name="krbarg" '.
 <input type="radio" name="krbver" value="4" $check4 />Version 4               'value="'.$in{'kerb_def_dom'}.'" '.
 <input type="radio" name="krbver" value="5" $check5 />Version 5               'onchange="'.$jscall.'" />',
 END           '<input type="radio" name="krbver" value="4" '.$check4.' />',
            '<input type="radio" name="krbver" value="5" '.$check5.' />');
     return $result;      return $result;
 }  }
   
Line 1117  sub authform_internal{ Line 1126  sub authform_internal{
                 kerb_def_dom => 'MSU.EDU',                  kerb_def_dom => 'MSU.EDU',
                 @_,                  @_,
                 );                  );
     my $result='';      my $jscall = "javascript:changed_radio('int',$args{'formname'});";
     $result.=<<"END";      my $result.=&mt
 <input type="radio" name="login" value="int"          ('[_1] Internally authenticated (with initial password [_2])',
        onchange="javascript:changed_radio('int',$args{'formname'});"           '<input type="radio" name="login" value="int" '.
        onclick="javascript:changed_radio('int',$args{'formname'});" />               'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
 Internally authenticated (with initial password            '<input type="text" size="10" name="intarg" value="" '.
 <input type="text" size="10" name="intarg" value=""               'onchange="'.$jscall.'" />');
        onchange="javascript:changed_text('int',$args{'formname'});" />)  
 END  
     return $result;      return $result;
 }  }
   
Line 1135  sub authform_local{ Line 1142  sub authform_local{
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my $result='';      my $jscall = "javascript:changed_radio('loc',$in{'formname'});";
     $result.=<<"END";      my $result.=&mt('[_1] Local Authentication with argument [_2]',
 <input type="radio" name="login" value="loc"                      '<input type="radio" name="login" value="loc" '.
        onchange="javascript:changed_radio('loc',$in{'formname'});"                          'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
        onclick="javascript:changed_radio('loc',$in{'formname'});" />                      '<input type="text" size="10" name="locarg" value="" '.
 Local Authentication with argument                          'onchange="'.$jscall.'" />');
 <input type="text" size="10" name="locarg" value=""  
        onchange="javascript:changed_text('loc',$in{'formname'});" />  
 END  
     return $result;      return $result;
 }  }
   
Line 1153  sub authform_filesystem{ Line 1157  sub authform_filesystem{
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my $result='';      my $jscall = "javascript:changed_radio('fsys',$in{'formname'});";
     $result.=<<"END";      my $result.= &mt
 <input type="radio" name="login" value="fsys"           ('[_1] Filesystem Authenticated (with initial password [_2])',
        onchange="javascript:changed_radio('fsys',$in{'formname'});"           '<input type="radio" name="login" value="fsys" '.
        onclick="javascript:changed_radio('fsys',$in{'formname'});" />           'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
 Filesystem authenticated (with initial password            '<input type="text" size="10" name="fsysarg" value="" '.
 <input type="text" size="10" name="fsysarg" value=""                    'onchange="'.$jscall.'" />');
        onchange="javascript:changed_text('fsys',$in{'formname'});">)  
 END  
     return $result;      return $result;
 }  }
   
 =pod  
   
 =back  
   
 =cut  
   
 ###############################################################  ###############################################################
 ##    Get Authentication Defaults for Domain                 ##  ##    Get Authentication Defaults for Domain                 ##
 ###############################################################  ###############################################################
Line 1325  sub keyword { Line 1321  sub keyword {
   
 =item * get_related_words  =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  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  will be returned.  The order of the words returned is determined by the
 database which holds them.  database which holds them.
Line 1503  returns description of a specified langu Line 1499  returns description of a specified langu
 =cut  =cut
   
 sub languagedescription {  sub languagedescription {
     return $language{shift(@_)};      my $code=shift;
       return  ($supported_language{$code}?'* ':'').
               $language{$code}.
       ($supported_language{$code}?' ('.&mt('interface available').')':'');
   }
   
   sub plainlanguagedescription {
       my $code=shift;
       return $language{$code};
   }
   
   sub supportedlanguagecode {
       my $code=shift;
       return $supported_language{$code};
 }  }
   
 =pod  =pod
Line 1611  sub fileextensions { Line 1620  sub fileextensions {
   
 sub display_languages {  sub display_languages {
     my %languages=();      my %languages=();
     if ($ENV{'environment.languages'}) {      foreach (&preferred_languages()) {
  foreach (split(/\s*(\,|\;|\:)\s*/,$ENV{'environment.languages'})) {   $languages{$_}=1;
     $languages{$_}=1;  
         }  
     }  
     if ($ENV{'course.'.$ENV{'request.course.id'}.'.languages'}) {  
  foreach (split(/\s*(\,|\;|\:)\s*/,  
  $ENV{'course.'.$ENV{'request.course.id'}.'.languages'})) {  
     $languages{$_}=1;  
         }  
     }      }
     &get_unprocessed_cgi($ENV{'QUERY_STRING'},['displaylanguage']);      &get_unprocessed_cgi($ENV{'QUERY_STRING'},['displaylanguage']);
     if ($ENV{'form.displaylanguage'}) {      if ($ENV{'form.displaylanguage'}) {
Line 1631  sub display_languages { Line 1632  sub display_languages {
     return %languages;      return %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'}));
       }
       my $browser=(split(/\;/,$ENV{'HTTP_ACCEPT_LANGUAGE'}))[0];
       if ($browser) {
    @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$browser));
       }
       if ($Apache::lonnet::domain_lang_def{$ENV{'user.domain'}}) {
    @languages=(@languages,
    $Apache::lonnet::domain_lang_def{$ENV{'user.domain'}});
       }
       if ($Apache::lonnet::domain_lang_def{$ENV{'request.role.domain'}}) {
    @languages=(@languages,
    $Apache::lonnet::domain_lang_def{$ENV{'request.role.domain'}});
       }
       if ($Apache::lonnet::domain_lang_def{
                             $Apache::lonnet::perlvar{'lonDefDomain'}}) {
    @languages=(@languages,
    $Apache::lonnet::domain_lang_def{
                                     $Apache::lonnet::perlvar{'lonDefDomain'}});
       }
   # turn "en-ca" into "en-ca,en"
       my @genlanguages;
       foreach (@languages) {
    unless ($_=~/\w/) { next; }
    push (@genlanguages,$_);
    if ($_=~/(\-|\_)/) {
       push (@genlanguages,(split(/(\-|\_)/,$_))[0]);
    }
       }
       return @genlanguages;
   }
   
 ###############################################################  ###############################################################
 ##               Student Answer Attempts                     ##  ##               Student Answer Attempts                     ##
 ###############################################################  ###############################################################
Line 1711  sub get_previous_attempt { Line 1751  sub get_previous_attempt {
        } else {         } else {
   $value=$returnhash{$version.':'.$_};    $value=$returnhash{$version.':'.$_};
        }         }
        $prevattempts.='<td>'.$value.'&nbsp;</td>';            $prevattempts.='<td>'.&Apache::lonnet::unescape($value).'&nbsp;</td>';   
     }      }
  }   }
       }        }
Line 1723  sub get_previous_attempt { Line 1763  sub get_previous_attempt {
  } else {   } else {
   $value=$lasthash{$_};    $value=$lasthash{$_};
  }   }
    $value=&Apache::lonnet::unescape($value);
  if ($_ =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}   if ($_ =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
  $prevattempts.='<td>'.$value.'&nbsp;</td>';   $prevattempts.='<td>'.$value.'&nbsp;</td>';
       }        }
Line 1972  sub domainlogo { Line 2013  sub domainlogo {
  my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};   my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
  if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }   if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
         return '<img src="http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.          return '<img src="http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.
     '/adm/lonDomLogos/'.$domain.'.gif" />';      '/adm/lonDomLogos/'.$domain.'.gif" alt="'.$domain.'" />';
     } elsif(exists($Apache::lonnet::domaindescription{$domain})) {      } elsif(exists($Apache::lonnet::domaindescription{$domain})) {
         return $Apache::lonnet::domaindescription{$domain};          return $Apache::lonnet::domaindescription{$domain};
     } else {      } else {
Line 2059  other decorations will be returned. Line 2100  other decorations will be returned.
   
 sub bodytag {  sub bodytag {
     my ($title,$function,$addentries,$bodyonly,$domain,$forcereg)=@_;      my ($title,$function,$addentries,$bodyonly,$domain,$forcereg)=@_;
       $title=&mt($title);
     unless ($function) {      unless ($function) {
  $function='student';   $function='student';
         if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {          if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {
Line 2082  sub bodytag { Line 2124  sub bodytag {
     my $sidebg=&designparm($function.'.sidebg',$domain);      my $sidebg=&designparm($function.'.sidebg',$domain);
 # Accessibility font enhance  # Accessibility font enhance
     unless ($addentries) { $addentries=''; }      unless ($addentries) { $addentries=''; }
       my $addstyle='';
     if ($ENV{'browser.fontenhance'} eq 'on') {      if ($ENV{'browser.fontenhance'} eq 'on') {
  $addentries.=' style="font-size: x-large"';   $addstyle=' font-size: x-large;';
     }      }
  # role and realm   # role and realm
     my ($role,$realm)      my ($role,$realm)
Line 2101  sub bodytag { Line 2144  sub bodytag {
     if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }      if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
 # construct main body tag  # construct main body tag
     my $bodytag = <<END;      my $bodytag = <<END;
   <style>
   h1, h2, h3, th { font-family: Arial, Helvetica, sans-serif }
   a:focus { color: red; background: yellow } 
   </style>
 <body bgcolor="$pgbg" text="$font" alink="$alink" vlink="$vlink" link="$link"  <body bgcolor="$pgbg" text="$font" alink="$alink" vlink="$vlink" link="$link"
 $addentries>  style="margin-top: 0px;$addstyle" $addentries>
 END  END
     my $upperleft='<img src="http://'.$ENV{'HTTP_HOST'}.':'.      my $upperleft='<img src="http://'.$ENV{'HTTP_HOST'}.':'.
                    $lonhttpdPort.$img.'" />';                     $lonhttpdPort.$img.'" alt="'.$function.'" />';
     if ($bodyonly) {      if ($bodyonly) {
         return $bodytag;          return $bodytag;
     } elsif ($ENV{'browser.interface'} eq 'textual') {      } elsif ($ENV{'browser.interface'} eq 'textual') {
Line 2117  END Line 2164  END
 # No Remote  # No Remote
         return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',          return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
                                                       $forcereg).                                                        $forcereg).
                '<table bgcolor="'.$pgbg.'" width="100%" border="0" cellspacing="3" cellpadding="3"><tr><td bgcolor="'.$tabbg.'"><font size="+3" color="'.$font.'"><b>'.$title.        '<table bgcolor="'.$pgbg.'" width="100%" border="0" cellspacing="3" cellpadding="3"><tr><td bgcolor="'.$tabbg.'"><font face="Arial, Helvetica, sans-serif" size="+3" color="'.$font.'"><b>'.$title.
 '</b></font></td></tr></table>';  '</b></font></td></tr></table>';
     }      }
   
Line 2133  $upperleft</td> Line 2180  $upperleft</td>
 </tr>  </tr>
 <tr>  <tr>
 <td rowspan="3" bgcolor="$tabbg">  <td rowspan="3" bgcolor="$tabbg">
 &nbsp;<font size="5"><b>$title</b></font>  &nbsp;<font size="5" face="Arial, Helvetica, sans-serif"><b>$title</b></font>
 <td bgcolor="$tabbg"  align="right">  <td bgcolor="$tabbg" align="right">
 <font size="2">  <font size="2" face="Arial, Helvetica, sans-serif">
     $ENV{'environment.firstname'}      $ENV{'environment.firstname'}
     $ENV{'environment.middlename'}      $ENV{'environment.middlename'}
     $ENV{'environment.lastname'}      $ENV{'environment.lastname'}
Line 2144  $upperleft</td> Line 2191  $upperleft</td>
 </td>  </td>
 </tr>  </tr>
 <tr><td bgcolor="$tabbg" align="right">  <tr><td bgcolor="$tabbg" align="right">
 <font size="2">$role</font>&nbsp;  <font size="2" face="Arial, Helvetica, sans-serif">$role</font>&nbsp;
 </td></tr>  </td></tr>
 <tr>  <tr>
 <td bgcolor="$tabbg" align="right"><font size="2">$realm</font>&nbsp;</td></tr>  <td bgcolor="$tabbg" align="right"><font size="2" face="Arial, Helvetica, sans-serif">$realm</font>&nbsp;</td></tr>
 </table><br>  </table><br>
 ENDBODY  ENDBODY
 }  }
Line 2287  sub no_cache { Line 2334  sub no_cache {
   #$r->header_out("Expires" => $date);    #$r->header_out("Expires" => $date);
 }  }
   
   sub content_type {
     my ($r,$type,$charset) = @_;
     unless ($charset) {
         $charset=&Apache::lonlocal::current_encoding;
     }
     $r->content_type($type.($charset?'; charset='.$charset:''));
   }
   
 =pod  =pod
   
 =item * add_to_env($name,$value)   =item * add_to_env($name,$value) 
Line 2316  sub add_to_env { Line 2371  sub add_to_env {
   
 =pod  =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   =back 
   
 =head1 CSV Upload/Handling functions  =head1 CSV Upload/Handling functions
Line 2340  sub upfile_store { Line 2421  sub upfile_store {
     my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.      my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.
  '_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;   '_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;
     {      {
  my $fh=Apache::File->new('>'.$r->dir_config('lonDaemons').          my $datafile = $r->dir_config('lonDaemons').
  '/tmp/'.$datatoken.'.tmp');                             '/tmp/'.$datatoken.'.tmp';
  print $fh $ENV{'form.upfile'};          if ( open(my $fh,">$datafile") ) {
               print $fh $ENV{'form.upfile'};
               close($fh);
           }
     }      }
     return $datatoken;      return $datatoken;
 }  }
Line 2361  sub load_tmp_file { Line 2445  sub load_tmp_file {
     my $r=shift;      my $r=shift;
     my @studentdata=();      my @studentdata=();
     {      {
  my $fh;          my $studentfile = $r->dir_config('lonDaemons').
  if ($fh=Apache::File->new($r->dir_config('lonDaemons').                                '/tmp/'.$ENV{'form.datatoken'}.'.tmp';
   '/tmp/'.$ENV{'form.datatoken'}.'.tmp')) {          if ( open(my $fh,"<$studentfile") ) {
     @studentdata=<$fh>;              @studentdata=<$fh>;
  }              close($fh);
           }
     }      }
     $ENV{'form.upfile'}=join('',@studentdata);      $ENV{'form.upfile'}=join('',@studentdata);
 }  }
Line 2439  sub record_sep { Line 2524  sub record_sep {
     return %components;      return %components;
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * upfile_select_html()  =item * upfile_select_html()
   
 return HTML code to select file and specify its type  Return HTML code to select a file from the users machine and specify 
   the file type.
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub upfile_select_html {  sub upfile_select_html {
     return (<<'ENDUPFORM');      my %Types = (
 <input type="file" name="upfile" size="50" />                   csv   => &mt('CSV (comma separated values, spreadsheet)'),
 <br />Type: <select name="upfiletype">                   space => &mt('Space separated'),
 <option value="csv">CSV (comma separated values, spreadsheet)</option>                   tab   => &mt('Tabulator separated'),
 <option value="space">Space separated</option>  #                 xml   => &mt('HTML/XML'),
 <option value="tab">Tabulator separated</option>                   );
 <option value="xml">HTML/XML</option>      my $Str = '<input type="file" name="upfile" size="50" />'.
 </select>          '<br />Type: <select name="upfiletype">';
 ENDUPFORM      foreach my $type (sort(keys(%Types))) {
           $Str .= '<option value="'.$type.'" >'.$Types{$type}."</option>\n";
       }
       $Str .= "</select>\n";
       return $Str;
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * csv_print_samples($r,$records)  =item * csv_print_samples($r,$records)
Line 2469  Apache Request ref, $records is an array Line 2567  Apache Request ref, $records is an array
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub csv_print_samples {  sub csv_print_samples {
     my ($r,$records) = @_;      my ($r,$records) = @_;
     my (%sone,%stwo,%sthree);      my (%sone,%stwo,%sthree);
     %sone=&record_sep($$records[0]);      %sone=&record_sep($$records[0]);
     if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}      if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
     if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}      if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
       #
     $r->print('Samples<br /><table border="2"><tr>');      $r->print(&mt('Samples').'<br /><table border="2"><tr>');
     foreach (sort({$a <=> $b} keys(%sone))) { $r->print('<th>Column&nbsp;'.($_+1).'</th>'); }      foreach (sort({$a <=> $b} keys(%sone))) { 
           $r->print('<th>'.&mt('Column&nbsp;[_1]',($_+1)).'</th>'); }
     $r->print('</tr>');      $r->print('</tr>');
     foreach my $hash (\%sone,\%stwo,\%sthree) {      foreach my $hash (\%sone,\%stwo,\%sthree) {
  $r->print('<tr>');   $r->print('<tr>');
Line 2491  sub csv_print_samples { Line 2592  sub csv_print_samples {
     $r->print('</tr></table><br />'."\n");      $r->print('</tr></table><br />'."\n");
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * csv_print_select_table($r,$records,$d)  =item * csv_print_select_table($r,$records,$d)
   
 Prints a table to create associations between values and table columns.  Prints a table to create associations between values and table columns.
   
 $r is an Apache Request ref,  $r is an Apache Request ref,
 $records is an arrayref from &Apache::loncommon::upfile_record_sep,  $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)
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub csv_print_select_table {  sub csv_print_select_table {
     my ($r,$records,$d) = @_;      my ($r,$records,$d) = @_;
     my $i=0;my %sone;      my $i=0;my %sone;
     %sone=&record_sep($$records[0]);      %sone=&record_sep($$records[0]);
     $r->print('Associate columns with student attributes.'."\n".      $r->print(&mt('Associate columns with student attributes.')."\n".
      '<table border="2"><tr><th>Attribute</th><th>Column</th></tr>'."\n");       '<table border="2"><tr>'.
                 '<th>'.&mt('Attribute').'</th>'.
                 '<th>'.&mt('Column').'</th></tr>'."\n");
     foreach (@$d) {      foreach (@$d) {
  my ($value,$display)=@{ $_ };   my ($value,$display)=@{ $_ };
  $r->print('<tr><td>'.$display.'</td>');   $r->print('<tr><td>'.$display.'</td>');
Line 2525  sub csv_print_select_table { Line 2634  sub csv_print_select_table {
     return $i;      return $i;
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * csv_samples_select_table($r,$records,$d)  =item * csv_samples_select_table($r,$records,$d)
Line 2537  $d is an array of 2 element arrays (inte Line 2649  $d is an array of 2 element arrays (inte
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub csv_samples_select_table {  sub csv_samples_select_table {
     my ($r,$records,$d) = @_;      my ($r,$records,$d) = @_;
     my %sone; my %stwo; my %sthree;      my %sone; my %stwo; my %sthree;
     my $i=0;      my $i=0;
       #
     $r->print('<table border=2><tr><th>Field</th><th>Samples</th></tr>');      $r->print('<table border=2><tr><th>'.
                 &mt('Field').'</th><th>'.&mt('Samples').'</th></tr>');
     %sone=&record_sep($$records[0]);      %sone=&record_sep($$records[0]);
     if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}      if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
     if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}      if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
       #
     foreach (sort keys %sone) {      foreach (sort keys %sone) {
  $r->print('<tr><td><select name=f'.$i.   $r->print('<tr><td><select name="f'.$i.'"'.
   ' onchange="javascript:flip(this.form,'.$i.');">');    ' onchange="javascript:flip(this.form,'.$i.');">');
  foreach (@$d) {   foreach (@$d) {
     my ($value,$display)=@{ $_ };      my ($value,$display)=@{ $_ };
     $r->print('<option value='.$value.'>'.$display.'</option>');      $r->print('<option value="'.$value.'">'.$display.'</option>');
  }   }
  $r->print('</select></td><td>');   $r->print('</select></td><td>');
  if (defined($sone{$_})) { $r->print($sone{$_}."</br>\n"); }   if (defined($sone{$_})) { $r->print($sone{$_}."</br>\n"); }
Line 2565  sub csv_samples_select_table { Line 2680  sub csv_samples_select_table {
     return($i);      return($i);
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item clean_excel_name($name)  =item clean_excel_name($name)
Line 2573  Returns a replacement for $name which do Line 2691  Returns a replacement for $name which do
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub clean_excel_name {  sub clean_excel_name {
     my ($name) = @_;      my ($name) = @_;
     $name =~ s/[:\*\?\/\\]//g;      $name =~ s/[:\*\?\/\\]//g;
Line 2601  $uname, optional the username of the use Line 2721  $uname, optional the username of the use
   
 sub check_if_partid_hidden {  sub check_if_partid_hidden {
     my ($id,$symb,$udom,$uname) = @_;      my ($id,$symb,$udom,$uname) = @_;
     my $hiddenparts=&Apache::lonnet::EXT('resource.0.parameter_hiddenparts',      my $hiddenparts=&Apache::lonnet::EXT('resource.0.hiddenparts',
  $symb,$udom,$uname);   $symb,$udom,$uname);
       my $truth=1;
       #if the string starts with !, then the list is the list to show not hide
       if ($hiddenparts=~s/^\s*!//) { $truth=undef; }
     my @hiddenlist=split(/,/,$hiddenparts);      my @hiddenlist=split(/,/,$hiddenparts);
     foreach my $checkid (@hiddenlist) {      foreach my $checkid (@hiddenlist) {
  if ($checkid =~ /^\s*\Q$id\E\s*$/) { return 1; }   if ($checkid =~ /^\s*\Q$id\E\s*$/) { return $truth; }
       }
       return !$truth;
   }
   
   
   ############################################################
   ############################################################
   
   =pod
   
   =back 
   
   =head1 cgi-bin script and graphing routines
   
   =over 4
   
   =item get_cgi_id
   
   Inputs: none
   
   Returns an id which can be used to pass environment variables
   to various cgi-bin scripts.  These environment variables will
   be removed from the users environment after a given time by
   the routine &Apache::lonnet::transfer_profile_to_env.
   
   =cut
   
   ############################################################
   ############################################################
   my $uniq=0;
   sub get_cgi_id {
       $uniq=($uniq+1)%100000;
       return (time.'_'.$uniq);
   }
   
   ############################################################
   ############################################################
   
   =pod
   
   =item DrawBarGraph
   
   Facilitates the plotting of data in a (stacked) bar graph.
   Puts plot definition data into the users environment in order for 
   graph.png to plot it.  Returns an <img> tag for the plot.
   The bars on the plot are labeled '1','2',...,'n'.
   
   Inputs:
   
   =over 4
   
   =item $Title: string, the title of the plot
   
   =item $xlabel: string, text describing the X-axis of the plot
   
   =item $ylabel: string, text describing the Y-axis of the plot
   
   =item $Max: scalar, the maximum Y value to use in the plot
   If $Max is < any data point, the graph will not be rendered.
   
   =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 @Values: An array of array references.  Each array reference holds data
   to be plotted in a stacked bar chart.
   
   =back
   
   Returns:
   
   An <img> tag which references graph.png and the appropriate identifying
   information for the plot.
   
   =cut
   
   ############################################################
   ############################################################
   sub DrawBarGraph {
       my ($Title,$xlabel,$ylabel,$Max,$colors,@Values)=@_;
       #
       if (! defined($colors)) {
           $colors = ['#33ff00', 
                     '#0033cc', '#990000', '#aaaa66', '#663399', '#ff9933',
                     '#66ccff', '#ff9999', '#cccc33', '#660000', '#33cc66',
                     ]; 
     }      }
     return undef;      #
       my $identifier = &get_cgi_id();
       my $id = 'cgi.'.$identifier;        
       if (! @Values || ref($Values[0]) ne 'ARRAY') {
           return '';
       }
       my $NumBars = scalar(@{$Values[0]});
       my %ValuesHash;
       my $NumSets=1;
       foreach my $array (@Values) {
           next if (! ref($array));
           $ValuesHash{$id.'.data.'.$NumSets++} = 
               join(',',@$array);
       }
       #
       my ($height,$width,$xskip,$bar_width) = (200,120,1,15);
       if ($NumBars < 10) {
           $width = 120+$NumBars*15;
           $xskip = 1;
           $bar_width = 15;
       } elsif ($NumBars <= 25) {
           $width = 120+$NumBars*11;
           $xskip = 5;
           $bar_width = 8;
       } elsif ($NumBars <= 50) {
           $width = 120+$NumBars*8;
           $xskip = 5;
           $bar_width = 4;
       } else {
           $width = 120+$NumBars*8;
           $xskip = 5;
           $bar_width = 4;
       }
       #
       my @Labels;
       for (my $i=0;$i<@{$Values[0]};$i++) {
           push (@Labels,$i+1);
       }
       #
       $Max = 1 if ($Max < 1);
       if ( int($Max) < $Max ) {
           $Max++;
           $Max = int($Max);
       }
       $Title  = '' if (! defined($Title));
       $xlabel = '' if (! defined($xlabel));
       $ylabel = '' if (! defined($ylabel));
       $ValuesHash{$id.'.title'}    = &Apache::lonnet::escape($Title);
       $ValuesHash{$id.'.xlabel'}   = &Apache::lonnet::escape($xlabel);
       $ValuesHash{$id.'.ylabel'}   = &Apache::lonnet::escape($ylabel);
       $ValuesHash{$id.'.y_max_value'} = $Max;
       $ValuesHash{$id.'.NumBars'}  = $NumBars;
       $ValuesHash{$id.'.NumSets'}  = $NumSets;
       $ValuesHash{$id.'.PlotType'} = 'bar';
       $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
       $ValuesHash{$id.'.height'}   = $height;
       $ValuesHash{$id.'.width'}    = $width;
       $ValuesHash{$id.'.xskip'}    = $xskip;
       $ValuesHash{$id.'.bar_width'} = $bar_width;
       $ValuesHash{$id.'.labels'} = join(',',@Labels);
       #
       &Apache::lonnet::appenv(%ValuesHash);
       return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
 }  }
   
   ############################################################
   ############################################################
   
   =pod
   
   =item DrawXYGraph
   
   Facilitates the plotting of data in an XY graph.
   Puts plot definition data into the users environment in order for 
   graph.png to plot it.  Returns an <img> tag for the plot.
   
   Inputs:
   
   =over 4
   
   =item $Title: string, the title of the plot
   
   =item $xlabel: string, text describing the X-axis of the plot
   
   =item $ylabel: string, text describing the Y-axis of the plot
   
   =item $Max: scalar, the maximum Y value to use in the plot
   If $Max is < any data point, the graph will not be rendered.
   
   =item $colors: Array ref containing the hex color codes for the data to be 
   plotted in.  If undefined, default values will be used.
   
   =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.
   
   =item %Values: hash indicating or overriding any default values which are 
   passed to graph.png.  
   Possible values are: width, xskip, x_ticks, x_tick_offset, among others.
   
   =back
   
   Returns:
   
   An <img> tag which references graph.png and the appropriate identifying
   information for the plot.
   
   =cut
   
   ############################################################
   ############################################################
   sub DrawXYGraph {
       my ($Title,$xlabel,$ylabel,$Max,$colors,$Xlabels,$Ydata,%Values)=@_;
       #
       # Create the identifier for the graph
       my $identifier = &get_cgi_id();
       my $id = 'cgi.'.$identifier;
       #
       $Title  = '' if (! defined($Title));
       $xlabel = '' if (! defined($xlabel));
       $ylabel = '' if (! defined($ylabel));
       my %ValuesHash = 
           (
            $id.'.title'  => &Apache::lonnet::escape($Title),
            $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
            $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
            $id.'.y_max_value'=> $Max,
            $id.'.labels'     => join(',',@$Xlabels),
            $id.'.PlotType'   => 'XY',
            );
       #
       if (defined($colors) && ref($colors) eq 'ARRAY') {
           $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
       }
       #
       if (! ref($Ydata) || ref($Ydata) ne 'ARRAY') {
           return '';
       }
       my $NumSets=1;
       foreach my $array (@{$Ydata}){
           next if (! ref($array));
           $ValuesHash{$id.'.data.'.$NumSets++} = join(',',@$array);
       }
       $ValuesHash{$id.'.NumSets'} = $NumSets-1;
       #
       # Deal with other parameters
       while (my ($key,$value) = each(%Values)) {
           $ValuesHash{$id.'.'.$key} = $value;
       }
       #
       &Apache::lonnet::appenv(%ValuesHash);
       return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
   }
   
   ############################################################
   ############################################################
   
   =pod
   
   =item DrawXYYGraph
   
   Facilitates the plotting of data in an XY graph with two Y axes.
   Puts plot definition data into the users environment in order for 
   graph.png to plot it.  Returns an <img> tag for the plot.
   
   Inputs:
   
   =over 4
   
   =item $Title: string, the title of the plot
   
   =item $xlabel: string, text describing the X-axis of the plot
   
   =item $ylabel: string, text describing the Y-axis of the plot
   
   =item $colors: Array ref containing the hex color codes for the data to be 
   plotted in.  If undefined, default values will be used.
   
   =item $Xlabels: Array ref containing the labels to be used for the X-axis.
   
   =item $Ydata1: The first data set
   
   =item $Min1: The minimum value of the left Y-axis
   
   =item $Max1: The maximum value of the left Y-axis
   
   =item $Ydata2: The second data set
   
   =item $Min2: The minimum value of the right Y-axis
   
   =item $Max2: The maximum value of the left Y-axis
   
   =item %Values: hash indicating or overriding any default values which are 
   passed to graph.png.  
   Possible values are: width, xskip, x_ticks, x_tick_offset, among others.
   
   =back
   
   Returns:
   
   An <img> tag which references graph.png and the appropriate identifying
   information for the plot.
   
   =cut
   
   ############################################################
   ############################################################
   sub DrawXYYGraph {
       my ($Title,$xlabel,$ylabel,$colors,$Xlabels,$Ydata1,$Min1,$Max1,
                                           $Ydata2,$Min2,$Max2,%Values)=@_;
       #
       # Create the identifier for the graph
       my $identifier = &get_cgi_id();
       my $id = 'cgi.'.$identifier;
       #
       $Title  = '' if (! defined($Title));
       $xlabel = '' if (! defined($xlabel));
       $ylabel = '' if (! defined($ylabel));
       my %ValuesHash = 
           (
            $id.'.title'  => &Apache::lonnet::escape($Title),
            $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
            $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
            $id.'.labels' => join(',',@$Xlabels),
            $id.'.PlotType' => 'XY',
            $id.'.NumSets' => 2,
            $id.'.two_axes' => 1,
            $id.'.y1_max_value' => $Max1,
            $id.'.y1_min_value' => $Min1,
            $id.'.y2_max_value' => $Max2,
            $id.'.y2_min_value' => $Min2,
            );
       #
       if (defined($colors) && ref($colors) eq 'ARRAY') {
           $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
       }
       #
       if (! ref($Ydata1) || ref($Ydata1) ne 'ARRAY' ||
           ! ref($Ydata2) || ref($Ydata2) ne 'ARRAY'){
           return '';
       }
       my $NumSets=1;
       foreach my $array ($Ydata1,$Ydata2){
           next if (! ref($array));
           $ValuesHash{$id.'.data.'.$NumSets++} = join(',',@$array);
       }
       #
       # Deal with other parameters
       while (my ($key,$value) = each(%Values)) {
           $ValuesHash{$id.'.'.$key} = $value;
       }
       #
       &Apache::lonnet::appenv(%ValuesHash);
       return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
   }
   
   ############################################################
   ############################################################
   
   =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.  
   
   Inputs:
   
   =over 4
   
   =item $linktext: The text of the link
   
   =item $sname: The students username
   
   =item $sdomain: The students domain
   
   =back
   
   =back
   
   =cut
   
   ############################################################
   ############################################################
   sub chartlink {
       my ($linktext, $sname, $sdomain) = @_;
       my $link = '<a href="/adm/statistics?reportSelected=student_assessment'.
           '&SelectedStudent='.&Apache::lonnet::escape($sname.':'.$sdomain).
           '&chartoutputmode='.HTML::Entities::encode('html, with all links').
          '">'.$linktext.'</a>';
   }
   
   #######################################################
   #######################################################
   
   =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 @file_ext = split(/\./,$file);
       my $curfext = $file_ext[-1];
       my $iconname="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";
   } 
   
 =pod  =pod
   
 =back  =back

Removed from v.1.116  
changed lines
  Added in v.1.163


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