Annotation of loncom/interface/loncommon.pm, revision 1.174

1.10      albertel    1: # The LearningOnline Network with CAPA
1.1       albertel    2: # a pile of common routines
1.10      albertel    3: #
1.174   ! matthew     4: # $Id: loncommon.pm,v 1.173 2004/01/15 18:12:59 www Exp $
1.10      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.1       albertel   28: 
                     29: # Makes a table out of the previous attempts
1.2       albertel   30: # Inputs result_from_symbread, user, domain, course_id
1.16      harris41   31: # Reads in non-network-related .tab files
1.1       albertel   32: 
1.35      matthew    33: # POD header:
                     34: 
1.45      matthew    35: =pod
                     36: 
1.35      matthew    37: =head1 NAME
                     38: 
                     39: Apache::loncommon - pile of common routines
                     40: 
                     41: =head1 SYNOPSIS
                     42: 
1.112     bowersj2   43: Common routines for manipulating connections, student answers,
                     44:     domains, common Javascript fragments, etc.
1.35      matthew    45: 
1.112     bowersj2   46: =head1 OVERVIEW
1.35      matthew    47: 
1.112     bowersj2   48: A collection of commonly used subroutines that don't have a natural
                     49: home anywhere else. This collection helps remove
1.35      matthew    50: redundancy from other modules and increase efficiency of memory usage.
                     51: 
                     52: =cut 
                     53: 
                     54: # End of POD header
1.1       albertel   55: package Apache::loncommon;
                     56: 
                     57: use strict;
1.22      www        58: use Apache::lonnet();
1.46      matthew    59: use GDBM_File;
1.51      www        60: use POSIX qw(strftime mktime);
1.99      www        61: use Apache::Constants qw(:common :http :methods);
1.1       albertel   62: use Apache::lonmsg();
1.82      www        63: use Apache::lonmenu();
1.117     www        64: use Apache::lonlocal;
1.139     matthew    65: use HTML::Entities;
1.117     www        66: 
1.22      www        67: my $readit;
                     68: 
1.157     matthew    69: ##
                     70: ## Global Variables
                     71: ##
1.46      matthew    72: 
1.20      www        73: # ----------------------------------------------- Filetypes/Languages/Copyright
1.12      harris41   74: my %language;
1.124     www        75: my %supported_language;
1.12      harris41   76: my %cprtag;
                     77: my %fe; my %fd;
1.41      ng         78: my %category_extensions;
1.12      harris41   79: 
1.63      www        80: # ---------------------------------------------- Designs
                     81: 
                     82: my %designhash;
                     83: 
1.46      matthew    84: # ---------------------------------------------- Thesaurus variables
1.144     matthew    85: #
                     86: # %Keywords:
                     87: #      A hash used by &keyword to determine if a word is considered a keyword.
                     88: # $thesaurus_db_file 
                     89: #      Scalar containing the full path to the thesaurus database.
1.46      matthew    90: 
                     91: my %Keywords;
                     92: my $thesaurus_db_file;
                     93: 
1.144     matthew    94: #
                     95: # Initialize values from language.tab, copyright.tab, filetypes.tab,
                     96: # thesaurus.tab, and filecategories.tab.
                     97: #
1.18      www        98: BEGIN {
1.46      matthew    99:     # Variable initialization
                    100:     $thesaurus_db_file = $Apache::lonnet::perlvar{'lonTabDir'}."/thesaurus.db";
                    101:     #
1.22      www       102:     unless ($readit) {
1.12      harris41  103: # ------------------------------------------------------------------- languages
                    104:     {
1.158     raeburn   105:         my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}.
                    106:                                    '/language.tab';
                    107:         if ( open(my $fh,"<$langtabfile") ) {
                    108:             while (<$fh>) {
                    109:                 next if /^\#/;
                    110:                 chomp;
                    111:                 my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_));
                    112:                 $language{$key}=$val.' - '.$enc;
                    113:                 if ($sup) {
                    114:                     $supported_language{$key}=$sup;
                    115:                 }
                    116:             }
                    117:             close($fh);
                    118:         }
1.12      harris41  119:     }
                    120: # ------------------------------------------------------------------ copyrights
                    121:     {
1.158     raeburn   122:         my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
                    123:                                   '/copyright.tab';
                    124:         if ( open (my $fh,"<$copyrightfile") ) {
                    125:             while (<$fh>) {
                    126:                 next if /^\#/;
                    127:                 chomp;
                    128:                 my ($key,$val)=(split(/\s+/,$_,2));
                    129:                 $cprtag{$key}=$val;
                    130:             }
                    131:             close($fh);
                    132:         }
1.12      harris41  133:     }
1.63      www       134: 
                    135: # -------------------------------------------------------------- domain designs
                    136: 
                    137:     my $filename;
                    138:     my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
                    139:     opendir(DIR,$designdir);
                    140:     while ($filename=readdir(DIR)) {
                    141: 	my ($domain)=($filename=~/^(\w+)\./);
                    142:     {
1.158     raeburn   143:         my $designfile = $designdir.'/'.$filename;
                    144:         if ( open (my $fh,"<$designfile") ) {
                    145:             while (<$fh>) {
                    146:                 next if /^\#/;
                    147:                 chomp;
                    148:                 my ($key,$val)=(split(/\=/,$_));
                    149:                 if ($val) { $designhash{$domain.'.'.$key}=$val; }
                    150:             }
                    151:             close($fh);
                    152:         }
1.63      www       153:     }
                    154: 
                    155:     }
                    156:     closedir(DIR);
                    157: 
                    158: 
1.15      harris41  159: # ------------------------------------------------------------- file categories
                    160:     {
1.158     raeburn   161:         my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}.
                    162:                                   '/filecategories.tab';
                    163:         if ( open (my $fh,"<$categoryfile") ) {
                    164:             while (<$fh>) {
                    165:                 next if /^\#/;
                    166:                 chomp;
                    167:                 my ($extension,$category)=(split(/\s+/,$_,2));
                    168:                 push @{$category_extensions{lc($category)}},$extension;
                    169:             }
                    170:             close($fh);
                    171:         }
                    172: 
1.15      harris41  173:     }
1.12      harris41  174: # ------------------------------------------------------------------ file types
                    175:     {
1.158     raeburn   176:         my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}.
                    177:                '/filetypes.tab';
                    178:         if ( open (my $fh,"<$typesfile") ) {
1.16      harris41  179:             while (<$fh>) {
1.158     raeburn   180:                 next if (/^\#/);
                    181:                 chomp;
                    182:                 my ($ending,$emb,$descr)=split(/\s+/,$_,3);
                    183:                 if ($descr ne '') {
                    184:                     $fe{$ending}=lc($emb);
                    185:                     $fd{$ending}=$descr;
                    186:                 }
                    187:             }
                    188:             close($fh);
                    189:         }
1.12      harris41  190:     }
1.22      www       191:     &Apache::lonnet::logthis(
1.46      matthew   192:               "<font color=yellow>INFO: Read file types</font>");
1.22      www       193:     $readit=1;
1.46      matthew   194:     }  # end of unless($readit) 
1.32      matthew   195:     
                    196: }
1.112     bowersj2  197: 
1.42      matthew   198: ###############################################################
                    199: ##           HTML and Javascript Helper Functions            ##
                    200: ###############################################################
                    201: 
                    202: =pod 
                    203: 
1.112     bowersj2  204: =head1 HTML and Javascript Functions
1.42      matthew   205: 
1.112     bowersj2  206: =over 4
                    207: 
                    208: =item * browser_and_searcher_javascript ()
                    209: 
                    210: X<browsing, javascript>X<searching, javascript>Returns a string
                    211: containing javascript with two functions, C<openbrowser> and
                    212: C<opensearcher>. Returned string does not contain E<lt>scriptE<gt>
                    213: tags.
1.42      matthew   214: 
1.112     bowersj2  215: =item * openbrowser(formname,elementname,only,omit) [javascript]
1.42      matthew   216: 
                    217: inputs: formname, elementname, only, omit
                    218: 
                    219: formname and elementname indicate the name of the html form and name of
                    220: the element that the results of the browsing selection are to be placed in. 
                    221: 
                    222: Specifying 'only' will restrict the browser to displaying only files
                    223: with the given extension.  Can be a comma seperated list.
                    224: 
                    225: Specifying 'omit' will restrict the browser to NOT displaying files
                    226: with the given extension.  Can be a comma seperated list.
                    227: 
1.112     bowersj2  228: =item * opensearcher(formname, elementname) [javascript]
1.42      matthew   229: 
                    230: Inputs: formname, elementname
                    231: 
                    232: formname and elementname specify the name of the html form and the name
                    233: of the element the selection from the search results will be placed in.
                    234: 
                    235: =cut
                    236: 
                    237: sub browser_and_searcher_javascript {
1.170     www       238:     my $resurl=&lastresurl();
1.42      matthew   239:     return <<END;
1.50      matthew   240:     var editbrowser = null;
1.135     albertel  241:     function openbrowser(formname,elementname,only,omit,titleelement) {
1.170     www       242:         var url = '$resurl/?';
1.42      matthew   243:         if (editbrowser == null) {
                    244:             url += 'launch=1&';
                    245:         }
                    246:         url += 'catalogmode=interactive&';
                    247:         url += 'mode=edit&';
                    248:         url += 'form=' + formname + '&';
                    249:         if (only != null) {
                    250:             url += 'only=' + only + '&';
                    251:         } 
                    252:         if (omit != null) {
                    253:             url += 'omit=' + omit + '&';
                    254:         }
1.135     albertel  255:         if (titleelement != null) {
                    256:             url += 'titleelement=' + titleelement + '&';
                    257:         }
1.42      matthew   258:         url += 'element=' + elementname + '';
                    259:         var title = 'Browser';
                    260:         var options = 'scrollbars=1,resizable=1,menubar=0';
                    261:         options += ',width=700,height=600';
                    262:         editbrowser = open(url,title,options,'1');
                    263:         editbrowser.focus();
                    264:     }
                    265:     var editsearcher;
1.135     albertel  266:     function opensearcher(formname,elementname,titleelement) {
1.42      matthew   267:         var url = '/adm/searchcat?';
                    268:         if (editsearcher == null) {
                    269:             url += 'launch=1&';
                    270:         }
                    271:         url += 'catalogmode=interactive&';
                    272:         url += 'mode=edit&';
                    273:         url += 'form=' + formname + '&';
1.135     albertel  274:         if (titleelement != null) {
                    275:             url += 'titleelement=' + titleelement + '&';
                    276:         }
1.42      matthew   277:         url += 'element=' + elementname + '';
                    278:         var title = 'Search';
                    279:         var options = 'scrollbars=1,resizable=1,menubar=0';
                    280:         options += ',width=700,height=600';
                    281:         editsearcher = open(url,title,options,'1');
                    282:         editsearcher.focus();
                    283:     }
                    284: END
1.170     www       285: }
                    286: 
                    287: sub lastresurl {
                    288:     if ($ENV{'environment.lastresurl'}) {
                    289: 	return $ENV{'environment.lastresurl'}
                    290:     } else {
                    291: 	return '/res';
                    292:     }
                    293: }
                    294: 
                    295: sub storeresurl {
                    296:     my $resurl=&Apache::lonnet::clutter(shift);
                    297:     unless ($resurl=~/^\/res/) { return 0; }
                    298:     $resurl=~s/\/$//;
                    299:     &Apache::lonnet::put('environment',{'lastresurl' => $resurl});
                    300:     &Apache::lonnet::appenv('environment.lastresurl' => $resurl);
                    301:     return 1;
1.42      matthew   302: }
                    303: 
1.74      www       304: sub studentbrowser_javascript {
1.111     www       305:    unless (
                    306:             (($ENV{'request.course.id'}) && 
                    307:              (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})))
                    308:          || ($ENV{'request.role'}=~/^(au|dc|su)/)
                    309:           ) { return ''; }  
1.74      www       310:    return (<<'ENDSTDBRW');
                    311: <script type="text/javascript" language="Javascript" >
                    312:     var stdeditbrowser;
1.111     www       313:     function openstdbrowser(formname,uname,udom,roleflag) {
1.74      www       314:         var url = '/adm/pickstudent?';
                    315:         var filter;
                    316:         eval('filter=document.'+formname+'.'+uname+'.value;');
                    317:         if (filter != null) {
                    318:            if (filter != '') {
                    319:                url += 'filter='+filter+'&';
                    320: 	   }
                    321:         }
                    322:         url += 'form=' + formname + '&unameelement='+uname+
                    323:                                     '&udomelement='+udom;
1.111     www       324: 	if (roleflag) { url+="&roles=1"; }
1.102     www       325:         var title = 'Student_Browser';
1.74      www       326:         var options = 'scrollbars=1,resizable=1,menubar=0';
                    327:         options += ',width=700,height=600';
                    328:         stdeditbrowser = open(url,title,options,'1');
                    329:         stdeditbrowser.focus();
                    330:     }
                    331: </script>
                    332: ENDSTDBRW
                    333: }
1.42      matthew   334: 
1.74      www       335: sub selectstudent_link {
1.111     www       336:    my ($form,$unameele,$udomele)=@_;
                    337:    if ($ENV{'request.course.id'}) {  
                    338:        unless (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
                    339: 	   return '';
                    340:        }
                    341:        return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele.
1.119     www       342:         '","'.$udomele.'");'."'>".&mt('Select User')."</a>";
1.74      www       343:    }
1.111     www       344:    if ($ENV{'request.role'}=~/^(au|dc|su)/) {
                    345:        return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele.
1.119     www       346:         '","'.$udomele.'",1);'."'>".&mt('Select User')."</a>";
1.111     www       347:    }
                    348:    return '';
1.91      www       349: }
                    350: 
                    351: sub coursebrowser_javascript {
1.128     albertel  352:     my ($domainfilter)=@_;
                    353:    return (<<ENDSTDBRW);
1.91      www       354: <script type="text/javascript" language="Javascript" >
                    355:     var stdeditbrowser;
                    356:     function opencrsbrowser(formname,uname,udom) {
                    357:         var url = '/adm/pickcourse?';
                    358:         var filter;
                    359:         if (filter != null) {
                    360:            if (filter != '') {
                    361:                url += 'filter='+filter+'&';
                    362: 	   }
                    363:         }
1.128     albertel  364:         var domainfilter='$domainfilter';
                    365:         if (domainfilter != null) {
                    366:            if (domainfilter != '') {
                    367:                url += 'domainfilter='+domainfilter+'&';
                    368: 	   }
                    369:         }
1.91      www       370:         url += 'form=' + formname + '&cnumelement='+uname+
                    371:                                     '&cdomelement='+udom;
1.102     www       372:         var title = 'Course_Browser';
1.91      www       373:         var options = 'scrollbars=1,resizable=1,menubar=0';
                    374:         options += ',width=700,height=600';
                    375:         stdeditbrowser = open(url,title,options,'1');
                    376:         stdeditbrowser.focus();
                    377:     }
                    378: </script>
                    379: ENDSTDBRW
                    380: }
                    381: 
                    382: sub selectcourse_link {
                    383:    my ($form,$unameele,$udomele)=@_;
                    384:     return "<a href='".'javascript:opencrsbrowser("'.$form.'","'.$unameele.
1.119     www       385:         '","'.$udomele.'");'."'>".&mt('Select Course')."</a>";
1.74      www       386: }
1.42      matthew   387: 
                    388: =pod
1.36      matthew   389: 
1.112     bowersj2  390: =item * linked_select_forms(...)
1.36      matthew   391: 
                    392: linked_select_forms returns a string containing a <script></script> block
                    393: and html for two <select> menus.  The select menus will be linked in that
                    394: changing the value of the first menu will result in new values being placed
                    395: in the second menu.  The values in the select menu will appear in alphabetical
                    396: order.
                    397: 
                    398: linked_select_forms takes the following ordered inputs:
                    399: 
                    400: =over 4
                    401: 
1.112     bowersj2  402: =item * $formname, the name of the <form> tag
1.36      matthew   403: 
1.112     bowersj2  404: =item * $middletext, the text which appears between the <select> tags
1.36      matthew   405: 
1.112     bowersj2  406: =item * $firstdefault, the default value for the first menu
1.36      matthew   407: 
1.112     bowersj2  408: =item * $firstselectname, the name of the first <select> tag
1.36      matthew   409: 
1.112     bowersj2  410: =item * $secondselectname, the name of the second <select> tag
1.36      matthew   411: 
1.112     bowersj2  412: =item * $hashref, a reference to a hash containing the data for the menus.
1.36      matthew   413: 
1.41      ng        414: =back 
                    415: 
1.36      matthew   416: Below is an example of such a hash.  Only the 'text', 'default', and 
                    417: 'select2' keys must appear as stated.  keys(%menu) are the possible 
                    418: values for the first select menu.  The text that coincides with the 
1.41      ng        419: first menu value is given in $menu{$choice1}->{'text'}.  The values 
1.36      matthew   420: and text for the second menu are given in the hash pointed to by 
                    421: $menu{$choice1}->{'select2'}.  
                    422: 
1.112     bowersj2  423:  my %menu = ( A1 => { text =>"Choice A1" ,
                    424:                        default => "B3",
                    425:                        select2 => { 
                    426:                            B1 => "Choice B1",
                    427:                            B2 => "Choice B2",
                    428:                            B3 => "Choice B3",
                    429:                            B4 => "Choice B4"
                    430:                            }
                    431:                    },
                    432:                A2 => { text =>"Choice A2" ,
                    433:                        default => "C2",
                    434:                        select2 => { 
                    435:                            C1 => "Choice C1",
                    436:                            C2 => "Choice C2",
                    437:                            C3 => "Choice C3"
                    438:                            }
                    439:                    },
                    440:                A3 => { text =>"Choice A3" ,
                    441:                        default => "D6",
                    442:                        select2 => { 
                    443:                            D1 => "Choice D1",
                    444:                            D2 => "Choice D2",
                    445:                            D3 => "Choice D3",
                    446:                            D4 => "Choice D4",
                    447:                            D5 => "Choice D5",
                    448:                            D6 => "Choice D6",
                    449:                            D7 => "Choice D7"
                    450:                            }
                    451:                    }
                    452:                );
1.36      matthew   453: 
                    454: =cut
                    455: 
                    456: sub linked_select_forms {
                    457:     my ($formname,
                    458:         $middletext,
                    459:         $firstdefault,
                    460:         $firstselectname,
                    461:         $secondselectname, 
                    462:         $hashref
                    463:         ) = @_;
                    464:     my $second = "document.$formname.$secondselectname";
                    465:     my $first = "document.$formname.$firstselectname";
                    466:     # output the javascript to do the changing
                    467:     my $result = '';
                    468:     $result.="<script>\n";
                    469:     $result.="var select2data = new Object();\n";
                    470:     $" = '","';
                    471:     my $debug = '';
                    472:     foreach my $s1 (sort(keys(%$hashref))) {
                    473:         $result.="select2data.d_$s1 = new Object();\n";        
                    474:         $result.="select2data.d_$s1.def = new String('".
                    475:             $hashref->{$s1}->{'default'}."');\n";
                    476:         $result.="select2data.d_$s1.values = new Array(";        
                    477:         my @s2values = sort(keys( %{ $hashref->{$s1}->{'select2'} } ));
                    478:         $result.="\"@s2values\");\n";
                    479:         $result.="select2data.d_$s1.texts = new Array(";        
                    480:         my @s2texts;
                    481:         foreach my $value (@s2values) {
                    482:             push @s2texts, $hashref->{$s1}->{'select2'}->{$value};
                    483:         }
                    484:         $result.="\"@s2texts\");\n";
                    485:     }
                    486:     $"=' ';
                    487:     $result.= <<"END";
                    488: 
                    489: function select1_changed() {
                    490:     // Determine new choice
                    491:     var newvalue = "d_" + $first.value;
                    492:     // update select2
                    493:     var values     = select2data[newvalue].values;
                    494:     var texts      = select2data[newvalue].texts;
                    495:     var select2def = select2data[newvalue].def;
                    496:     var i;
                    497:     // out with the old
                    498:     for (i = 0; i < $second.options.length; i++) {
                    499:         $second.options[i] = null;
                    500:     }
                    501:     // in with the nuclear
                    502:     for (i=0;i<values.length; i++) {
                    503:         $second.options[i] = new Option(values[i]);
1.143     matthew   504:         $second.options[i].value = values[i];
1.36      matthew   505:         $second.options[i].text = texts[i];
                    506:         if (values[i] == select2def) {
                    507:             $second.options[i].selected = true;
                    508:         }
                    509:     }
                    510: }
                    511: </script>
                    512: END
                    513:     # output the initial values for the selection lists
                    514:     $result .= "<select size=\"1\" name=\"$firstselectname\" onchange=\"select1_changed()\">\n";
                    515:     foreach my $value (sort(keys(%$hashref))) {
                    516:         $result.="    <option value=\"$value\" ";
                    517:         $result.=" selected=\"true\" " if ($value eq $firstdefault);
1.119     www       518:         $result.=">".&mt($hashref->{$value}->{'text'})."</option>\n";
1.36      matthew   519:     }
                    520:     $result .= "</select>\n";
                    521:     my %select2 = %{$hashref->{$firstdefault}->{'select2'}};
                    522:     $result .= $middletext;
                    523:     $result .= "<select size=\"1\" name=\"$secondselectname\">\n";
                    524:     my $seconddefault = $hashref->{$firstdefault}->{'default'};
                    525:     foreach my $value (sort(keys(%select2))) {
                    526:         $result.="    <option value=\"$value\" ";        
                    527:         $result.=" selected=\"true\" " if ($value eq $seconddefault);
1.119     www       528:         $result.=">".&mt($select2{$value})."</option>\n";
1.36      matthew   529:     }
                    530:     $result .= "</select>\n";
                    531:     #    return $debug;
                    532:     return $result;
                    533: }   #  end of sub linked_select_forms {
                    534: 
1.45      matthew   535: =pod
1.44      bowersj2  536: 
1.112     bowersj2  537: =item * help_open_topic($topic, $text, $stayOnPage, $width, $height)
1.44      bowersj2  538: 
1.112     bowersj2  539: Returns a string corresponding to an HTML link to the given help
                    540: $topic, where $topic corresponds to the name of a .tex file in
                    541: /home/httpd/html/adm/help/tex, with underscores replaced by
                    542: spaces. 
                    543: 
                    544: $text will optionally be linked to the same topic, allowing you to
                    545: link text in addition to the graphic. If you do not want to link
                    546: text, but wish to specify one of the later parameters, pass an
                    547: empty string. 
                    548: 
                    549: $stayOnPage is a value that will be interpreted as a boolean. If true,
                    550: the link will not open a new window. If false, the link will open
                    551: a new window using Javascript. (Default is false.) 
                    552: 
                    553: $width and $height are optional numerical parameters that will
                    554: override the width and height of the popped up window, which may
                    555: be useful for certain help topics with big pictures included. 
1.44      bowersj2  556: 
                    557: =cut
                    558: 
                    559: sub help_open_topic {
1.48      bowersj2  560:     my ($topic, $text, $stayOnPage, $width, $height) = @_;
                    561:     $text = "" if (not defined $text);
1.44      bowersj2  562:     $stayOnPage = 0 if (not defined $stayOnPage);
1.108     bowersj2  563:     if ($ENV{'browser.interface'} eq 'textual' ||
                    564: 	$ENV{'environment.remote'} eq 'off' ) {
1.79      www       565: 	$stayOnPage=1;
                    566:     }
1.44      bowersj2  567:     $width = 350 if (not defined $width);
                    568:     $height = 400 if (not defined $height);
                    569:     my $filename = $topic;
                    570:     $filename =~ s/ /_/g;
                    571: 
1.48      bowersj2  572:     my $template = "";
                    573:     my $link;
1.159     www       574: 
                    575:     $topic=~s/\W/\_/g;
1.44      bowersj2  576: 
                    577:     if (!$stayOnPage)
                    578:     {
1.72      bowersj2  579: 	$link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
1.44      bowersj2  580:     }
                    581:     else
                    582:     {
1.48      bowersj2  583: 	$link = "/adm/help/${filename}.hlp";
                    584:     }
                    585: 
                    586:     # Add the text
                    587:     if ($text ne "")
                    588:     {
1.77      www       589: 	$template .= 
                    590:   "<table bgcolor='#3333AA' cellspacing='1' cellpadding='1' border='0'><tr>".
1.78      www       591:   "<td bgcolor='#5555FF'><a href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
1.48      bowersj2  592:     }
                    593: 
                    594:     # Add the graphic
                    595:     $template .= <<"ENDTEMPLATE";
1.77      www       596:  <a href="$link"><image src="/adm/help/gif/smallHelp.gif" border="0" alt="(Help: $topic)" /></a>
1.44      bowersj2  597: ENDTEMPLATE
1.78      www       598:     if ($text ne '') { $template.='</td></tr></table>' };
1.44      bowersj2  599:     return $template;
                    600: 
1.106     bowersj2  601: }
                    602: 
                    603: # This is a quicky function for Latex cheatsheet editing, since it 
                    604: # appears in at least four places
                    605: sub helpLatexCheatsheet {
                    606:     my $other = shift;
                    607:     my $addOther = '';
                    608:     if ($other) {
                    609: 	$addOther = Apache::loncommon::help_open_topic($other, shift,
                    610: 						       undef, undef, 600) .
                    611: 							   '</td><td>';
                    612:     }
                    613:     return '<table><tr><td>'.
                    614: 	$addOther .
                    615: 	&Apache::loncommon::help_open_topic("Greek_Symbols",'Greek Symbols',
                    616: 					    undef,undef,600)
                    617: 	.'</td><td>'.
                    618: 	&Apache::loncommon::help_open_topic("Other_Symbols",'Other Symbols',
                    619: 					    undef,undef,600)
                    620: 	.'</td></tr></table>';
1.172     www       621: }
                    622: 
                    623: sub help_open_bug {
                    624:     my ($topic, $text, $stayOnPage, $width, $height) = @_;
                    625:     unless ($ENV{'user.adv'}) { return ''; }
                    626:     unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }
                    627:     $text = "" if (not defined $text);
                    628:     $stayOnPage = 0 if (not defined $stayOnPage);
                    629:     if ($ENV{'browser.interface'} eq 'textual' ||
                    630: 	$ENV{'environment.remote'} eq 'off' ) {
                    631: 	$stayOnPage=1;
                    632:     }
                    633:     $width = 350 if (not defined $width);
                    634:     $height = 400 if (not defined $height);
                    635: 
                    636:     $topic=~s/\W+/\+/g;
                    637:     my $link='';
                    638:     my $template='';
                    639:     my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='.
                    640: 	&Apache::lonnet::escape($ENV{'REQUEST_URI'}).'&component='.$topic;
                    641:     if (!$stayOnPage)
                    642:     {
                    643: 	$link = "javascript:void(open('$url', 'Bugzilla', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
                    644:     }
                    645:     else
                    646:     {
                    647: 	$link = $url;
                    648:     }
                    649: 
                    650:     # Add the text
                    651:     if ($text ne "")
                    652:     {
                    653: 	$template .= 
                    654:   "<table bgcolor='#AA3333' cellspacing='1' cellpadding='1' border='0'><tr>".
                    655:   "<td bgcolor='#FF5555'><a href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
                    656:     }
                    657: 
                    658:     # Add the graphic
                    659:     $template .= <<"ENDTEMPLATE";
                    660:  <a href="$link"><image src="/adm/lonMisc/smallBug.gif" border="0" alt="(Bug: $topic)" /></a>
                    661: ENDTEMPLATE
                    662:     if ($text ne '') { $template.='</td></tr></table>' };
                    663:     return $template;
                    664: 
                    665: }
                    666: 
                    667: sub help_open_faq {
                    668:     my ($topic, $text, $stayOnPage, $width, $height) = @_;
                    669:     unless ($ENV{'user.adv'}) { return ''; }
                    670:     unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }
                    671:     $text = "" if (not defined $text);
                    672:     $stayOnPage = 0 if (not defined $stayOnPage);
                    673:     if ($ENV{'browser.interface'} eq 'textual' ||
                    674: 	$ENV{'environment.remote'} eq 'off' ) {
                    675: 	$stayOnPage=1;
                    676:     }
                    677:     $width = 350 if (not defined $width);
                    678:     $height = 400 if (not defined $height);
                    679: 
                    680:     $topic=~s/\W+/\+/g;
                    681:     my $link='';
                    682:     my $template='';
                    683:     my $url=$Apache::lonnet::perlvar{'FAQHost'}.'/fom/cache/'.$topic.'.html';
                    684:     if (!$stayOnPage)
                    685:     {
                    686: 	$link = "javascript:void(open('$url', 'FAQ-O-Matic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
                    687:     }
                    688:     else
                    689:     {
                    690: 	$link = $url;
                    691:     }
                    692: 
                    693:     # Add the text
                    694:     if ($text ne "")
                    695:     {
                    696: 	$template .= 
1.173     www       697:   "<table bgcolor='#337733' cellspacing='1' cellpadding='1' border='0'><tr>".
                    698:   "<td bgcolor='#448844'><a href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
1.172     www       699:     }
                    700: 
                    701:     # Add the graphic
                    702:     $template .= <<"ENDTEMPLATE";
                    703:  <a href="$link"><image src="/adm/lonMisc/smallFAQ.gif" border="0" alt="(FAQ: $topic)" /></a>
                    704: ENDTEMPLATE
                    705:     if ($text ne '') { $template.='</td></tr></table>' };
                    706:     return $template;
                    707: 
1.44      bowersj2  708: }
1.37      matthew   709: 
1.45      matthew   710: =pod
                    711: 
1.112     bowersj2  712: =item * csv_translate($text) 
1.37      matthew   713: 
                    714: Translate $text to allow it to be output as a 'comma seperated values' 
                    715: format.
                    716: 
                    717: =cut
                    718: 
                    719: sub csv_translate {
                    720:     my $text = shift;
                    721:     $text =~ s/\"/\"\"/g;
                    722:     $text =~ s/\n//g;
                    723:     return $text;
                    724: }
1.113     bowersj2  725: 
                    726: =pod
                    727: 
                    728: =item * change_content_javascript():
                    729: 
                    730: This and the next function allow you to create small sections of an
                    731: otherwise static HTML page that you can update on the fly with
                    732: Javascript, even in Netscape 4.
                    733: 
                    734: The Javascript fragment returned by this function (no E<lt>scriptE<gt> tag)
                    735: must be written to the HTML page once. It will prove the Javascript
                    736: function "change(name, content)". Calling the change function with the
                    737: name of the section 
                    738: you want to update, matching the name passed to C<changable_area>, and
                    739: the new content you want to put in there, will put the content into
                    740: that area.
                    741: 
                    742: B<Note>: Netscape 4 only reserves enough space for the changable area
                    743: to contain room for the original contents. You need to "make space"
                    744: for whatever changes you wish to make, and be B<sure> to check your
                    745: code in Netscape 4. This feature in Netscape 4 is B<not> powerful;
                    746: it's adequate for updating a one-line status display, but little more.
                    747: This script will set the space to 100% width, so you only need to
                    748: worry about height in Netscape 4.
                    749: 
                    750: Modern browsers are much less limiting, and if you can commit to the
                    751: user not using Netscape 4, this feature may be used freely with
                    752: pretty much any HTML.
                    753: 
                    754: =cut
                    755: 
                    756: sub change_content_javascript {
                    757:     # If we're on Netscape 4, we need to use Layer-based code
                    758:     if ($ENV{'browser.type'} eq 'netscape' &&
                    759: 	$ENV{'browser.version'} =~ /^4\./) {
                    760: 	return (<<NETSCAPE4);
                    761: 	function change(name, content) {
                    762: 	    doc = document.layers[name+"___escape"].layers[0].document;
                    763: 	    doc.open();
                    764: 	    doc.write(content);
                    765: 	    doc.close();
                    766: 	}
                    767: NETSCAPE4
                    768:     } else {
                    769: 	# Otherwise, we need to use semi-standards-compliant code
                    770: 	# (technically, "innerHTML" isn't standard but the equivalent
                    771: 	# is really scary, and every useful browser supports it
                    772: 	return (<<DOMBASED);
                    773: 	function change(name, content) {
                    774: 	    element = document.getElementById(name);
                    775: 	    element.innerHTML = content;
                    776: 	}
                    777: DOMBASED
                    778:     }
                    779: }
                    780: 
                    781: =pod
                    782: 
                    783: =item * changable_area($name, $origContent):
                    784: 
                    785: This provides a "changable area" that can be modified on the fly via
                    786: the Javascript code provided in C<change_content_javascript>. $name is
                    787: the name you will use to reference the area later; do not repeat the
                    788: same name on a given HTML page more then once. $origContent is what
                    789: the area will originally contain, which can be left blank.
                    790: 
                    791: =cut
                    792: 
                    793: sub changable_area {
                    794:     my ($name, $origContent) = @_;
                    795: 
                    796:     if ($ENV{'browser.type'} eq 'netscape' &&
                    797: 	$ENV{'browser.version'} =~ /^4\./) {
                    798: 	# If this is netscape 4, we need to use the Layer tag
                    799: 	return "<ilayer width='100%' id='${name}___escape' overflow='none'><layer width='100%' id='$name' overflow='none'>$origContent</layer></ilayer>";
                    800:     } else {
                    801: 	return "<span id='$name'>$origContent</span>";
                    802:     }
                    803: }
                    804: 
                    805: =pod
                    806: 
                    807: =back
                    808: 
                    809: =cut
1.37      matthew   810: 
                    811: ###############################################################
1.33      matthew   812: ##        Home server <option> list generating code          ##
                    813: ###############################################################
1.35      matthew   814: 
1.45      matthew   815: =pod
                    816: 
1.112     bowersj2  817: =head1 Home Server option list generating code
                    818: 
                    819: =over 4
                    820: 
                    821: =item * get_domains()
1.35      matthew   822: 
                    823: Returns an array containing each of the domains listed in the hosts.tab
                    824: file.
                    825: 
                    826: =cut
                    827: 
                    828: #-------------------------------------------
1.34      matthew   829: sub get_domains {
                    830:     # The code below was stolen from "The Perl Cookbook", p 102, 1st ed.
                    831:     my @domains;
                    832:     my %seen;
                    833:     foreach (sort values(%Apache::lonnet::hostdom)) {
1.169     www       834: 	push (@domains,$_) unless $seen{$_}++;
1.34      matthew   835:     }
                    836:     return @domains;
                    837: }
1.88      www       838: 
1.169     www       839: # ------------------------------------------
                    840: 
                    841: sub domain_select {
                    842:     my ($name,$value,$multiple)=@_;
                    843:     my %domains=map { 
                    844: 	$_ => $_.' '.$Apache::lonnet::domaindescription{$_} 
                    845:     } &get_domains;
                    846:     if ($multiple) {
                    847: 	$domains{''}=&mt('Any domain');
                    848: 	return &multiple_select_form($name,$value,%domains);
                    849:     } else {
                    850: 	return &select_form($name,$value,%domains);
                    851:     }
                    852: }
                    853: 
                    854: sub multiple_select_form {
                    855:     my ($name,$value,%hash)=@_;
                    856:     my %selected = map { $_ => 1 } ref($value)?@{$value}:($value);
                    857:     my $output='';
                    858:     my $size =(scalar keys %hash<4?scalar keys %hash:4);
                    859:     $output.="\n<select name='$name' size='$size' multiple='1'>";
                    860:     foreach (sort keys %hash) {
                    861:         $output.="<option name='$_'".
                    862:             ($selected{$_}?' selected="1"' :'').">$hash{$_}</option>\n";
                    863:     }
                    864:     $output.="</select>\n";
                    865:     return $output;
                    866: }
                    867: 
1.88      www       868: #-------------------------------------------
                    869: 
                    870: =pod
                    871: 
1.112     bowersj2  872: =item * select_form($defdom,$name,%hash)
1.88      www       873: 
                    874: Returns a string containing a <select name='$name' size='1'> form to 
                    875: allow a user to select options from a hash option_name => displayed text.  
                    876: See lonrights.pm for an example invocation and use.
                    877: 
                    878: =cut
                    879: 
                    880: #-------------------------------------------
                    881: sub select_form {
                    882:     my ($def,$name,%hash) = @_;
                    883:     my $selectform = "<select name=\"$name\" size=\"1\">\n";
1.128     albertel  884:     my @keys;
                    885:     if (exists($hash{'select_form_order'})) {
                    886: 	@keys=@{$hash{'select_form_order'}};
                    887:     } else {
                    888: 	@keys=sort(keys(%hash));
                    889:     }
                    890:     foreach (@keys) {
1.88      www       891:         $selectform.="<option value=\"$_\" ".
                    892:             ($_ eq $def ? 'selected' : '').
1.119     www       893:                 ">".&mt($hash{$_})."</option>\n";
1.88      www       894:     }
                    895:     $selectform.="</select>";
                    896:     return $selectform;
                    897: }
                    898: 
1.167     www       899: sub gradeleveldescription {
                    900:     my $gradelevel=shift;
                    901:     my %gradelevels=(0 => 'Not specified',
                    902: 		     1 => 'Grade 1',
                    903: 		     2 => 'Grade 2',
                    904: 		     3 => 'Grade 3',
                    905: 		     4 => 'Grade 4',
                    906: 		     5 => 'Grade 5',
                    907: 		     6 => 'Grade 6',
                    908: 		     7 => 'Grade 7',
                    909: 		     8 => 'Grade 8',
                    910: 		     9 => 'Grade 9',
                    911: 		     10 => 'Grade 10',
                    912: 		     11 => 'Grade 11',
                    913: 		     12 => 'Grade 12',
                    914: 		     13 => 'Grade 13',
                    915: 		     14 => '100 Level',
                    916: 		     15 => '200 Level',
                    917: 		     16 => '300 Level',
                    918: 		     17 => '400 Level',
                    919: 		     18 => 'Graduate Level');
                    920:     return &mt($gradelevels{$gradelevel});
                    921: }
                    922: 
1.163     www       923: sub select_level_form {
                    924:     my ($deflevel,$name)=@_;
                    925:     unless ($deflevel) { $deflevel=0; }
1.167     www       926:     my $selectform = "<select name=\"$name\" size=\"1\">\n";
                    927:     for (my $i=0; $i<=18; $i++) {
                    928:         $selectform.="<option value=\"$i\" ".
                    929:             ($i==$deflevel ? 'selected' : '').
                    930:                 ">".&gradeleveldescription($i)."</option>\n";
                    931:     }
                    932:     $selectform.="</select>";
                    933:     return $selectform;
1.163     www       934: }
1.167     www       935: 
1.35      matthew   936: #-------------------------------------------
                    937: 
1.45      matthew   938: =pod
                    939: 
1.112     bowersj2  940: =item * select_dom_form($defdom,$name,$includeempty)
1.35      matthew   941: 
                    942: Returns a string containing a <select name='$name' size='1'> form to 
                    943: allow a user to select the domain to preform an operation in.  
                    944: See loncreateuser.pm for an example invocation and use.
                    945: 
1.90      www       946: If the $includeempty flag is set, it also includes an empty choice ("no domain
                    947: selected");
                    948: 
1.35      matthew   949: =cut
                    950: 
                    951: #-------------------------------------------
1.34      matthew   952: sub select_dom_form {
1.90      www       953:     my ($defdom,$name,$includeempty) = @_;
1.34      matthew   954:     my @domains = get_domains();
1.90      www       955:     if ($includeempty) { @domains=('',@domains); }
1.34      matthew   956:     my $selectdomain = "<select name=\"$name\" size=\"1\">\n";
                    957:     foreach (@domains) {
                    958:         $selectdomain.="<option value=\"$_\" ".
                    959:             ($_ eq $defdom ? 'selected' : '').
                    960:                 ">$_</option>\n";
                    961:     }
                    962:     $selectdomain.="</select>";
                    963:     return $selectdomain;
                    964: }
                    965: 
1.35      matthew   966: #-------------------------------------------
                    967: 
1.45      matthew   968: =pod
                    969: 
1.112     bowersj2  970: =item * get_library_servers($domain)
1.35      matthew   971: 
                    972: Returns a hash which contains keys like '103l3' and values like 
                    973: 'kirk.lite.msu.edu'.  All of the keys will be for machines in the
                    974: given $domain.
                    975: 
                    976: =cut
                    977: 
                    978: #-------------------------------------------
1.52      matthew   979: sub get_library_servers {
1.33      matthew   980:     my $domain = shift;
1.52      matthew   981:     my %library_servers;
1.33      matthew   982:     foreach (keys(%Apache::lonnet::libserv)) {
                    983:         if ($Apache::lonnet::hostdom{$_} eq $domain) {
1.52      matthew   984:             $library_servers{$_} = $Apache::lonnet::hostname{$_};
1.33      matthew   985:         }
                    986:     }
1.52      matthew   987:     return %library_servers;
1.33      matthew   988: }
                    989: 
1.35      matthew   990: #-------------------------------------------
                    991: 
1.45      matthew   992: =pod
                    993: 
1.112     bowersj2  994: =item * home_server_option_list($domain)
1.35      matthew   995: 
                    996: returns a string which contains an <option> list to be used in a 
                    997: <select> form input.  See loncreateuser.pm for an example.
                    998: 
                    999: =cut
                   1000: 
                   1001: #-------------------------------------------
1.33      matthew  1002: sub home_server_option_list {
                   1003:     my $domain = shift;
1.52      matthew  1004:     my %servers = &get_library_servers($domain);
1.33      matthew  1005:     my $result = '';
                   1006:     foreach (sort keys(%servers)) {
                   1007:         $result.=
                   1008:             '<option value="'.$_.'">'.$_.' '.$servers{$_}."</option>\n";
                   1009:     }
                   1010:     return $result;
                   1011: }
1.112     bowersj2 1012: 
                   1013: =pod
                   1014: 
                   1015: =back
                   1016: 
                   1017: =cut
1.87      matthew  1018: 
                   1019: ###############################################################
1.112     bowersj2 1020: ##                  Decoding User Agent                      ##
1.87      matthew  1021: ###############################################################
                   1022: 
                   1023: =pod
                   1024: 
1.112     bowersj2 1025: =head1 Decoding the User Agent
                   1026: 
                   1027: =over 4
                   1028: 
                   1029: =item * &decode_user_agent()
1.87      matthew  1030: 
                   1031: Inputs: $r
                   1032: 
                   1033: Outputs:
                   1034: 
                   1035: =over 4
                   1036: 
1.112     bowersj2 1037: =item * $httpbrowser
1.87      matthew  1038: 
1.112     bowersj2 1039: =item * $clientbrowser
1.87      matthew  1040: 
1.112     bowersj2 1041: =item * $clientversion
1.87      matthew  1042: 
1.112     bowersj2 1043: =item * $clientmathml
1.87      matthew  1044: 
1.112     bowersj2 1045: =item * $clientunicode
1.87      matthew  1046: 
1.112     bowersj2 1047: =item * $clientos
1.87      matthew  1048: 
                   1049: =back
                   1050: 
1.157     matthew  1051: =back 
                   1052: 
1.87      matthew  1053: =cut
                   1054: 
                   1055: ###############################################################
                   1056: ###############################################################
                   1057: sub decode_user_agent {
                   1058:     my @browsertype=split(/\&/,$Apache::lonnet::perlvar{"lonBrowsDet"});
                   1059:     my %mathcap=split(/\&/,$$Apache::lonnet::perlvar{"lonMathML"});
                   1060:     my $httpbrowser=$ENV{"HTTP_USER_AGENT"};
                   1061:     my $clientbrowser='unknown';
                   1062:     my $clientversion='0';
                   1063:     my $clientmathml='';
                   1064:     my $clientunicode='0';
                   1065:     for (my $i=0;$i<=$#browsertype;$i++) {
                   1066:         my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\:/,$browsertype[$i]);
                   1067: 	if (($httpbrowser=~/$match/i)  && ($httpbrowser!~/$notmatch/i)) {
                   1068: 	    $clientbrowser=$bname;
                   1069:             $httpbrowser=~/$vreg/i;
                   1070: 	    $clientversion=$1;
                   1071:             $clientmathml=($clientversion>=$minv);
                   1072:             $clientunicode=($clientversion>=$univ);
                   1073: 	}
                   1074:     }
                   1075:     my $clientos='unknown';
                   1076:     if (($httpbrowser=~/linux/i) ||
                   1077:         ($httpbrowser=~/unix/i) ||
                   1078:         ($httpbrowser=~/ux/i) ||
                   1079:         ($httpbrowser=~/solaris/i)) { $clientos='unix'; }
                   1080:     if (($httpbrowser=~/vax/i) ||
                   1081:         ($httpbrowser=~/vms/i)) { $clientos='vms'; }
                   1082:     if ($httpbrowser=~/next/i) { $clientos='next'; }
                   1083:     if (($httpbrowser=~/mac/i) ||
                   1084:         ($httpbrowser=~/powerpc/i)) { $clientos='mac'; }
                   1085:     if ($httpbrowser=~/win/i) { $clientos='win'; }
                   1086:     if ($httpbrowser=~/embed/i) { $clientos='pda'; }
                   1087:     return ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
                   1088:             $clientunicode,$clientos,);
                   1089: }
                   1090: 
1.32      matthew  1091: ###############################################################
                   1092: ##    Authentication changing form generation subroutines    ##
                   1093: ###############################################################
                   1094: ##
                   1095: ## All of the authform_xxxxxxx subroutines take their inputs in a
                   1096: ## hash, and have reasonable default values.
                   1097: ##
                   1098: ##    formname = the name given in the <form> tag.
1.35      matthew  1099: #-------------------------------------------
                   1100: 
1.45      matthew  1101: =pod
                   1102: 
1.112     bowersj2 1103: =head1 Authentication Routines
                   1104: 
                   1105: =over 4
                   1106: 
                   1107: =item * authform_xxxxxx
1.35      matthew  1108: 
                   1109: The authform_xxxxxx subroutines provide javascript and html forms which 
                   1110: handle some of the conveniences required for authentication forms.  
                   1111: This is not an optimal method, but it works.  
                   1112: 
                   1113: See loncreateuser.pm for invocation and use examples.
                   1114: 
                   1115: =over 4
                   1116: 
1.112     bowersj2 1117: =item * authform_header
1.35      matthew  1118: 
1.112     bowersj2 1119: =item * authform_authorwarning
1.35      matthew  1120: 
1.112     bowersj2 1121: =item * authform_nochange
1.35      matthew  1122: 
1.112     bowersj2 1123: =item * authform_kerberos
1.35      matthew  1124: 
1.112     bowersj2 1125: =item * authform_internal
1.35      matthew  1126: 
1.112     bowersj2 1127: =item * authform_filesystem
1.35      matthew  1128: 
                   1129: =back
                   1130: 
1.157     matthew  1131: =back 
                   1132: 
1.35      matthew  1133: =cut
                   1134: 
                   1135: #-------------------------------------------
1.32      matthew  1136: sub authform_header{  
                   1137:     my %in = (
                   1138:         formname => 'cu',
1.80      albertel 1139:         kerb_def_dom => '',
1.32      matthew  1140:         @_,
                   1141:     );
                   1142:     $in{'formname'} = 'document.' . $in{'formname'};
                   1143:     my $result='';
1.80      albertel 1144: 
                   1145: #---------------------------------------------- Code for upper case translation
                   1146:     my $Javascript_toUpperCase;
                   1147:     unless ($in{kerb_def_dom}) {
                   1148:         $Javascript_toUpperCase =<<"END";
                   1149:         switch (choice) {
                   1150:            case 'krb': currentform.elements[choicearg].value =
                   1151:                currentform.elements[choicearg].value.toUpperCase();
                   1152:                break;
                   1153:            default:
                   1154:         }
                   1155: END
                   1156:     } else {
                   1157:         $Javascript_toUpperCase = "";
                   1158:     }
                   1159: 
1.165     raeburn  1160:     my $radioval = "'nochange'";
1.174   ! matthew  1161:     if (exists($in{'curr_authtype'}) &&
        !          1162:         defined($in{'curr_authtype'}) &&
        !          1163:         $in{'curr_authtype'} ne '') {
        !          1164:         $radioval = "'$in{'curr_authtype'}arg'";
        !          1165:     }
1.165     raeburn  1166:     my $argfield = 'null';
                   1167:     if ( grep/^mode$/,(keys %in) ) {
                   1168:         if ($in{'mode'} eq 'modifycourse')  {
                   1169:             if ( grep/^curr_authtype$/,(keys %in) ) {
                   1170:                 $radioval = "'$in{'curr_authtype'}'";
                   1171:             }
                   1172:             if ( grep/^curr_autharg$/,(keys %in) ) {
                   1173:                 unless ($in{'curr_autharg'} eq '') {
                   1174:                     $argfield = "'$in{'curr_autharg'}'";
                   1175:                 }
                   1176:             }
                   1177:         }
                   1178:     }
                   1179: 
1.32      matthew  1180:     $result.=<<"END";
                   1181: var current = new Object();
1.165     raeburn  1182: current.radiovalue = $radioval;
                   1183: current.argfield = $argfield;
1.32      matthew  1184: 
                   1185: function changed_radio(choice,currentform) {
                   1186:     var choicearg = choice + 'arg';
                   1187:     // If a radio button in changed, we need to change the argfield
                   1188:     if (current.radiovalue != choice) {
                   1189:         current.radiovalue = choice;
                   1190:         if (current.argfield != null) {
                   1191:             currentform.elements[current.argfield].value = '';
                   1192:         }
                   1193:         if (choice == 'nochange') {
                   1194:             current.argfield = null;
                   1195:         } else {
                   1196:             current.argfield = choicearg;
                   1197:             switch(choice) {
                   1198:                 case 'krb': 
                   1199:                     currentform.elements[current.argfield].value = 
                   1200:                         "$in{'kerb_def_dom'}";
                   1201:                 break;
                   1202:               default:
                   1203:                 break;
                   1204:             }
                   1205:         }
                   1206:     }
                   1207:     return;
                   1208: }
1.22      www      1209: 
1.32      matthew  1210: function changed_text(choice,currentform) {
                   1211:     var choicearg = choice + 'arg';
                   1212:     if (currentform.elements[choicearg].value !='') {
1.80      albertel 1213:         $Javascript_toUpperCase
1.32      matthew  1214:         // clear old field
                   1215:         if ((current.argfield != choicearg) && (current.argfield != null)) {
                   1216:             currentform.elements[current.argfield].value = '';
                   1217:         }
                   1218:         current.argfield = choicearg;
                   1219:     }
                   1220:     set_auth_radio_buttons(choice,currentform);
                   1221:     return;
1.20      www      1222: }
1.32      matthew  1223: 
                   1224: function set_auth_radio_buttons(newvalue,currentform) {
                   1225:     var i=0;
                   1226:     while (i < currentform.login.length) {
                   1227:         if (currentform.login[i].value == newvalue) { break; }
                   1228:         i++;
                   1229:     }
                   1230:     if (i == currentform.login.length) {
                   1231:         return;
                   1232:     }
                   1233:     current.radiovalue = newvalue;
                   1234:     currentform.login[i].checked = true;
                   1235:     return;
                   1236: }
                   1237: END
                   1238:     return $result;
                   1239: }
                   1240: 
                   1241: sub authform_authorwarning{
                   1242:     my $result='';
1.144     matthew  1243:     $result='<i>'.
                   1244:         &mt('As a general rule, only authors or co-authors should be '.
                   1245:             'filesystem authenticated '.
                   1246:             '(which allows access to the server filesystem).')."</i>\n";
1.32      matthew  1247:     return $result;
                   1248: }
                   1249: 
                   1250: sub authform_nochange{  
                   1251:     my %in = (
                   1252:               formname => 'document.cu',
                   1253:               kerb_def_dom => 'MSU.EDU',
                   1254:               @_,
                   1255:           );
1.144     matthew  1256:     my $result = &mt('[_1] Do not change login data',
                   1257:                      '<input type="radio" name="login" value="nochange" '.
                   1258:                      'checked="checked" onclick="'.
                   1259:             "javascript:changed_radio('nochange',$in{'formname'});".'" />');
1.32      matthew  1260:     return $result;
                   1261: }
                   1262: 
                   1263: sub authform_kerberos{  
                   1264:     my %in = (
                   1265:               formname => 'document.cu',
                   1266:               kerb_def_dom => 'MSU.EDU',
1.80      albertel 1267:               kerb_def_auth => 'krb4',
1.32      matthew  1268:               @_,
                   1269:               );
1.165     raeburn  1270:     my ($check4,$check5,$krbarg);
1.80      albertel 1271:     if ($in{'kerb_def_auth'} eq 'krb5') {
                   1272:        $check5 = " checked=\"on\"";
                   1273:     } else {
                   1274:        $check4 = " checked=\"on\"";
                   1275:     }
1.165     raeburn  1276:     $krbarg = $in{'kerb_def_dom'};
                   1277: 
                   1278:     my $krbcheck = "";
                   1279:     if ( grep/^curr_authtype$/,(keys %in) ) {
                   1280:         if ($in{'curr_authtype'} =~ m/^krb/) {
                   1281:             $krbcheck = " checked=\"on\"";
                   1282:             if ( grep/^curr_autharg$/,(keys %in) ) {
                   1283:                 $krbarg = $in{'curr_autharg'};
                   1284:             }
                   1285:         }
                   1286:     }
                   1287: 
1.144     matthew  1288:     my $jscall = "javascript:changed_radio('krb',$in{'formname'});";
                   1289:     my $result .= &mt
                   1290:         ('[_1] Kerberos authenticated with domain [_2] '.
                   1291:          '[_3] Version 4 [_4] Version 5',
                   1292:          '<input type="radio" name="login" value="krb" '.
1.165     raeburn  1293:              'onclick="'.$jscall.'" onchange="'.$jscall.'"'.$krbcheck.' />',
1.144     matthew  1294:          '<input type="text" size="10" name="krbarg" '.
1.165     raeburn  1295:              'value="'.$krbarg.'" '.
1.144     matthew  1296:              'onchange="'.$jscall.'" />',
                   1297:          '<input type="radio" name="krbver" value="4" '.$check4.' />',
                   1298:          '<input type="radio" name="krbver" value="5" '.$check5.' />');
1.32      matthew  1299:     return $result;
                   1300: }
                   1301: 
                   1302: sub authform_internal{  
                   1303:     my %args = (
                   1304:                 formname => 'document.cu',
                   1305:                 kerb_def_dom => 'MSU.EDU',
                   1306:                 @_,
                   1307:                 );
1.165     raeburn  1308: 
                   1309:     my $intcheck = "";
                   1310:     my $intarg = 'value=""';
                   1311:     if ( grep/^curr_authtype$/,(keys %args) ) {
                   1312:         if ($args{'curr_authtype'} eq 'int') {
                   1313:             $intcheck = " checked=\"on\"";
                   1314:             if ( grep/^curr_autharg$/,(keys %args) ) {
                   1315:                 $intarg = "value=\"$args{'curr_autharg'}\"";
                   1316:             }
                   1317:         }
                   1318:     }
                   1319: 
1.144     matthew  1320:     my $jscall = "javascript:changed_radio('int',$args{'formname'});";
                   1321:     my $result.=&mt
                   1322:         ('[_1] Internally authenticated (with initial password [_2])',
1.165     raeburn  1323:          '<input type="radio" name="login" value="int" '.$intcheck.
                   1324:              ' onchange="'.$jscall.'" onclick="'.$jscall.'" />',
                   1325:          '<input type="text" size="10" name="intarg" '.$intarg.
                   1326:              ' onchange="'.$jscall.'" />');
1.32      matthew  1327:     return $result;
                   1328: }
                   1329: 
                   1330: sub authform_local{  
                   1331:     my %in = (
                   1332:               formname => 'document.cu',
                   1333:               kerb_def_dom => 'MSU.EDU',
                   1334:               @_,
                   1335:               );
1.165     raeburn  1336: 
                   1337:     my $loccheck = "";
                   1338:     my $locarg = 'value=""';
                   1339:     if ( grep/^curr_authtype$/,(keys %in) ) {
                   1340:         if ($in{'curr_authtype'} eq 'loc') {
                   1341:             $loccheck = " checked=\"on\"";
                   1342:             if ( grep/^curr_autharg$/,(keys %in) ) {
                   1343:                 $locarg = "value=\"$in{'curr_autharg'}\"";
                   1344:             }
                   1345:         }
                   1346:     }
                   1347: 
1.144     matthew  1348:     my $jscall = "javascript:changed_radio('loc',$in{'formname'});";
1.160     matthew  1349:     my $result.=&mt('[_1] Local Authentication with argument [_2]',
1.165     raeburn  1350:                     '<input type="radio" name="login" value="loc" '.$loccheck.
                   1351:                         ' onchange="'.$jscall.'" onclick="'.$jscall.'" />',
                   1352:                     '<input type="text" size="10" name="locarg" '.$locarg.
                   1353:                         ' onchange="'.$jscall.'" />');
1.32      matthew  1354:     return $result;
                   1355: }
                   1356: 
                   1357: sub authform_filesystem{  
                   1358:     my %in = (
                   1359:               formname => 'document.cu',
                   1360:               kerb_def_dom => 'MSU.EDU',
                   1361:               @_,
                   1362:               );
1.144     matthew  1363:     my $jscall = "javascript:changed_radio('fsys',$in{'formname'});";
                   1364:     my $result.= &mt
                   1365:         ('[_1] Filesystem Authenticated (with initial password [_2])',
                   1366:          '<input type="radio" name="login" value="fsys" '.
                   1367:          'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
                   1368:          '<input type="text" size="10" name="fsysarg" value="" '.
                   1369:                   'onchange="'.$jscall.'" />');
1.32      matthew  1370:     return $result;
                   1371: }
                   1372: 
1.80      albertel 1373: ###############################################################
                   1374: ##    Get Authentication Defaults for Domain                 ##
                   1375: ###############################################################
                   1376: 
                   1377: =pod
                   1378: 
1.112     bowersj2 1379: =head1 Domains and Authentication
                   1380: 
                   1381: Returns default authentication type and an associated argument as
                   1382: listed in file 'domain.tab'.
                   1383: 
                   1384: =over 4
                   1385: 
                   1386: =item * get_auth_defaults
1.80      albertel 1387: 
                   1388: get_auth_defaults($target_domain) returns the default authentication
                   1389: type and an associated argument (initial password or a kerberos domain).
                   1390: These values are stored in lonTabs/domain.tab
                   1391: 
                   1392: ($def_auth, $def_arg) = &get_auth_defaults($target_domain);
                   1393: 
                   1394: If target_domain is not found in domain.tab, returns nothing ('').
                   1395: 
                   1396: =cut
                   1397: 
                   1398: #-------------------------------------------
                   1399: sub get_auth_defaults {
                   1400:     my $domain=shift;
                   1401:     return ($Apache::lonnet::domain_auth_def{$domain},$Apache::lonnet::domain_auth_arg_def{$domain});
                   1402: }
                   1403: ###############################################################
                   1404: ##   End Get Authentication Defaults for Domain              ##
                   1405: ###############################################################
                   1406: 
                   1407: ###############################################################
                   1408: ##    Get Kerberos Defaults for Domain                 ##
                   1409: ###############################################################
                   1410: ##
                   1411: ## Returns default kerberos version and an associated argument
                   1412: ## as listed in file domain.tab. If not listed, provides
                   1413: ## appropriate default domain and kerberos version.
                   1414: ##
                   1415: #-------------------------------------------
                   1416: 
                   1417: =pod
                   1418: 
1.112     bowersj2 1419: =item * get_kerberos_defaults
1.80      albertel 1420: 
                   1421: get_kerberos_defaults($target_domain) returns the default kerberos
                   1422: version and domain. If not found in domain.tabs, it defaults to
                   1423: version 4 and the domain of the server.
                   1424: 
                   1425: ($def_version, $def_krb_domain) = &get_kerberos_defaults($target_domain);
                   1426: 
                   1427: =cut
                   1428: 
                   1429: #-------------------------------------------
                   1430: sub get_kerberos_defaults {
                   1431:     my $domain=shift;
                   1432:     my ($krbdef,$krbdefdom) =
                   1433:         &Apache::loncommon::get_auth_defaults($domain);
                   1434:     unless ($krbdef =~/^krb/ && $krbdefdom) {
                   1435:         $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/;
                   1436:         my $krbdefdom=$1;
                   1437:         $krbdefdom=~tr/a-z/A-Z/;
                   1438:         $krbdef = "krb4";
                   1439:     }
                   1440:     return ($krbdef,$krbdefdom);
                   1441: }
1.112     bowersj2 1442: 
                   1443: =pod
                   1444: 
                   1445: =back
                   1446: 
                   1447: =cut
1.32      matthew  1448: 
1.46      matthew  1449: ###############################################################
                   1450: ##                Thesaurus Functions                        ##
                   1451: ###############################################################
1.20      www      1452: 
1.46      matthew  1453: =pod
1.20      www      1454: 
1.112     bowersj2 1455: =head1 Thesaurus Functions
                   1456: 
                   1457: =over 4
                   1458: 
                   1459: =item * initialize_keywords
1.46      matthew  1460: 
                   1461: Initializes the package variable %Keywords if it is empty.  Uses the
                   1462: package variable $thesaurus_db_file.
                   1463: 
                   1464: =cut
                   1465: 
                   1466: ###################################################
                   1467: 
                   1468: sub initialize_keywords {
                   1469:     return 1 if (scalar keys(%Keywords));
                   1470:     # If we are here, %Keywords is empty, so fill it up
                   1471:     #   Make sure the file we need exists...
                   1472:     if (! -e $thesaurus_db_file) {
                   1473:         &Apache::lonnet::logthis("Attempt to access $thesaurus_db_file".
                   1474:                                  " failed because it does not exist");
                   1475:         return 0;
                   1476:     }
                   1477:     #   Set up the hash as a database
                   1478:     my %thesaurus_db;
                   1479:     if (! tie(%thesaurus_db,'GDBM_File',
1.53      albertel 1480:               $thesaurus_db_file,&GDBM_READER(),0640)){
1.46      matthew  1481:         &Apache::lonnet::logthis("Could not tie \%thesaurus_db to ".
                   1482:                                  $thesaurus_db_file);
                   1483:         return 0;
                   1484:     } 
                   1485:     #  Get the average number of appearances of a word.
                   1486:     my $avecount = $thesaurus_db{'average.count'};
                   1487:     #  Put keywords (those that appear > average) into %Keywords
                   1488:     while (my ($word,$data)=each (%thesaurus_db)) {
                   1489:         my ($count,undef) = split /:/,$data;
                   1490:         $Keywords{$word}++ if ($count > $avecount);
                   1491:     }
                   1492:     untie %thesaurus_db;
                   1493:     # Remove special values from %Keywords.
                   1494:     foreach ('total.count','average.count') {
                   1495:         delete($Keywords{$_}) if (exists($Keywords{$_}));
                   1496:     }
                   1497:     return 1;
                   1498: }
                   1499: 
                   1500: ###################################################
                   1501: 
                   1502: =pod
                   1503: 
1.112     bowersj2 1504: =item * keyword($word)
1.46      matthew  1505: 
                   1506: Returns true if $word is a keyword.  A keyword is a word that appears more 
                   1507: than the average number of times in the thesaurus database.  Calls 
                   1508: &initialize_keywords
                   1509: 
                   1510: =cut
                   1511: 
                   1512: ###################################################
1.20      www      1513: 
                   1514: sub keyword {
1.46      matthew  1515:     return if (!&initialize_keywords());
                   1516:     my $word=lc(shift());
                   1517:     $word=~s/\W//g;
                   1518:     return exists($Keywords{$word});
1.20      www      1519: }
1.46      matthew  1520: 
                   1521: ###############################################################
                   1522: 
                   1523: =pod 
1.20      www      1524: 
1.112     bowersj2 1525: =item * get_related_words
1.46      matthew  1526: 
1.160     matthew  1527: Look up a word in the thesaurus.  Takes a scalar argument and returns
1.46      matthew  1528: an array of words.  If the keyword is not in the thesaurus, an empty array
                   1529: will be returned.  The order of the words returned is determined by the
                   1530: database which holds them.
                   1531: 
                   1532: Uses global $thesaurus_db_file.
                   1533: 
                   1534: =cut
                   1535: 
                   1536: ###############################################################
                   1537: sub get_related_words {
                   1538:     my $keyword = shift;
                   1539:     my %thesaurus_db;
                   1540:     if (! -e $thesaurus_db_file) {
                   1541:         &Apache::lonnet::logthis("Attempt to access $thesaurus_db_file ".
                   1542:                                  "failed because the file does not exist");
                   1543:         return ();
                   1544:     }
                   1545:     if (! tie(%thesaurus_db,'GDBM_File',
1.53      albertel 1546:               $thesaurus_db_file,&GDBM_READER(),0640)){
1.46      matthew  1547:         return ();
                   1548:     } 
                   1549:     my @Words=();
                   1550:     if (exists($thesaurus_db{$keyword})) {
                   1551:         $_ = $thesaurus_db{$keyword};
                   1552:         (undef,@Words) = split/:/;  # The first element is the number of times
                   1553:                                     # the word appears.  We do not need it now.
                   1554:         for (my $i=0;$i<=$#Words;$i++) {
                   1555:             ($Words[$i],undef)= split/\,/,$Words[$i];
1.20      www      1556:         }
                   1557:     }
1.46      matthew  1558:     untie %thesaurus_db;
                   1559:     return @Words;
1.14      harris41 1560: }
1.46      matthew  1561: 
1.112     bowersj2 1562: =pod
                   1563: 
                   1564: =back
                   1565: 
                   1566: =cut
1.61      www      1567: 
                   1568: # -------------------------------------------------------------- Plaintext name
1.81      albertel 1569: =pod
                   1570: 
1.112     bowersj2 1571: =head1 User Name Functions
                   1572: 
                   1573: =over 4
                   1574: 
                   1575: =item * plainname($uname,$udom)
1.81      albertel 1576: 
1.112     bowersj2 1577: Takes a users logon name and returns it as a string in
                   1578: "first middle last generation" form
1.81      albertel 1579: 
                   1580: =cut
1.61      www      1581: 
1.81      albertel 1582: ###############################################################
1.61      www      1583: sub plainname {
                   1584:     my ($uname,$udom)=@_;
                   1585:     my %names=&Apache::lonnet::get('environment',
                   1586:                     ['firstname','middlename','lastname','generation'],
                   1587: 					 $udom,$uname);
1.62      www      1588:     my $name=$names{'firstname'}.' '.$names{'middlename'}.' '.
1.61      www      1589: 	$names{'lastname'}.' '.$names{'generation'};
1.62      www      1590:     $name=~s/\s+$//;
                   1591:     $name=~s/\s+/ /g;
                   1592:     return $name;
1.61      www      1593: }
1.66      www      1594: 
                   1595: # -------------------------------------------------------------------- Nickname
1.81      albertel 1596: =pod
                   1597: 
1.112     bowersj2 1598: =item * nickname($uname,$udom)
1.81      albertel 1599: 
                   1600: Gets a users name and returns it as a string as
                   1601: 
                   1602: "&quot;nickname&quot;"
1.66      www      1603: 
1.81      albertel 1604: if the user has a nickname or
                   1605: 
                   1606: "first middle last generation"
                   1607: 
                   1608: if the user does not
                   1609: 
                   1610: =cut
1.66      www      1611: 
                   1612: sub nickname {
                   1613:     my ($uname,$udom)=@_;
                   1614:     my %names=&Apache::lonnet::get('environment',
                   1615:   ['nickname','firstname','middlename','lastname','generation'],$udom,$uname);
1.68      albertel 1616:     my $name=$names{'nickname'};
1.66      www      1617:     if ($name) {
                   1618:        $name='&quot;'.$name.'&quot;'; 
                   1619:     } else {
                   1620:        $name=$names{'firstname'}.' '.$names{'middlename'}.' '.
                   1621: 	     $names{'lastname'}.' '.$names{'generation'};
                   1622:        $name=~s/\s+$//;
                   1623:        $name=~s/\s+/ /g;
                   1624:     }
                   1625:     return $name;
                   1626: }
                   1627: 
1.61      www      1628: 
                   1629: # ------------------------------------------------------------------ Screenname
1.81      albertel 1630: 
                   1631: =pod
                   1632: 
1.112     bowersj2 1633: =item * screenname($uname,$udom)
1.81      albertel 1634: 
                   1635: Gets a users screenname and returns it as a string
                   1636: 
                   1637: =cut
1.61      www      1638: 
                   1639: sub screenname {
                   1640:     my ($uname,$udom)=@_;
                   1641:     my %names=
                   1642:  &Apache::lonnet::get('environment',['screenname'],$udom,$uname);
1.68      albertel 1643:     return $names{'screenname'};
1.62      www      1644: }
                   1645: 
                   1646: # ------------------------------------------------------------- Message Wrapper
                   1647: 
                   1648: sub messagewrapper {
                   1649:     my ($link,$un,$do)=@_;
                   1650:     return 
                   1651: "<a href='/adm/email?compose=individual&recname=$un&recdom=$do'>$link</a>";
1.74      www      1652: }
                   1653: # --------------------------------------------------------------- Notes Wrapper
                   1654: 
                   1655: sub noteswrapper {
                   1656:     my ($link,$un,$do)=@_;
                   1657:     return 
                   1658: "<a href='/adm/email?recordftf=retrieve&recname=$un&recdom=$do'>$link</a>";
1.62      www      1659: }
                   1660: # ------------------------------------------------------------- Aboutme Wrapper
                   1661: 
                   1662: sub aboutmewrapper {
1.166     www      1663:     my ($link,$username,$domain,$target)=@_;
                   1664:     return "<a href='/adm/$domain/$username/aboutme'".
                   1665: 	($target?" target='$target'":'').">$link</a>";
1.62      www      1666: }
                   1667: 
                   1668: # ------------------------------------------------------------ Syllabus Wrapper
                   1669: 
                   1670: 
                   1671: sub syllabuswrapper {
1.109     matthew  1672:     my ($linktext,$coursedir,$domain,$fontcolor)=@_;
                   1673:     if ($fontcolor) { 
                   1674:         $linktext='<font color="'.$fontcolor.'">'.$linktext.'</font>'; 
                   1675:     }
                   1676:     return "<a href='/public/$domain/$coursedir/syllabus'>$linktext</a>";
1.61      www      1677: }
1.14      harris41 1678: 
1.112     bowersj2 1679: =pod
                   1680: 
                   1681: =back
                   1682: 
                   1683: =head1 Access .tab File Data
                   1684: 
                   1685: =over 4
                   1686: 
                   1687: =item * languageids() 
                   1688: 
                   1689: returns list of all language ids
                   1690: 
                   1691: =cut
                   1692: 
1.14      harris41 1693: sub languageids {
1.16      harris41 1694:     return sort(keys(%language));
1.14      harris41 1695: }
                   1696: 
1.112     bowersj2 1697: =pod
                   1698: 
                   1699: =item * languagedescription() 
                   1700: 
                   1701: returns description of a specified language id
                   1702: 
                   1703: =cut
                   1704: 
1.14      harris41 1705: sub languagedescription {
1.125     www      1706:     my $code=shift;
                   1707:     return  ($supported_language{$code}?'* ':'').
                   1708:             $language{$code}.
1.126     www      1709: 	    ($supported_language{$code}?' ('.&mt('interface available').')':'');
1.145     www      1710: }
                   1711: 
                   1712: sub plainlanguagedescription {
                   1713:     my $code=shift;
                   1714:     return $language{$code};
                   1715: }
                   1716: 
                   1717: sub supportedlanguagecode {
                   1718:     my $code=shift;
                   1719:     return $supported_language{$code};
1.97      www      1720: }
                   1721: 
1.112     bowersj2 1722: =pod
                   1723: 
                   1724: =item * copyrightids() 
                   1725: 
                   1726: returns list of all copyrights
                   1727: 
                   1728: =cut
                   1729: 
                   1730: sub copyrightids {
                   1731:     return sort(keys(%cprtag));
                   1732: }
                   1733: 
                   1734: =pod
                   1735: 
                   1736: =item * copyrightdescription() 
                   1737: 
                   1738: returns description of a specified copyright id
                   1739: 
                   1740: =cut
                   1741: 
                   1742: sub copyrightdescription {
1.166     www      1743:     return &mt($cprtag{shift(@_)});
1.112     bowersj2 1744: }
                   1745: 
                   1746: =pod
                   1747: 
                   1748: =item * filecategories() 
                   1749: 
                   1750: returns list of all file categories
                   1751: 
                   1752: =cut
                   1753: 
                   1754: sub filecategories {
                   1755:     return sort(keys(%category_extensions));
                   1756: }
                   1757: 
                   1758: =pod
                   1759: 
                   1760: =item * filecategorytypes() 
                   1761: 
                   1762: returns list of file types belonging to a given file
                   1763: category
                   1764: 
                   1765: =cut
                   1766: 
                   1767: sub filecategorytypes {
                   1768:     return @{$category_extensions{lc($_[0])}};
                   1769: }
                   1770: 
                   1771: =pod
                   1772: 
                   1773: =item * fileembstyle() 
                   1774: 
                   1775: returns embedding style for a specified file type
                   1776: 
                   1777: =cut
                   1778: 
                   1779: sub fileembstyle {
                   1780:     return $fe{lc(shift(@_))};
1.169     www      1781: }
                   1782: 
                   1783: 
                   1784: sub filecategoryselect {
                   1785:     my ($name,$value)=@_;
                   1786:     return &select_form($name,$value,
                   1787: 			'' => &mt('Any category'),
                   1788: 			map { $_,$_ } sort(keys(%category_extensions)));
1.112     bowersj2 1789: }
                   1790: 
                   1791: =pod
                   1792: 
                   1793: =item * filedescription() 
                   1794: 
                   1795: returns description for a specified file type
                   1796: 
                   1797: =cut
                   1798: 
                   1799: sub filedescription {
1.166     www      1800:     return &mt($fd{lc(shift(@_))});
1.112     bowersj2 1801: }
                   1802: 
                   1803: =pod
                   1804: 
                   1805: =item * filedescriptionex() 
                   1806: 
                   1807: returns description for a specified file type with
                   1808: extra formatting
                   1809: 
                   1810: =cut
                   1811: 
                   1812: sub filedescriptionex {
                   1813:     my $ex=shift;
1.166     www      1814:     return '.'.$ex.' '.&mt($fd{lc($ex)});
1.112     bowersj2 1815: }
                   1816: 
                   1817: # End of .tab access
                   1818: =pod
                   1819: 
                   1820: =back
                   1821: 
                   1822: =cut
                   1823: 
                   1824: # ------------------------------------------------------------------ File Types
                   1825: sub fileextensions {
                   1826:     return sort(keys(%fe));
                   1827: }
                   1828: 
1.97      www      1829: # ----------------------------------------------------------- Display Languages
                   1830: # returns a hash with all desired display languages
                   1831: #
                   1832: 
                   1833: sub display_languages {
                   1834:     my %languages=();
1.118     www      1835:     foreach (&preferred_languages()) {
                   1836: 	$languages{$_}=1;
1.97      www      1837:     }
                   1838:     &get_unprocessed_cgi($ENV{'QUERY_STRING'},['displaylanguage']);
                   1839:     if ($ENV{'form.displaylanguage'}) {
                   1840: 	foreach (split(/\s*(\,|\;|\:)\s*/,$ENV{'form.displaylanguage'})) {
                   1841: 	    $languages{$_}=1;
                   1842:         }
                   1843:     }
                   1844:     return %languages;
1.14      harris41 1845: }
                   1846: 
1.117     www      1847: sub preferred_languages {
                   1848:     my @languages=();
                   1849:     if ($ENV{'environment.languages'}) {
                   1850: 	@languages=split(/\s*(\,|\;|\:)\s*/,$ENV{'environment.languages'});
                   1851:     }
                   1852:     if ($ENV{'course.'.$ENV{'request.course.id'}.'.languages'}) {
                   1853: 	@languages=(@languages,split(/\s*(\,|\;|\:)\s*/,
                   1854: 	         $ENV{'course.'.$ENV{'request.course.id'}.'.languages'}));
1.118     www      1855:     }
1.162     www      1856:     my $browser=(split(/\;/,$ENV{'HTTP_ACCEPT_LANGUAGE'}))[0];
                   1857:     if ($browser) {
                   1858: 	@languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$browser));
                   1859:     }
1.118     www      1860:     if ($Apache::lonnet::domain_lang_def{$ENV{'user.domain'}}) {
                   1861: 	@languages=(@languages,
                   1862: 		$Apache::lonnet::domain_lang_def{$ENV{'user.domain'}});
                   1863:     }
                   1864:     if ($Apache::lonnet::domain_lang_def{$ENV{'request.role.domain'}}) {
                   1865: 	@languages=(@languages,
                   1866: 		$Apache::lonnet::domain_lang_def{$ENV{'request.role.domain'}});
                   1867:     }
                   1868:     if ($Apache::lonnet::domain_lang_def{
                   1869: 	                          $Apache::lonnet::perlvar{'lonDefDomain'}}) {
                   1870: 	@languages=(@languages,
                   1871: 		$Apache::lonnet::domain_lang_def{
                   1872:                                   $Apache::lonnet::perlvar{'lonDefDomain'}});
                   1873:     }
                   1874: # turn "en-ca" into "en-ca,en"
                   1875:     my @genlanguages;
                   1876:     foreach (@languages) {
                   1877: 	unless ($_=~/\w/) { next; }
                   1878: 	push (@genlanguages,$_);
                   1879: 	if ($_=~/(\-|\_)/) {
                   1880: 	    push (@genlanguages,(split(/(\-|\_)/,$_))[0]);
                   1881: 	}
                   1882:     }
                   1883:     return @genlanguages;
1.117     www      1884: }
                   1885: 
1.112     bowersj2 1886: ###############################################################
                   1887: ##               Student Answer Attempts                     ##
                   1888: ###############################################################
                   1889: 
                   1890: =pod
                   1891: 
                   1892: =head1 Alternate Problem Views
                   1893: 
                   1894: =over 4
                   1895: 
                   1896: =item * get_previous_attempt($symb, $username, $domain, $course,
                   1897:     $getattempt, $regexp, $gradesub)
                   1898: 
                   1899: Return string with previous attempt on problem. Arguments:
                   1900: 
                   1901: =over 4
                   1902: 
                   1903: =item * $symb: Problem, including path
                   1904: 
                   1905: =item * $username: username of the desired student
                   1906: 
                   1907: =item * $domain: domain of the desired student
1.14      harris41 1908: 
1.112     bowersj2 1909: =item * $course: Course ID
1.14      harris41 1910: 
1.112     bowersj2 1911: =item * $getattempt: Leave blank for all attempts, otherwise put
                   1912:     something
1.14      harris41 1913: 
1.112     bowersj2 1914: =item * $regexp: if string matches this regexp, the string will be
                   1915:     sent to $gradesub
1.14      harris41 1916: 
1.112     bowersj2 1917: =item * $gradesub: routine that processes the string if it matches $regexp
1.14      harris41 1918: 
1.112     bowersj2 1919: =back
1.14      harris41 1920: 
1.112     bowersj2 1921: The output string is a table containing all desired attempts, if any.
1.16      harris41 1922: 
1.112     bowersj2 1923: =cut
1.1       albertel 1924: 
                   1925: sub get_previous_attempt {
1.43      ng       1926:   my ($symb,$username,$domain,$course,$getattempt,$regexp,$gradesub)=@_;
1.1       albertel 1927:   my $prevattempts='';
1.43      ng       1928:   no strict 'refs';
1.1       albertel 1929:   if ($symb) {
1.3       albertel 1930:     my (%returnhash)=
                   1931:       &Apache::lonnet::restore($symb,$course,$domain,$username);
1.1       albertel 1932:     if ($returnhash{'version'}) {
                   1933:       my %lasthash=();
                   1934:       my $version;
                   1935:       for ($version=1;$version<=$returnhash{'version'};$version++) {
1.19      harris41 1936:         foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {
1.1       albertel 1937: 	  $lasthash{$_}=$returnhash{$version.':'.$_};
1.19      harris41 1938:         }
1.1       albertel 1939:       }
1.43      ng       1940:       $prevattempts='<table border="0" width="100%"><tr><td bgcolor="#777777">';
1.40      ng       1941:       $prevattempts.='<table border="0" width="100%"><tr bgcolor="#e6ffff"><td>History</td>';
1.16      harris41 1942:       foreach (sort(keys %lasthash)) {
1.31      albertel 1943: 	my ($ign,@parts) = split(/\./,$_);
1.41      ng       1944: 	if ($#parts > 0) {
1.31      albertel 1945: 	  my $data=$parts[-1];
                   1946: 	  pop(@parts);
1.40      ng       1947: 	  $prevattempts.='<td>Part '.join('.',@parts).'<br />'.$data.'&nbsp;</td>';
1.31      albertel 1948: 	} else {
1.41      ng       1949: 	  if ($#parts == 0) {
                   1950: 	    $prevattempts.='<th>'.$parts[0].'</th>';
                   1951: 	  } else {
                   1952: 	    $prevattempts.='<th>'.$ign.'</th>';
                   1953: 	  }
1.31      albertel 1954: 	}
1.16      harris41 1955:       }
1.40      ng       1956:       if ($getattempt eq '') {
                   1957: 	for ($version=1;$version<=$returnhash{'version'};$version++) {
                   1958: 	  $prevattempts.='</tr><tr bgcolor="#ffffe6"><td>Transaction '.$version.'</td>';
                   1959: 	    foreach (sort(keys %lasthash)) {
                   1960: 	       my $value;
                   1961: 	       if ($_ =~ /timestamp/) {
                   1962: 		  $value=scalar(localtime($returnhash{$version.':'.$_}));
                   1963: 	       } else {
                   1964: 		  $value=$returnhash{$version.':'.$_};
                   1965: 	       }
1.142     albertel 1966: 	       $prevattempts.='<td>'.&Apache::lonnet::unescape($value).'&nbsp;</td>';   
1.40      ng       1967: 	    }
                   1968: 	 }
1.1       albertel 1969:       }
1.40      ng       1970:       $prevattempts.='</tr><tr bgcolor="#ffffe6"><td>Current</td>';
1.16      harris41 1971:       foreach (sort(keys %lasthash)) {
1.5       albertel 1972: 	my $value;
                   1973: 	if ($_ =~ /timestamp/) {
                   1974: 	  $value=scalar(localtime($lasthash{$_}));
                   1975: 	} else {
                   1976: 	  $value=$lasthash{$_};
                   1977: 	}
1.142     albertel 1978: 	$value=&Apache::lonnet::unescape($value);
1.49      ng       1979: 	if ($_ =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
1.40      ng       1980: 	$prevattempts.='<td>'.$value.'&nbsp;</td>';
1.16      harris41 1981:       }
1.40      ng       1982:       $prevattempts.='</tr></table></td></tr></table>';
1.1       albertel 1983:     } else {
                   1984:       $prevattempts='Nothing submitted - no attempts.';
                   1985:     }
                   1986:   } else {
                   1987:     $prevattempts='No data.';
                   1988:   }
1.10      albertel 1989: }
                   1990: 
1.107     albertel 1991: sub relative_to_absolute {
                   1992:     my ($url,$output)=@_;
                   1993:     my $parser=HTML::TokeParser->new(\$output);
                   1994:     my $token;
                   1995:     my $thisdir=$url;
                   1996:     my @rlinks=();
                   1997:     while ($token=$parser->get_token) {
                   1998: 	if ($token->[0] eq 'S') {
                   1999: 	    if ($token->[1] eq 'a') {
                   2000: 		if ($token->[2]->{'href'}) {
                   2001: 		    $rlinks[$#rlinks+1]=$token->[2]->{'href'};
                   2002: 		}
                   2003: 	    } elsif ($token->[1] eq 'img' || $token->[1] eq 'embed' ) {
                   2004: 		$rlinks[$#rlinks+1]=$token->[2]->{'src'};
                   2005: 	    } elsif ($token->[1] eq 'base') {
                   2006: 		$thisdir=$token->[2]->{'href'};
                   2007: 	    }
                   2008: 	}
                   2009:     }
                   2010:     $thisdir=~s-/[^/]*$--;
                   2011:     foreach (@rlinks) {
                   2012: 	unless (($_=~/^http:\/\//i) ||
                   2013: 		($_=~/^\//) ||
                   2014: 		($_=~/^javascript:/i) ||
                   2015: 		($_=~/^mailto:/i) ||
                   2016: 		($_=~/^\#/)) {
                   2017: 	    my $newlocation=&Apache::lonnet::hreflocation($thisdir,$_);
                   2018: 	    $output=~s/(\"|\'|\=\s*)$_(\"|\'|\s|\>)/$1$newlocation$2/;
                   2019: 	}
                   2020:     }
                   2021: # -------------------------------------------------- Deal with Applet codebases
                   2022:     $output=~s/(\<applet[^\>]+)(codebase\=[^\S\>]+)*([^\>]*)\>/$1.($2?$2:' codebase="'.$thisdir.'"').$3.'>'/gei;
                   2023:     return $output;
                   2024: }
                   2025: 
1.112     bowersj2 2026: =pod
                   2027: 
                   2028: =item * get_student_view
                   2029: 
                   2030: show a snapshot of what student was looking at
                   2031: 
                   2032: =cut
                   2033: 
1.10      albertel 2034: sub get_student_view {
1.64      sakharuk 2035:   my ($symb,$username,$domain,$courseid,$target) = @_;
1.114     www      2036:   my ($map,$id,$feedurl) = &Apache::lonnet::decode_symb($symb);
1.10      albertel 2037:   my (%old,%moreenv);
                   2038:   my @elements=('symb','courseid','domain','username');
                   2039:   foreach my $element (@elements) {
                   2040:     $old{$element}=$ENV{'form.grade_'.$element};
                   2041:     $moreenv{'form.grade_'.$element}=eval '$'.$element #'
                   2042:   }
1.64      sakharuk 2043:   if ($target eq 'tex') {$moreenv{'form.grade_target'} = 'tex';}
1.11      albertel 2044:   &Apache::lonnet::appenv(%moreenv);
1.107     albertel 2045:   $feedurl=&Apache::lonnet::clutter($feedurl);
                   2046:   my $userview=&Apache::lonnet::ssi_body($feedurl);
1.11      albertel 2047:   &Apache::lonnet::delenv('form.grade_');
                   2048:   foreach my $element (@elements) {
                   2049:     $ENV{'form.grade_'.$element}=$old{$element};
                   2050:   }
                   2051:   $userview=~s/\<body[^\>]*\>//gi;
                   2052:   $userview=~s/\<\/body\>//gi;
                   2053:   $userview=~s/\<html\>//gi;
                   2054:   $userview=~s/\<\/html\>//gi;
                   2055:   $userview=~s/\<head\>//gi;
                   2056:   $userview=~s/\<\/head\>//gi;
                   2057:   $userview=~s/action\s*\=/would_be_action\=/gi;
1.107     albertel 2058:   $userview=&relative_to_absolute($feedurl,$userview);
1.11      albertel 2059:   return $userview;
                   2060: }
                   2061: 
1.112     bowersj2 2062: =pod
                   2063: 
                   2064: =item * get_student_answers() 
                   2065: 
                   2066: show a snapshot of how student was answering problem
                   2067: 
                   2068: =cut
                   2069: 
1.11      albertel 2070: sub get_student_answers {
1.100     sakharuk 2071:   my ($symb,$username,$domain,$courseid,%form) = @_;
1.114     www      2072:   my ($map,$id,$feedurl) = &Apache::lonnet::decode_symb($symb);
1.11      albertel 2073:   my (%old,%moreenv);
                   2074:   my @elements=('symb','courseid','domain','username');
                   2075:   foreach my $element (@elements) {
                   2076:     $old{$element}=$ENV{'form.grade_'.$element};
                   2077:     $moreenv{'form.grade_'.$element}=eval '$'.$element #'
                   2078:   }
                   2079:   $moreenv{'form.grade_target'}='answer';
1.10      albertel 2080:   &Apache::lonnet::appenv(%moreenv);
1.100     sakharuk 2081:   my $userview=&Apache::lonnet::ssi('/res/'.$feedurl,%form);
1.10      albertel 2082:   &Apache::lonnet::delenv('form.grade_');
                   2083:   foreach my $element (@elements) {
                   2084:     $ENV{'form.grade_'.$element}=$old{$element};
                   2085:   }
                   2086:   return $userview;
1.1       albertel 2087: }
1.116     albertel 2088: 
                   2089: =pod
                   2090: 
                   2091: =item * &submlink()
                   2092: 
                   2093: Inputs: $text $uname $udom $symb
                   2094: 
                   2095: Returns: A link to grades.pm such as to see the SUBM view of a student
                   2096: 
                   2097: =cut
                   2098: 
                   2099: ###############################################
                   2100: sub submlink {
                   2101:     my ($text,$uname,$udom,$symb)=@_;
                   2102:     if (!($uname && $udom)) {
                   2103: 	(my $cursymb, my $courseid,$udom,$uname)=
                   2104: 	    &Apache::lonxml::whichuser($symb);
                   2105: 	if (!$symb) { $symb=$cursymb; }
                   2106:     }
                   2107:     if (!$symb) { $symb=&symbread(); }
                   2108:     return '<a href="/adm/grades?symb='.$symb.'&student='.$uname.
                   2109: 	'&userdom='.$udom.'&command=submission">'.$text.'</a>';
                   2110: }
                   2111: ##############################################
1.37      matthew  2112: 
1.112     bowersj2 2113: =pod
                   2114: 
                   2115: =back
                   2116: 
                   2117: =cut
                   2118: 
1.37      matthew  2119: ###############################################
1.51      www      2120: 
                   2121: 
                   2122: sub timehash {
                   2123:     my @ltime=localtime(shift);
                   2124:     return ( 'seconds' => $ltime[0],
                   2125:              'minutes' => $ltime[1],
                   2126:              'hours'   => $ltime[2],
                   2127:              'day'     => $ltime[3],
                   2128:              'month'   => $ltime[4]+1,
                   2129:              'year'    => $ltime[5]+1900,
                   2130:              'weekday' => $ltime[6],
                   2131:              'dayyear' => $ltime[7]+1,
                   2132:              'dlsav'   => $ltime[8] );
                   2133: }
                   2134: 
                   2135: sub maketime {
                   2136:     my %th=@_;
                   2137:     return POSIX::mktime(
                   2138:         ($th{'seconds'},$th{'minutes'},$th{'hours'},
                   2139:          $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,$th{'dlsav'}));
1.70      www      2140: }
                   2141: 
                   2142: #########################################
1.51      www      2143: 
                   2144: sub findallcourses {
                   2145:     my %courses=();
                   2146:     my $now=time;
                   2147:     foreach (keys %ENV) {
                   2148: 	if ($_=~/^user\.role\.\w+\.\/(\w+)\/(\w+)/) {
                   2149: 	    my ($starttime,$endtime)=$ENV{$_};
                   2150:             my $active=1;
                   2151:             if ($starttime) {
                   2152: 		if ($now<$starttime) { $active=0; }
                   2153:             }
                   2154:             if ($endtime) {
                   2155:                 if ($now>$endtime) { $active=0; }
                   2156:             }
                   2157:             if ($active) { $courses{$1.'_'.$2}=1; }
                   2158:         }
                   2159:     }
                   2160:     return keys %courses;
                   2161: }
1.37      matthew  2162: 
1.54      www      2163: ###############################################
1.60      matthew  2164: ###############################################
                   2165: 
                   2166: =pod
                   2167: 
1.112     bowersj2 2168: =head1 Domain Template Functions
                   2169: 
                   2170: =over 4
                   2171: 
                   2172: =item * &determinedomain()
1.60      matthew  2173: 
                   2174: Inputs: $domain (usually will be undef)
                   2175: 
1.63      www      2176: Returns: Determines which domain should be used for designs
1.60      matthew  2177: 
                   2178: =cut
1.54      www      2179: 
1.60      matthew  2180: ###############################################
1.63      www      2181: sub determinedomain {
                   2182:     my $domain=shift;
                   2183:    if (! $domain) {
1.60      matthew  2184:         # Determine domain if we have not been given one
                   2185:         $domain = $Apache::lonnet::perlvar{'lonDefDomain'};
                   2186:         if ($ENV{'user.domain'}) { $domain=$ENV{'user.domain'}; }
                   2187:         if ($ENV{'request.role.domain'}) { 
                   2188:             $domain=$ENV{'request.role.domain'}; 
                   2189:         }
                   2190:     }
1.63      www      2191:     return $domain;
                   2192: }
                   2193: ###############################################
                   2194: =pod
                   2195: 
1.112     bowersj2 2196: =item * &domainlogo()
1.63      www      2197: 
                   2198: Inputs: $domain (usually will be undef)
                   2199: 
                   2200: Returns: A link to a domain logo, if the domain logo exists.
                   2201: If the domain logo does not exist, a description of the domain.
                   2202: 
                   2203: =cut
1.112     bowersj2 2204: 
1.63      www      2205: ###############################################
                   2206: sub domainlogo {
                   2207:     my $domain = &determinedomain(shift);    
                   2208:      # See if there is a logo
1.59      www      2209:     if (-e '/home/httpd/html/adm/lonDomLogos/'.$domain.'.gif') {
1.83      albertel 2210: 	my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
                   2211: 	if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
                   2212:         return '<img src="http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.
1.150     matthew  2213: 	    '/adm/lonDomLogos/'.$domain.'.gif" alt="'.$domain.'" />';
1.60      matthew  2214:     } elsif(exists($Apache::lonnet::domaindescription{$domain})) {
                   2215:         return $Apache::lonnet::domaindescription{$domain};
1.59      www      2216:     } else {
1.60      matthew  2217:         return '';
1.59      www      2218:     }
                   2219: }
1.63      www      2220: ##############################################
                   2221: 
                   2222: =pod
                   2223: 
1.112     bowersj2 2224: =item * &designparm()
1.63      www      2225: 
                   2226: Inputs: $which parameter; $domain (usually will be undef)
                   2227: 
                   2228: Returns: value of designparamter $which
                   2229: 
                   2230: =cut
1.112     bowersj2 2231: 
1.63      www      2232: ##############################################
                   2233: sub designparm {
                   2234:     my ($which,$domain)=@_;
1.110     www      2235:     if ($ENV{'browser.blackwhite'} eq 'on') {
                   2236: 	if ($which=~/\.(font|alink|vlink|link)$/) {
                   2237: 	    return '#000000';
                   2238: 	}
                   2239: 	if ($which=~/\.(pgbg|sidebg)$/) {
                   2240: 	    return '#FFFFFF';
                   2241: 	}
                   2242: 	if ($which=~/\.tabbg$/) {
                   2243: 	    return '#CCCCCC';
                   2244: 	}
                   2245:     }
1.96      www      2246:     if ($ENV{'environment.color.'.$which}) {
                   2247: 	return $ENV{'environment.color.'.$which};
                   2248:     }
1.63      www      2249:     $domain=&determinedomain($domain);
                   2250:     if ($designhash{$domain.'.'.$which}) {
                   2251: 	return $designhash{$domain.'.'.$which};
                   2252:     } else {
                   2253:         return $designhash{'default.'.$which};
                   2254:     }
                   2255: }
1.59      www      2256: 
1.60      matthew  2257: ###############################################
                   2258: ###############################################
                   2259: 
                   2260: =pod
                   2261: 
1.112     bowersj2 2262: =back
                   2263: 
                   2264: =head1 HTTP Helpers
                   2265: 
                   2266: =over 4
                   2267: 
                   2268: =item * &bodytag()
1.60      matthew  2269: 
                   2270: Returns a uniform header for LON-CAPA web pages.
                   2271: 
                   2272: Inputs: 
                   2273: 
1.112     bowersj2 2274: =over 4
                   2275: 
                   2276: =item * $title, A title to be displayed on the page.
                   2277: 
                   2278: =item * $function, the current role (can be undef).
                   2279: 
                   2280: =item * $addentries, extra parameters for the <body> tag.
                   2281: 
                   2282: =item * $bodyonly, if defined, only return the <body> tag.
                   2283: 
                   2284: =item * $domain, if defined, force a given domain.
                   2285: 
                   2286: =item * $forcereg, if page should register as content page (relevant for 
1.86      www      2287:             text interface only)
1.60      matthew  2288: 
1.112     bowersj2 2289: =back
                   2290: 
1.60      matthew  2291: Returns: A uniform header for LON-CAPA web pages.  
                   2292: If $bodyonly is nonzero, a string containing a <body> tag will be returned.
                   2293: If $bodyonly is undef or zero, an html string containing a <body> tag and 
                   2294: other decorations will be returned.
                   2295: 
                   2296: =cut
                   2297: 
1.54      www      2298: sub bodytag {
1.86      www      2299:     my ($title,$function,$addentries,$bodyonly,$domain,$forcereg)=@_;
1.117     www      2300:     $title=&mt($title);
1.55      www      2301:     unless ($function) {
                   2302: 	$function='student';
                   2303:         if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {
                   2304: 	    $function='coordinator';
                   2305:         }
                   2306: 	if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {
                   2307:             $function='admin';
                   2308:         }
                   2309:         if (($ENV{'request.role'}=~/^(au|ca)/) ||
                   2310:             ($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
                   2311:             $function='author';
                   2312:         }
                   2313:     }
1.63      www      2314:     my $img=&designparm($function.'.img',$domain);
                   2315:     my $pgbg=&designparm($function.'.pgbg',$domain);
                   2316:     my $tabbg=&designparm($function.'.tabbg',$domain);
                   2317:     my $font=&designparm($function.'.font',$domain);
                   2318:     my $link=&designparm($function.'.link',$domain);
                   2319:     my $alink=&designparm($function.'.alink',$domain);
                   2320:     my $vlink=&designparm($function.'.vlink',$domain);
                   2321:     my $sidebg=&designparm($function.'.sidebg',$domain);
1.110     www      2322: # Accessibility font enhance
                   2323:     unless ($addentries) { $addentries=''; }
1.146     www      2324:     my $addstyle='';
1.110     www      2325:     if ($ENV{'browser.fontenhance'} eq 'on') {
1.146     www      2326: 	$addstyle=' font-size: x-large;';
1.110     www      2327:     }
1.63      www      2328:  # role and realm
1.55      www      2329:     my ($role,$realm)
                   2330:        =&Apache::lonnet::plaintext((split(/\./,$ENV{'request.role'}))[0]);
                   2331: # realm
1.54      www      2332:     if ($ENV{'request.course.id'}) {
1.55      www      2333: 	$realm=
                   2334:          $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
1.54      www      2335:     }
1.55      www      2336:     unless ($realm) { $realm='&nbsp;'; }
                   2337: # Set messages
1.60      matthew  2338:     my $messages=&domainlogo($domain);
1.101     www      2339: # Port for miniserver
1.83      albertel 2340:     my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
                   2341:     if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
1.101     www      2342: # construct main body tag
1.60      matthew  2343:     my $bodytag = <<END;
1.146     www      2344: <style>
1.147     www      2345: h1, h2, h3, th { font-family: Arial, Helvetica, sans-serif }
1.146     www      2346: a:focus { color: red; background: yellow } 
                   2347: </style>
1.54      www      2348: <body bgcolor="$pgbg" text="$font" alink="$alink" vlink="$vlink" link="$link"
1.151     www      2349: style="margin-top: 0px;$addstyle" $addentries>
1.60      matthew  2350: END
1.94      www      2351:     my $upperleft='<img src="http://'.$ENV{'HTTP_HOST'}.':'.
1.150     matthew  2352:                    $lonhttpdPort.$img.'" alt="'.$function.'" />';
1.60      matthew  2353:     if ($bodyonly) {
                   2354:         return $bodytag;
1.79      www      2355:     } elsif ($ENV{'browser.interface'} eq 'textual') {
1.95      www      2356: # Accessibility
1.93      www      2357:         return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
                   2358:                                                       $forcereg).
                   2359:                '<h1>LON-CAPA: '.$title.'</h1>';
                   2360:     } elsif ($ENV{'environment.remote'} eq 'off') {
1.95      www      2361: # No Remote
                   2362:         return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
                   2363:                                                       $forcereg).
1.151     www      2364:       '<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.
1.95      www      2365: '</b></font></td></tr></table>';
1.94      www      2366:     }
1.95      www      2367: 
1.93      www      2368: #
1.95      www      2369: # Top frame rendering, Remote is up
1.93      www      2370: #
1.94      www      2371:     return(<<ENDBODY);
1.60      matthew  2372: $bodytag
1.55      www      2373: <table width="100%" cellspacing="0" border="0" cellpadding="0">
1.95      www      2374: <tr><td bgcolor="$sidebg">
1.94      www      2375: $upperleft</td>
1.95      www      2376: <td bgcolor="$sidebg" align="right">$messages&nbsp;</td>
1.55      www      2377: </tr>
1.54      www      2378: <tr>
1.55      www      2379: <td rowspan="3" bgcolor="$tabbg">
1.146     www      2380: &nbsp;<font size="5" face="Arial, Helvetica, sans-serif"><b>$title</b></font>
                   2381: <td bgcolor="$tabbg" align="right">
                   2382: <font size="2" face="Arial, Helvetica, sans-serif">
1.54      www      2383:     $ENV{'environment.firstname'}
                   2384:     $ENV{'environment.middlename'}
                   2385:     $ENV{'environment.lastname'}
                   2386:     $ENV{'environment.generation'}
1.55      www      2387:     </font>&nbsp;
1.54      www      2388: </td>
                   2389: </tr>
                   2390: <tr><td bgcolor="$tabbg" align="right">
1.146     www      2391: <font size="2" face="Arial, Helvetica, sans-serif">$role</font>&nbsp;
1.54      www      2392: </td></tr>
1.55      www      2393: <tr>
1.148     www      2394: <td bgcolor="$tabbg" align="right"><font size="2" face="Arial, Helvetica, sans-serif">$realm</font>&nbsp;</td></tr>
1.54      www      2395: </table><br>
                   2396: ENDBODY
                   2397: }
1.99      www      2398: 
                   2399: ###############################################
                   2400: 
                   2401: sub get_posted_cgi {
                   2402:     my $r=shift;
                   2403: 
                   2404:     my $buffer;
                   2405:     
                   2406:     $r->read($buffer,$r->header_in('Content-length'),0);
                   2407:     unless ($buffer=~/^(\-+\w+)\s+Content\-Disposition\:\s*form\-data/si) {
                   2408: 	my @pairs=split(/&/,$buffer);
                   2409: 	my $pair;
                   2410: 	foreach $pair (@pairs) {
                   2411: 	    my ($name,$value) = split(/=/,$pair);
                   2412: 	    $value =~ tr/+/ /;
                   2413: 	    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
                   2414: 	    $name  =~ tr/+/ /;
                   2415: 	    $name  =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
                   2416: 	    &add_to_env("form.$name",$value);
                   2417: 	}
                   2418:     } else {
                   2419: 	my $contentsep=$1;
                   2420: 	my @lines = split (/\n/,$buffer);
                   2421: 	my $name='';
                   2422: 	my $value='';
                   2423: 	my $fname='';
                   2424: 	my $fmime='';
                   2425: 	my $i;
                   2426: 	for ($i=0;$i<=$#lines;$i++) {
                   2427: 	    if ($lines[$i]=~/^$contentsep/) {
                   2428: 		if ($name) {
                   2429: 		    chomp($value);
                   2430: 		    if ($fname) {
                   2431: 			$ENV{"form.$name.filename"}=$fname;
                   2432: 			$ENV{"form.$name.mimetype"}=$fmime;
                   2433: 		    } else {
                   2434: 			$value=~s/\s+$//s;
                   2435: 		    }
                   2436: 		    &add_to_env("form.$name",$value);
                   2437: 		}
                   2438: 		if ($i<$#lines) {
                   2439: 		    $i++;
                   2440: 		    $lines[$i]=~
                   2441: 		/Content\-Disposition\:\s*form\-data\;\s*name\=\"([^\"]+)\"/i;
                   2442: 		    $name=$1;
                   2443: 		    $value='';
                   2444: 		    if ($lines[$i]=~/filename\=\"([^\"]+)\"/i) {
                   2445: 			$fname=$1;
                   2446: 			if 
                   2447:                             ($lines[$i+1]=~/Content\-Type\:\s*([\w\-\/]+)/i) {
                   2448: 				$fmime=$1;
                   2449: 				$i++;
                   2450: 			    } else {
                   2451: 				$fmime='';
                   2452: 			    }
                   2453: 		    } else {
                   2454: 			$fname='';
                   2455: 			$fmime='';
                   2456: 		    }
                   2457: 		    $i++;
                   2458: 		}
                   2459: 	    } else {
                   2460: 		$value.=$lines[$i]."\n";
                   2461: 	    }
                   2462: 	}
                   2463:     }
                   2464:     $ENV{'request.method'}=$ENV{'REQUEST_METHOD'};
                   2465:     $r->method_number(M_GET);
                   2466:     $r->method('GET');
                   2467:     $r->headers_in->unset('Content-length');
                   2468: }
                   2469: 
1.112     bowersj2 2470: =pod
                   2471: 
                   2472: =item * get_unprocessed_cgi($query,$possible_names)
                   2473: 
                   2474: Modify the %ENV hash to contain unprocessed CGI form parameters held in
                   2475: $query.  The parameters listed in $possible_names (an array reference),
                   2476: will be set in $ENV{'form.name'} if they do not already exist.
                   2477: 
                   2478: Typically called with $ENV{'QUERY_STRING'} as the first parameter.  
                   2479: $possible_names is an ref to an array of form element names.  As an example:
                   2480: get_unprocessed_cgi($ENV{'QUERY_STRING'},['uname','udom']);
                   2481: will result in $ENV{'form.uname'} and $ENV{'form.udom'} being set.
                   2482: 
                   2483: =cut
1.1       albertel 2484: 
1.6       albertel 2485: sub get_unprocessed_cgi {
1.25      albertel 2486:   my ($query,$possible_names)= @_;
1.26      matthew  2487:   # $Apache::lonxml::debug=1;
1.16      harris41 2488:   foreach (split(/&/,$query)) {
1.6       albertel 2489:     my ($name, $value) = split(/=/,$_);
1.25      albertel 2490:     $name = &Apache::lonnet::unescape($name);
                   2491:     if (!defined($possible_names) || (grep {$_ eq $name} @$possible_names)) {
                   2492:       $value =~ tr/+/ /;
                   2493:       $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
                   2494:       &Apache::lonxml::debug("Seting :$name: to :$value:");
1.30      albertel 2495:       unless (defined($ENV{'form.'.$name})) { &add_to_env('form.'.$name,$value) };
1.25      albertel 2496:     }
1.16      harris41 2497:   }
1.6       albertel 2498: }
                   2499: 
1.112     bowersj2 2500: =pod
                   2501: 
                   2502: =item * cacheheader() 
                   2503: 
                   2504: returns cache-controlling header code
                   2505: 
                   2506: =cut
                   2507: 
1.7       albertel 2508: sub cacheheader {
1.23      www      2509:   unless ($ENV{'request.method'} eq 'GET') { return ''; }
1.8       albertel 2510:   my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime);
1.7       albertel 2511:   my $output .='<meta HTTP-EQUIV="Expires" CONTENT="'.$date.'" />
                   2512:                 <meta HTTP-EQUIV="Cache-control" CONTENT="no-cache" />
                   2513:                 <meta HTTP-EQUIV="Pragma" CONTENT="no-cache" />';
                   2514:   return $output;
                   2515: }
                   2516: 
1.112     bowersj2 2517: =pod
                   2518: 
                   2519: =item * no_cache($r) 
                   2520: 
                   2521: specifies header code to not have cache
                   2522: 
                   2523: =cut
                   2524: 
1.9       albertel 2525: sub no_cache {
                   2526:   my ($r) = @_;
1.23      www      2527:   unless ($ENV{'request.method'} eq 'GET') { return ''; }
1.24      albertel 2528:   #my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime);
1.9       albertel 2529:   $r->no_cache(1);
                   2530:   $r->header_out("Pragma" => "no-cache");
1.24      albertel 2531:   #$r->header_out("Expires" => $date);
1.123     www      2532: }
                   2533: 
                   2534: sub content_type {
                   2535:   my ($r,$type,$charset) = @_;
                   2536:   unless ($charset) {
                   2537:       $charset=&Apache::lonlocal::current_encoding;
                   2538:   }
                   2539:   $r->content_type($type.($charset?'; charset='.$charset:''));
1.9       albertel 2540: }
1.25      albertel 2541: 
1.112     bowersj2 2542: =pod
                   2543: 
                   2544: =item * add_to_env($name,$value) 
                   2545: 
                   2546: adds $name to the %ENV hash with value
                   2547: $value, if $name already exists, the entry is converted to an array
                   2548: reference and $value is added to the array.
                   2549: 
                   2550: =cut
                   2551: 
1.25      albertel 2552: sub add_to_env {
                   2553:   my ($name,$value)=@_;
1.28      albertel 2554:   if (defined($ENV{$name})) {
1.27      albertel 2555:     if (ref($ENV{$name})) {
1.25      albertel 2556:       #already have multiple values
                   2557:       push(@{ $ENV{$name} },$value);
                   2558:     } else {
                   2559:       #first time seeing multiple values, convert hash entry to an arrayref
                   2560:       my $first=$ENV{$name};
                   2561:       undef($ENV{$name});
                   2562:       push(@{ $ENV{$name} },$first,$value);
                   2563:     }
                   2564:   } else {
                   2565:     $ENV{$name}=$value;
                   2566:   }
1.31      albertel 2567: }
1.149     albertel 2568: 
                   2569: =pod
                   2570: 
                   2571: =item * get_env_multiple($name) 
                   2572: 
                   2573: gets $name from the %ENV hash, it seemlessly handles the cases where multiple
                   2574: values may be defined and end up as an array ref.
                   2575: 
                   2576: returns an array of values
                   2577: 
                   2578: =cut
                   2579: 
                   2580: sub get_env_multiple {
                   2581:     my ($name) = @_;
                   2582:     my @values;
                   2583:     if (defined($ENV{$name})) {
                   2584:         # exists is it an array
                   2585:         if (ref($ENV{$name})) {
                   2586:             @values=@{ $ENV{$name} };
                   2587:         } else {
                   2588:             $values[0]=$ENV{$name};
                   2589:         }
                   2590:     }
                   2591:     return(@values);
                   2592: }
                   2593: 
1.31      albertel 2594: 
1.41      ng       2595: =pod
1.45      matthew  2596: 
                   2597: =back 
1.41      ng       2598: 
1.112     bowersj2 2599: =head1 CSV Upload/Handling functions
1.38      albertel 2600: 
1.41      ng       2601: =over 4
                   2602: 
1.112     bowersj2 2603: =item * upfile_store($r)
1.41      ng       2604: 
                   2605: Store uploaded file, $r should be the HTTP Request object,
                   2606: needs $ENV{'form.upfile'}
                   2607: returns $datatoken to be put into hidden field
                   2608: 
                   2609: =cut
1.31      albertel 2610: 
                   2611: sub upfile_store {
                   2612:     my $r=shift;
                   2613:     $ENV{'form.upfile'}=~s/\r/\n/gs;
                   2614:     $ENV{'form.upfile'}=~s/\f/\n/gs;
                   2615:     $ENV{'form.upfile'}=~s/\n+/\n/gs;
                   2616:     $ENV{'form.upfile'}=~s/\n+$//gs;
                   2617: 
                   2618:     my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.
                   2619: 	'_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;
                   2620:     {
1.158     raeburn  2621:         my $datafile = $r->dir_config('lonDaemons').
                   2622:                            '/tmp/'.$datatoken.'.tmp';
                   2623:         if ( open(my $fh,">$datafile") ) {
                   2624:             print $fh $ENV{'form.upfile'};
                   2625:             close($fh);
                   2626:         }
1.31      albertel 2627:     }
                   2628:     return $datatoken;
                   2629: }
                   2630: 
1.56      matthew  2631: =pod
                   2632: 
1.112     bowersj2 2633: =item * load_tmp_file($r)
1.41      ng       2634: 
                   2635: Load uploaded file from tmp, $r should be the HTTP Request object,
                   2636: needs $ENV{'form.datatoken'},
                   2637: sets $ENV{'form.upfile'} to the contents of the file
                   2638: 
                   2639: =cut
1.31      albertel 2640: 
                   2641: sub load_tmp_file {
                   2642:     my $r=shift;
                   2643:     my @studentdata=();
                   2644:     {
1.158     raeburn  2645:         my $studentfile = $r->dir_config('lonDaemons').
                   2646:                               '/tmp/'.$ENV{'form.datatoken'}.'.tmp';
                   2647:         if ( open(my $fh,"<$studentfile") ) {
                   2648:             @studentdata=<$fh>;
                   2649:             close($fh);
                   2650:         }
1.31      albertel 2651:     }
                   2652:     $ENV{'form.upfile'}=join('',@studentdata);
                   2653: }
                   2654: 
1.56      matthew  2655: =pod
                   2656: 
1.112     bowersj2 2657: =item * upfile_record_sep()
1.41      ng       2658: 
                   2659: Separate uploaded file into records
                   2660: returns array of records,
                   2661: needs $ENV{'form.upfile'} and $ENV{'form.upfiletype'}
                   2662: 
                   2663: =cut
1.31      albertel 2664: 
                   2665: sub upfile_record_sep {
                   2666:     if ($ENV{'form.upfiletype'} eq 'xml') {
                   2667:     } else {
                   2668: 	return split(/\n/,$ENV{'form.upfile'});
                   2669:     }
                   2670: }
                   2671: 
1.56      matthew  2672: =pod
                   2673: 
1.112     bowersj2 2674: =item * record_sep($record)
1.41      ng       2675: 
                   2676: Separate a record into fields $record should be an item from the upfile_record_sep(), needs $ENV{'form.upfiletype'}
                   2677: 
                   2678: =cut
                   2679: 
1.31      albertel 2680: sub record_sep {
                   2681:     my $record=shift;
                   2682:     my %components=();
                   2683:     if ($ENV{'form.upfiletype'} eq 'xml') {
                   2684:     } elsif ($ENV{'form.upfiletype'} eq 'space') {
                   2685:         my $i=0;
                   2686:         foreach (split(/\s+/,$record)) {
                   2687:             my $field=$_;
                   2688:             $field=~s/^(\"|\')//;
                   2689:             $field=~s/(\"|\')$//;
                   2690:             $components{$i}=$field;
                   2691:             $i++;
                   2692:         }
                   2693:     } elsif ($ENV{'form.upfiletype'} eq 'tab') {
                   2694:         my $i=0;
1.171     matthew  2695:         foreach (split(/\t/,$record)) {
1.31      albertel 2696:             my $field=$_;
                   2697:             $field=~s/^(\"|\')//;
                   2698:             $field=~s/(\"|\')$//;
                   2699:             $components{$i}=$field;
                   2700:             $i++;
                   2701:         }
                   2702:     } else {
                   2703:         my @allfields=split(/\,/,$record);
                   2704:         my $i=0;
                   2705:         my $j;
                   2706:         for ($j=0;$j<=$#allfields;$j++) {
                   2707:             my $field=$allfields[$j];
                   2708:             if ($field=~/^\s*(\"|\')/) {
                   2709: 		my $delimiter=$1;
                   2710:                 while (($field!~/$delimiter$/) && ($j<$#allfields)) {
                   2711: 		    $j++;
                   2712: 		    $field.=','.$allfields[$j];
                   2713: 		}
                   2714:                 $field=~s/^\s*$delimiter//;
                   2715:                 $field=~s/$delimiter\s*$//;
                   2716:             }
                   2717:             $components{$i}=$field;
                   2718: 	    $i++;
                   2719:         }
                   2720:     }
                   2721:     return %components;
                   2722: }
                   2723: 
1.144     matthew  2724: ######################################################
                   2725: ######################################################
                   2726: 
1.56      matthew  2727: =pod
                   2728: 
1.112     bowersj2 2729: =item * upfile_select_html()
1.41      ng       2730: 
1.144     matthew  2731: Return HTML code to select a file from the users machine and specify 
                   2732: the file type.
1.41      ng       2733: 
                   2734: =cut
                   2735: 
1.144     matthew  2736: ######################################################
                   2737: ######################################################
1.31      albertel 2738: sub upfile_select_html {
1.144     matthew  2739:     my %Types = (
                   2740:                  csv   => &mt('CSV (comma separated values, spreadsheet)'),
                   2741:                  space => &mt('Space separated'),
                   2742:                  tab   => &mt('Tabulator separated'),
                   2743: #                 xml   => &mt('HTML/XML'),
                   2744:                  );
                   2745:     my $Str = '<input type="file" name="upfile" size="50" />'.
                   2746:         '<br />Type: <select name="upfiletype">';
                   2747:     foreach my $type (sort(keys(%Types))) {
                   2748:         $Str .= '<option value="'.$type.'" >'.$Types{$type}."</option>\n";
                   2749:     }
                   2750:     $Str .= "</select>\n";
                   2751:     return $Str;
1.31      albertel 2752: }
                   2753: 
1.144     matthew  2754: ######################################################
                   2755: ######################################################
                   2756: 
1.56      matthew  2757: =pod
                   2758: 
1.112     bowersj2 2759: =item * csv_print_samples($r,$records)
1.41      ng       2760: 
                   2761: Prints a table of sample values from each column uploaded $r is an
                   2762: Apache Request ref, $records is an arrayref from
                   2763: &Apache::loncommon::upfile_record_sep
                   2764: 
                   2765: =cut
                   2766: 
1.144     matthew  2767: ######################################################
                   2768: ######################################################
1.31      albertel 2769: sub csv_print_samples {
                   2770:     my ($r,$records) = @_;
                   2771:     my (%sone,%stwo,%sthree);
                   2772:     %sone=&record_sep($$records[0]);
                   2773:     if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
                   2774:     if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
1.144     matthew  2775:     #
                   2776:     $r->print(&mt('Samples').'<br /><table border="2"><tr>');
                   2777:     foreach (sort({$a <=> $b} keys(%sone))) { 
                   2778:         $r->print('<th>'.&mt('Column&nbsp;[_1]',($_+1)).'</th>'); }
1.31      albertel 2779:     $r->print('</tr>');
                   2780:     foreach my $hash (\%sone,\%stwo,\%sthree) {
                   2781: 	$r->print('<tr>');
                   2782: 	foreach (sort({$a <=> $b} keys(%sone))) {
                   2783: 	    $r->print('<td>');
                   2784: 	    if (defined($$hash{$_})) { $r->print($$hash{$_}); }
                   2785: 	    $r->print('</td>');
                   2786: 	}
                   2787: 	$r->print('</tr>');
                   2788:     }
                   2789:     $r->print('</tr></table><br />'."\n");
                   2790: }
                   2791: 
1.144     matthew  2792: ######################################################
                   2793: ######################################################
                   2794: 
1.56      matthew  2795: =pod
                   2796: 
1.112     bowersj2 2797: =item * csv_print_select_table($r,$records,$d)
1.41      ng       2798: 
                   2799: Prints a table to create associations between values and table columns.
1.144     matthew  2800: 
1.41      ng       2801: $r is an Apache Request ref,
                   2802: $records is an arrayref from &Apache::loncommon::upfile_record_sep,
1.174   ! matthew  2803: $d is an array of 2 element arrays (internal name, displayed name,defaultcol)
1.41      ng       2804: 
                   2805: =cut
                   2806: 
1.144     matthew  2807: ######################################################
                   2808: ######################################################
1.31      albertel 2809: sub csv_print_select_table {
                   2810:     my ($r,$records,$d) = @_;
                   2811:     my $i=0;my %sone;
                   2812:     %sone=&record_sep($$records[0]);
1.144     matthew  2813:     $r->print(&mt('Associate columns with student attributes.')."\n".
                   2814: 	     '<table border="2"><tr>'.
                   2815:               '<th>'.&mt('Attribute').'</th>'.
                   2816:               '<th>'.&mt('Column').'</th></tr>'."\n");
1.31      albertel 2817:     foreach (@$d) {
1.174   ! matthew  2818: 	my ($value,$display,$defaultcol)=@{ $_ };
1.31      albertel 2819: 	$r->print('<tr><td>'.$display.'</td>');
                   2820: 
                   2821: 	$r->print('<td><select name=f'.$i.
1.32      matthew  2822: 		  ' onchange="javascript:flip(this.form,'.$i.');">');
1.31      albertel 2823: 	$r->print('<option value="none"></option>');
                   2824: 	foreach (sort({$a <=> $b} keys(%sone))) {
1.174   ! matthew  2825: 	    $r->print('<option value="'.$_.'"'.
        !          2826:                       ($_ eq $defaultcol ? ' selected ' : '').
        !          2827:                       '>Column '.($_+1).'</option>');
1.31      albertel 2828: 	}
                   2829: 	$r->print('</select></td></tr>'."\n");
                   2830: 	$i++;
                   2831:     }
                   2832:     $i--;
                   2833:     return $i;
                   2834: }
1.56      matthew  2835: 
1.144     matthew  2836: ######################################################
                   2837: ######################################################
                   2838: 
1.56      matthew  2839: =pod
1.31      albertel 2840: 
1.112     bowersj2 2841: =item * csv_samples_select_table($r,$records,$d)
1.41      ng       2842: 
                   2843: Prints a table of sample values from the upload and can make associate samples to internal names.
                   2844: 
                   2845: $r is an Apache Request ref,
                   2846: $records is an arrayref from &Apache::loncommon::upfile_record_sep,
                   2847: $d is an array of 2 element arrays (internal name, displayed name)
                   2848: 
                   2849: =cut
                   2850: 
1.144     matthew  2851: ######################################################
                   2852: ######################################################
1.31      albertel 2853: sub csv_samples_select_table {
                   2854:     my ($r,$records,$d) = @_;
                   2855:     my %sone; my %stwo; my %sthree;
                   2856:     my $i=0;
1.144     matthew  2857:     #
                   2858:     $r->print('<table border=2><tr><th>'.
                   2859:               &mt('Field').'</th><th>'.&mt('Samples').'</th></tr>');
1.31      albertel 2860:     %sone=&record_sep($$records[0]);
                   2861:     if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
                   2862:     if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
1.144     matthew  2863:     #
1.31      albertel 2864:     foreach (sort keys %sone) {
1.144     matthew  2865: 	$r->print('<tr><td><select name="f'.$i.'"'.
1.32      matthew  2866: 		  ' onchange="javascript:flip(this.form,'.$i.');">');
1.31      albertel 2867: 	foreach (@$d) {
1.174   ! matthew  2868: 	    my ($value,$display,$defaultcol)=@{ $_ };
        !          2869: 	    $r->print('<option value="'.$value.'"'.
        !          2870:                       ($i eq $defaultcol ? ' selected ':'').'>'.
        !          2871:                       $display.'</option>');
1.31      albertel 2872: 	}
                   2873: 	$r->print('</select></td><td>');
                   2874: 	if (defined($sone{$_})) { $r->print($sone{$_}."</br>\n"); }
                   2875: 	if (defined($stwo{$_})) { $r->print($stwo{$_}."</br>\n"); }
                   2876: 	if (defined($sthree{$_})) { $r->print($sthree{$_}."</br>\n"); }
                   2877: 	$r->print('</td></tr>');
                   2878: 	$i++;
                   2879:     }
                   2880:     $i--;
                   2881:     return($i);
1.115     matthew  2882: }
                   2883: 
1.144     matthew  2884: ######################################################
                   2885: ######################################################
                   2886: 
1.115     matthew  2887: =pod
                   2888: 
                   2889: =item clean_excel_name($name)
                   2890: 
                   2891: Returns a replacement for $name which does not contain any illegal characters.
                   2892: 
                   2893: =cut
                   2894: 
1.144     matthew  2895: ######################################################
                   2896: ######################################################
1.115     matthew  2897: sub clean_excel_name {
                   2898:     my ($name) = @_;
                   2899:     $name =~ s/[:\*\?\/\\]//g;
                   2900:     if (length($name) > 31) {
                   2901:         $name = substr($name,0,31);
                   2902:     }
                   2903:     return $name;
1.25      albertel 2904: }
1.84      albertel 2905: 
1.85      albertel 2906: =pod
                   2907: 
1.112     bowersj2 2908: =item * check_if_partid_hidden($id,$symb,$udom,$uname)
1.85      albertel 2909: 
                   2910: Returns either 1 or undef
                   2911: 
                   2912: 1 if the part is to be hidden, undef if it is to be shown
                   2913: 
                   2914: Arguments are:
                   2915: 
                   2916: $id the id of the part to be checked
                   2917: $symb, optional the symb of the resource to check
                   2918: $udom, optional the domain of the user to check for
                   2919: $uname, optional the username of the user to check for
                   2920: 
                   2921: =cut
1.84      albertel 2922: 
                   2923: sub check_if_partid_hidden {
                   2924:     my ($id,$symb,$udom,$uname) = @_;
1.133     albertel 2925:     my $hiddenparts=&Apache::lonnet::EXT('resource.0.hiddenparts',
1.84      albertel 2926: 					 $symb,$udom,$uname);
1.141     albertel 2927:     my $truth=1;
                   2928:     #if the string starts with !, then the list is the list to show not hide
                   2929:     if ($hiddenparts=~s/^\s*!//) { $truth=undef; }
1.84      albertel 2930:     my @hiddenlist=split(/,/,$hiddenparts);
                   2931:     foreach my $checkid (@hiddenlist) {
1.141     albertel 2932: 	if ($checkid =~ /^\s*\Q$id\E\s*$/) { return $truth; }
1.84      albertel 2933:     }
1.141     albertel 2934:     return !$truth;
1.84      albertel 2935: }
1.127     matthew  2936: 
1.138     matthew  2937: 
                   2938: ############################################################
                   2939: ############################################################
                   2940: 
                   2941: =pod
                   2942: 
1.157     matthew  2943: =back 
                   2944: 
1.138     matthew  2945: =head1 cgi-bin script and graphing routines
                   2946: 
1.157     matthew  2947: =over 4
                   2948: 
1.138     matthew  2949: =item get_cgi_id
                   2950: 
                   2951: Inputs: none
                   2952: 
                   2953: Returns an id which can be used to pass environment variables
                   2954: to various cgi-bin scripts.  These environment variables will
                   2955: be removed from the users environment after a given time by
                   2956: the routine &Apache::lonnet::transfer_profile_to_env.
                   2957: 
                   2958: =cut
                   2959: 
                   2960: ############################################################
                   2961: ############################################################
1.152     albertel 2962: my $uniq=0;
1.136     matthew  2963: sub get_cgi_id {
1.154     albertel 2964:     $uniq=($uniq+1)%100000;
1.152     albertel 2965:     return (time.'_'.$uniq);
1.136     matthew  2966: }
                   2967: 
1.127     matthew  2968: ############################################################
                   2969: ############################################################
                   2970: 
                   2971: =pod
                   2972: 
1.134     matthew  2973: =item DrawBarGraph
1.127     matthew  2974: 
1.138     matthew  2975: Facilitates the plotting of data in a (stacked) bar graph.
                   2976: Puts plot definition data into the users environment in order for 
                   2977: graph.png to plot it.  Returns an <img> tag for the plot.
                   2978: The bars on the plot are labeled '1','2',...,'n'.
                   2979: 
                   2980: Inputs:
                   2981: 
                   2982: =over 4
                   2983: 
                   2984: =item $Title: string, the title of the plot
                   2985: 
                   2986: =item $xlabel: string, text describing the X-axis of the plot
                   2987: 
                   2988: =item $ylabel: string, text describing the Y-axis of the plot
                   2989: 
                   2990: =item $Max: scalar, the maximum Y value to use in the plot
                   2991: If $Max is < any data point, the graph will not be rendered.
                   2992: 
1.140     matthew  2993: =item $colors: array ref holding the colors to be used for the data sets when
1.138     matthew  2994: they are plotted.  If undefined, default values will be used.
                   2995: 
                   2996: =item @Values: An array of array references.  Each array reference holds data
                   2997: to be plotted in a stacked bar chart.
                   2998: 
                   2999: =back
                   3000: 
                   3001: Returns:
                   3002: 
                   3003: An <img> tag which references graph.png and the appropriate identifying
                   3004: information for the plot.
                   3005: 
1.127     matthew  3006: =cut
                   3007: 
                   3008: ############################################################
                   3009: ############################################################
1.134     matthew  3010: sub DrawBarGraph {
1.129     matthew  3011:     my ($Title,$xlabel,$ylabel,$Max,$colors,@Values)=@_;
1.134     matthew  3012:     #
                   3013:     if (! defined($colors)) {
                   3014:         $colors = ['#33ff00', 
                   3015:                   '#0033cc', '#990000', '#aaaa66', '#663399', '#ff9933',
                   3016:                   '#66ccff', '#ff9999', '#cccc33', '#660000', '#33cc66',
                   3017:                   ]; 
                   3018:     }
1.127     matthew  3019:     #
1.136     matthew  3020:     my $identifier = &get_cgi_id();
                   3021:     my $id = 'cgi.'.$identifier;        
1.129     matthew  3022:     if (! @Values || ref($Values[0]) ne 'ARRAY') {
1.127     matthew  3023:         return '';
                   3024:     }
1.129     matthew  3025:     my $NumBars = scalar(@{$Values[0]});
                   3026:     my %ValuesHash;
                   3027:     my $NumSets=1;
                   3028:     foreach my $array (@Values) {
                   3029:         next if (! ref($array));
1.136     matthew  3030:         $ValuesHash{$id.'.data.'.$NumSets++} = 
1.132     matthew  3031:             join(',',@$array);
1.129     matthew  3032:     }
1.127     matthew  3033:     #
1.136     matthew  3034:     my ($height,$width,$xskip,$bar_width) = (200,120,1,15);
                   3035:     if ($NumBars < 10) {
                   3036:         $width = 120+$NumBars*15;
                   3037:         $xskip = 1;
                   3038:         $bar_width = 15;
                   3039:     } elsif ($NumBars <= 25) {
                   3040:         $width = 120+$NumBars*11;
                   3041:         $xskip = 5;
                   3042:         $bar_width = 8;
                   3043:     } elsif ($NumBars <= 50) {
                   3044:         $width = 120+$NumBars*8;
                   3045:         $xskip = 5;
                   3046:         $bar_width = 4;
                   3047:     } else {
                   3048:         $width = 120+$NumBars*8;
                   3049:         $xskip = 5;
                   3050:         $bar_width = 4;
                   3051:     }
                   3052:     #
                   3053:     my @Labels;
                   3054:     for (my $i=0;$i<@{$Values[0]};$i++) {
                   3055:         push (@Labels,$i+1);
                   3056:     }
                   3057:     #
1.137     matthew  3058:     $Max = 1 if ($Max < 1);
                   3059:     if ( int($Max) < $Max ) {
                   3060:         $Max++;
                   3061:         $Max = int($Max);
                   3062:     }
1.127     matthew  3063:     $Title  = '' if (! defined($Title));
                   3064:     $xlabel = '' if (! defined($xlabel));
                   3065:     $ylabel = '' if (! defined($ylabel));
1.136     matthew  3066:     $ValuesHash{$id.'.title'}    = &Apache::lonnet::escape($Title);
                   3067:     $ValuesHash{$id.'.xlabel'}   = &Apache::lonnet::escape($xlabel);
                   3068:     $ValuesHash{$id.'.ylabel'}   = &Apache::lonnet::escape($ylabel);
1.137     matthew  3069:     $ValuesHash{$id.'.y_max_value'} = $Max;
1.136     matthew  3070:     $ValuesHash{$id.'.NumBars'}  = $NumBars;
                   3071:     $ValuesHash{$id.'.NumSets'}  = $NumSets;
                   3072:     $ValuesHash{$id.'.PlotType'} = 'bar';
                   3073:     $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
                   3074:     $ValuesHash{$id.'.height'}   = $height;
                   3075:     $ValuesHash{$id.'.width'}    = $width;
                   3076:     $ValuesHash{$id.'.xskip'}    = $xskip;
                   3077:     $ValuesHash{$id.'.bar_width'} = $bar_width;
                   3078:     $ValuesHash{$id.'.labels'} = join(',',@Labels);
1.127     matthew  3079:     #
1.137     matthew  3080:     &Apache::lonnet::appenv(%ValuesHash);
                   3081:     return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
                   3082: }
                   3083: 
                   3084: ############################################################
                   3085: ############################################################
                   3086: 
                   3087: =pod
                   3088: 
                   3089: =item DrawXYGraph
                   3090: 
1.138     matthew  3091: Facilitates the plotting of data in an XY graph.
                   3092: Puts plot definition data into the users environment in order for 
                   3093: graph.png to plot it.  Returns an <img> tag for the plot.
                   3094: 
                   3095: Inputs:
                   3096: 
                   3097: =over 4
                   3098: 
                   3099: =item $Title: string, the title of the plot
                   3100: 
                   3101: =item $xlabel: string, text describing the X-axis of the plot
                   3102: 
                   3103: =item $ylabel: string, text describing the Y-axis of the plot
                   3104: 
                   3105: =item $Max: scalar, the maximum Y value to use in the plot
                   3106: If $Max is < any data point, the graph will not be rendered.
                   3107: 
                   3108: =item $colors: Array ref containing the hex color codes for the data to be 
                   3109: plotted in.  If undefined, default values will be used.
                   3110: 
                   3111: =item $Xlabels: Array ref containing the labels to be used for the X-axis.
                   3112: 
                   3113: =item $Ydata: Array ref containing Array refs.  
                   3114: Each of the contained arrays will be plotted as a seperate curve.
                   3115: 
                   3116: =item %Values: hash indicating or overriding any default values which are 
                   3117: passed to graph.png.  
                   3118: Possible values are: width, xskip, x_ticks, x_tick_offset, among others.
                   3119: 
                   3120: =back
                   3121: 
                   3122: Returns:
                   3123: 
                   3124: An <img> tag which references graph.png and the appropriate identifying
                   3125: information for the plot.
                   3126: 
1.137     matthew  3127: =cut
                   3128: 
                   3129: ############################################################
                   3130: ############################################################
                   3131: sub DrawXYGraph {
                   3132:     my ($Title,$xlabel,$ylabel,$Max,$colors,$Xlabels,$Ydata,%Values)=@_;
                   3133:     #
                   3134:     # Create the identifier for the graph
                   3135:     my $identifier = &get_cgi_id();
                   3136:     my $id = 'cgi.'.$identifier;
                   3137:     #
                   3138:     $Title  = '' if (! defined($Title));
                   3139:     $xlabel = '' if (! defined($xlabel));
                   3140:     $ylabel = '' if (! defined($ylabel));
                   3141:     my %ValuesHash = 
                   3142:         (
                   3143:          $id.'.title'  => &Apache::lonnet::escape($Title),
                   3144:          $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
                   3145:          $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
                   3146:          $id.'.y_max_value'=> $Max,
                   3147:          $id.'.labels'     => join(',',@$Xlabels),
                   3148:          $id.'.PlotType'   => 'XY',
                   3149:          );
                   3150:     #
                   3151:     if (defined($colors) && ref($colors) eq 'ARRAY') {
                   3152:         $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
                   3153:     }
                   3154:     #
                   3155:     if (! ref($Ydata) || ref($Ydata) ne 'ARRAY') {
                   3156:         return '';
                   3157:     }
                   3158:     my $NumSets=1;
1.138     matthew  3159:     foreach my $array (@{$Ydata}){
1.137     matthew  3160:         next if (! ref($array));
                   3161:         $ValuesHash{$id.'.data.'.$NumSets++} = join(',',@$array);
                   3162:     }
1.138     matthew  3163:     $ValuesHash{$id.'.NumSets'} = $NumSets-1;
1.137     matthew  3164:     #
                   3165:     # Deal with other parameters
                   3166:     while (my ($key,$value) = each(%Values)) {
                   3167:         $ValuesHash{$id.'.'.$key} = $value;
1.127     matthew  3168:     }
                   3169:     #
1.136     matthew  3170:     &Apache::lonnet::appenv(%ValuesHash);
                   3171:     return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
                   3172: }
                   3173: 
                   3174: ############################################################
                   3175: ############################################################
                   3176: 
                   3177: =pod
                   3178: 
1.138     matthew  3179: =item DrawXYYGraph
                   3180: 
                   3181: Facilitates the plotting of data in an XY graph with two Y axes.
                   3182: Puts plot definition data into the users environment in order for 
                   3183: graph.png to plot it.  Returns an <img> tag for the plot.
                   3184: 
                   3185: Inputs:
                   3186: 
                   3187: =over 4
                   3188: 
                   3189: =item $Title: string, the title of the plot
                   3190: 
                   3191: =item $xlabel: string, text describing the X-axis of the plot
                   3192: 
                   3193: =item $ylabel: string, text describing the Y-axis of the plot
                   3194: 
                   3195: =item $colors: Array ref containing the hex color codes for the data to be 
                   3196: plotted in.  If undefined, default values will be used.
                   3197: 
                   3198: =item $Xlabels: Array ref containing the labels to be used for the X-axis.
                   3199: 
                   3200: =item $Ydata1: The first data set
                   3201: 
                   3202: =item $Min1: The minimum value of the left Y-axis
                   3203: 
                   3204: =item $Max1: The maximum value of the left Y-axis
                   3205: 
                   3206: =item $Ydata2: The second data set
                   3207: 
                   3208: =item $Min2: The minimum value of the right Y-axis
                   3209: 
                   3210: =item $Max2: The maximum value of the left Y-axis
                   3211: 
                   3212: =item %Values: hash indicating or overriding any default values which are 
                   3213: passed to graph.png.  
                   3214: Possible values are: width, xskip, x_ticks, x_tick_offset, among others.
                   3215: 
                   3216: =back
                   3217: 
                   3218: Returns:
                   3219: 
                   3220: An <img> tag which references graph.png and the appropriate identifying
                   3221: information for the plot.
1.136     matthew  3222: 
                   3223: =cut
                   3224: 
                   3225: ############################################################
                   3226: ############################################################
1.137     matthew  3227: sub DrawXYYGraph {
                   3228:     my ($Title,$xlabel,$ylabel,$colors,$Xlabels,$Ydata1,$Min1,$Max1,
                   3229:                                         $Ydata2,$Min2,$Max2,%Values)=@_;
1.136     matthew  3230:     #
                   3231:     # Create the identifier for the graph
                   3232:     my $identifier = &get_cgi_id();
                   3233:     my $id = 'cgi.'.$identifier;
                   3234:     #
                   3235:     $Title  = '' if (! defined($Title));
                   3236:     $xlabel = '' if (! defined($xlabel));
                   3237:     $ylabel = '' if (! defined($ylabel));
                   3238:     my %ValuesHash = 
                   3239:         (
                   3240:          $id.'.title'  => &Apache::lonnet::escape($Title),
                   3241:          $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
                   3242:          $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
                   3243:          $id.'.labels' => join(',',@$Xlabels),
                   3244:          $id.'.PlotType' => 'XY',
                   3245:          $id.'.NumSets' => 2,
1.137     matthew  3246:          $id.'.two_axes' => 1,
                   3247:          $id.'.y1_max_value' => $Max1,
                   3248:          $id.'.y1_min_value' => $Min1,
                   3249:          $id.'.y2_max_value' => $Max2,
                   3250:          $id.'.y2_min_value' => $Min2,
1.136     matthew  3251:          );
                   3252:     #
1.137     matthew  3253:     if (defined($colors) && ref($colors) eq 'ARRAY') {
                   3254:         $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
                   3255:     }
                   3256:     #
                   3257:     if (! ref($Ydata1) || ref($Ydata1) ne 'ARRAY' ||
                   3258:         ! ref($Ydata2) || ref($Ydata2) ne 'ARRAY'){
1.136     matthew  3259:         return '';
                   3260:     }
                   3261:     my $NumSets=1;
1.137     matthew  3262:     foreach my $array ($Ydata1,$Ydata2){
1.136     matthew  3263:         next if (! ref($array));
                   3264:         $ValuesHash{$id.'.data.'.$NumSets++} = join(',',@$array);
1.137     matthew  3265:     }
                   3266:     #
                   3267:     # Deal with other parameters
                   3268:     while (my ($key,$value) = each(%Values)) {
                   3269:         $ValuesHash{$id.'.'.$key} = $value;
1.136     matthew  3270:     }
                   3271:     #
                   3272:     &Apache::lonnet::appenv(%ValuesHash);
1.130     albertel 3273:     return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
1.139     matthew  3274: }
                   3275: 
                   3276: ############################################################
                   3277: ############################################################
                   3278: 
                   3279: =pod
                   3280: 
1.157     matthew  3281: =back 
                   3282: 
1.139     matthew  3283: =head1 Statistics helper routines?  
                   3284: 
                   3285: Bad place for them but what the hell.
                   3286: 
1.157     matthew  3287: =over 4
                   3288: 
1.139     matthew  3289: =item &chartlink
                   3290: 
                   3291: Returns a link to the chart for a specific student.  
                   3292: 
                   3293: Inputs:
                   3294: 
                   3295: =over 4
                   3296: 
                   3297: =item $linktext: The text of the link
                   3298: 
                   3299: =item $sname: The students username
                   3300: 
                   3301: =item $sdomain: The students domain
                   3302: 
                   3303: =back
                   3304: 
1.157     matthew  3305: =back
                   3306: 
1.139     matthew  3307: =cut
                   3308: 
                   3309: ############################################################
                   3310: ############################################################
                   3311: sub chartlink {
                   3312:     my ($linktext, $sname, $sdomain) = @_;
                   3313:     my $link = '<a href="/adm/statistics?reportSelected=student_assessment'.
                   3314:         '&SelectedStudent='.&Apache::lonnet::escape($sname.':'.$sdomain).
                   3315:         '&chartoutputmode='.HTML::Entities::encode('html, with all links').
                   3316:        '">'.$linktext.'</a>';
1.153     matthew  3317: }
                   3318: 
                   3319: #######################################################
                   3320: #######################################################
                   3321: 
                   3322: =pod
                   3323: 
                   3324: =head1 Course Environment Routines
1.157     matthew  3325: 
                   3326: =over 4
1.153     matthew  3327: 
                   3328: =item &restore_course_settings 
                   3329: 
                   3330: =item &store_course_settings
                   3331: 
                   3332: Restores/Store indicated form parameters from the course environment.
                   3333: Will not overwrite existing values of the form parameters.
                   3334: 
                   3335: Inputs: 
                   3336: a scalar describing the data (e.g. 'chart', 'problem_analysis')
                   3337: 
                   3338: a hash ref describing the data to be stored.  For example:
                   3339:    
                   3340: %Save_Parameters = ('Status' => 'scalar',
                   3341:     'chartoutputmode' => 'scalar',
                   3342:     'chartoutputdata' => 'scalar',
                   3343:     'Section' => 'array',
                   3344:     'StudentData' => 'array',
                   3345:     'Maps' => 'array');
                   3346: 
                   3347: Returns: both routines return nothing
                   3348: 
                   3349: =cut
                   3350: 
                   3351: #######################################################
                   3352: #######################################################
                   3353: sub store_course_settings {
                   3354:     # save to the environment
                   3355:     # appenv the same items, just to be safe
                   3356:     my $courseid = $ENV{'request.course.id'};
                   3357:     my $coursedom = $ENV{'course.'.$courseid.'.domain'};
                   3358:     my ($prefix,$Settings) = @_;
                   3359:     my %SaveHash;
                   3360:     my %AppHash;
                   3361:     while (my ($setting,$type) = each(%$Settings)) {
                   3362:         my $basename = 'env.internal.'.$prefix.'.'.$setting;
                   3363:         my $envname = 'course.'.$courseid.'.'.$basename;
                   3364:         if (exists($ENV{'form.'.$setting})) {
                   3365:             # Save this value away
                   3366:             if ($type eq 'scalar' &&
                   3367:                 (! exists($ENV{$envname}) || 
                   3368:                  $ENV{$envname} ne $ENV{'form.'.$setting})) {
                   3369:                 $SaveHash{$basename} = $ENV{'form.'.$setting};
                   3370:                 $AppHash{$envname}   = $ENV{'form.'.$setting};
                   3371:             } elsif ($type eq 'array') {
                   3372:                 my $stored_form;
                   3373:                 if (ref($ENV{'form.'.$setting})) {
                   3374:                     $stored_form = join(',',
                   3375:                                         map {
                   3376:                                             &Apache::lonnet::escape($_);
                   3377:                                         } sort(@{$ENV{'form.'.$setting}}));
                   3378:                 } else {
                   3379:                     $stored_form = 
                   3380:                         &Apache::lonnet::escape($ENV{'form.'.$setting});
                   3381:                 }
                   3382:                 # Determine if the array contents are the same.
                   3383:                 if ($stored_form ne $ENV{$envname}) {
                   3384:                     $SaveHash{$basename} = $stored_form;
                   3385:                     $AppHash{$envname}   = $stored_form;
                   3386:                 }
                   3387:             }
                   3388:         }
                   3389:     }
                   3390:     my $put_result = &Apache::lonnet::put('environment',\%SaveHash,
                   3391:                                           $coursedom,
                   3392:                                           $ENV{'course.'.$courseid.'.num'});
                   3393:     if ($put_result !~ /^(ok|delayed)/) {
                   3394:         &Apache::lonnet::logthis('unable to save form parameters, '.
                   3395:                                  'got error:'.$put_result);
                   3396:     }
                   3397:     # Make sure these settings stick around in this session, too
                   3398:     &Apache::lonnet::appenv(%AppHash);
                   3399:     return;
                   3400: }
                   3401: 
                   3402: sub restore_course_settings {
                   3403:     my $courseid = $ENV{'request.course.id'};
                   3404:     my ($prefix,$Settings) = @_;
                   3405:     while (my ($setting,$type) = each(%$Settings)) {
                   3406:         next if (exists($ENV{'form.'.$setting}));
                   3407:         my $envname = 'course.'.$courseid.'.env.internal.'.$prefix.
                   3408:             '.'.$setting;
                   3409:         if (exists($ENV{$envname})) {
                   3410:             if ($type eq 'scalar') {
                   3411:                 $ENV{'form.'.$setting} = $ENV{$envname};
                   3412:             } elsif ($type eq 'array') {
                   3413:                 $ENV{'form.'.$setting} = [ 
                   3414:                                            map { 
                   3415:                                                &Apache::lonnet::unescape($_); 
                   3416:                                            } split(',',$ENV{$envname})
                   3417:                                            ];
                   3418:             }
                   3419:         }
                   3420:     }
1.127     matthew  3421: }
                   3422: 
                   3423: ############################################################
                   3424: ############################################################
1.154     albertel 3425: 
                   3426: sub propath {
                   3427:     my ($udom,$uname)=@_;
                   3428:     $udom=~s/\W//g;
                   3429:     $uname=~s/\W//g;
                   3430:     my $subdir=$uname.'__';
                   3431:     $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/;
                   3432:     my $proname="$Apache::lonnet::perlvar{'lonUsersDir'}/$udom/$subdir/$uname";
                   3433:     return $proname;
1.156     albertel 3434: } 
                   3435: 
                   3436: sub icon {
                   3437:     my ($file)=@_;
1.168     albertel 3438:     my $curfext = (split(/\./,$file))[-1];
                   3439:     my $iconname=$Apache::lonnet::perlvar{'lonIconsURL'}.'/unknown.gif';
1.156     albertel 3440:     my $embstyle = &Apache::loncommon::fileembstyle($curfext);
1.168     albertel 3441:     if (!(!defined($embstyle) || $embstyle eq 'unk' || $embstyle eq 'hdn')) {
                   3442: 	if (-e  $Apache::lonnet::perlvar{'lonDocRoot'}.'/'.
                   3443: 	          $Apache::lonnet::perlvar{'lonIconsURL'}.'/'.
                   3444: 	            $curfext.".gif") {
                   3445: 	    $iconname=$Apache::lonnet::perlvar{'lonIconsURL'}.'/'.
                   3446: 		$curfext.".gif";
                   3447: 	}
                   3448:     }
                   3449:     return $iconname;
1.154     albertel 3450: } 
1.84      albertel 3451: 
1.41      ng       3452: =pod
                   3453: 
                   3454: =back
                   3455: 
1.112     bowersj2 3456: =cut
1.41      ng       3457: 
1.112     bowersj2 3458: 1;
                   3459: __END__;
1.41      ng       3460: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.