Annotation of loncom/interface/lonpreferences.pm, revision 1.179.2.5

1.1       www         1: # The LearningOnline Network
                      2: # Preferences
                      3: #
1.179.2.5! raeburn     4: # $Id: lonpreferences.pm,v 1.179.2.4 2010/09/19 14:22:40 raeburn Exp $
1.2       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.3       matthew    28: # This package uses the "londes.js" javascript code. 
                     29: #
                     30: # TODOs that have to be completed:
                     31: #    interface with lonnet to change the password
                     32:  
1.1       www        33: package Apache::lonpreferences;
                     34: 
                     35: use strict;
1.86      albertel   36: use LONCAPA;
1.1       www        37: use Apache::Constants qw(:common);
1.3       matthew    38: use Apache::File;
                     39: use Crypt::DES;
                     40: use DynaLoader; # for Crypt::DES version
1.4       matthew    41: use Apache::loncommon();
1.23      matthew    42: use Apache::lonhtmlcommon();
1.32      www        43: use Apache::lonlocal;
1.59      albertel   44: use Apache::lonnet;
1.174     raeburn    45: use LONCAPA::lonauthcgi();
1.95      albertel   46: use LONCAPA();
1.3       matthew    47: 
                     48: #
                     49: # Write lonnet::passwd to do the call below.
                     50: # Use:
                     51: #   my $answer=reply("encrypt:passwd:$udom:$uname:$upass",$tryserver);
                     52: #
                     53: ##################################################
                     54: #          password associated functions         #
                     55: ##################################################
                     56: sub des_keys {
1.4       matthew    57:     # Make a new key for DES encryption.
1.36      www        58:     # Each key has two parts which are returned separately.
1.4       matthew    59:     # Please note:  Each key must be passed through the &hex function
                     60:     # before it is output to the web browser.  The hex versions cannot
                     61:     # be used to decrypt.
1.3       matthew    62:     my @hexstr=('0','1','2','3','4','5','6','7',
                     63:                 '8','9','a','b','c','d','e','f');
                     64:     my $lkey='';
                     65:     for (0..7) {
                     66:         $lkey.=$hexstr[rand(15)];
                     67:     }
                     68:     my $ukey='';
                     69:     for (0..7) {
                     70:         $ukey.=$hexstr[rand(15)];
                     71:     }
                     72:     return ($lkey,$ukey);
                     73: }
                     74: 
                     75: sub des_decrypt {
                     76:     my ($key,$cyphertext) = @_;
                     77:     my $keybin=pack("H16",$key);
                     78:     my $cypher;
                     79:     if ($Crypt::DES::VERSION>=2.03) {
                     80:         $cypher=new Crypt::DES $keybin;
                     81:     } else {
                     82:         $cypher=new DES $keybin;
                     83:     }
                     84:     my $plaintext=
                     85: 	$cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,0,16))));
                     86:     $plaintext.=
                     87: 	$cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,16,16))));
1.4       matthew    88:     $plaintext=substr($plaintext,1,ord(substr($plaintext,0,1)) );
1.3       matthew    89:     return $plaintext;
                     90: }
                     91: 
1.4       matthew    92: ################################################################
                     93: #                       Handler subroutines                    #
                     94: ################################################################
1.9       matthew    95: 
                     96: ################################################################
1.28      www        97: #         Language Change Subroutines                          #
                     98: ################################################################
1.44      www        99: 
                    100: sub wysiwygchanger {
                    101:     my $r = shift;
1.126     droeschl  102:     Apache::lonhtmlcommon::add_breadcrumb(
                    103: 	    {	href => '/adm/preferences?action=changewysiwyg',
                    104:                 text => 'Change WYSIWYG Preferences'});
1.147     schafran  105:     $r->print(Apache::loncommon::start_page('Content Display Settings'));
1.126     droeschl  106:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change WYSIWYG Preferences'));
                    107: 
1.44      www       108:     my %userenv = &Apache::lonnet::get
                    109:         ('environment',['wysiwygeditor']);
1.78      albertel  110:     my $onselect='checked="checked"';
1.44      www       111:     my $offselect='';
1.77      albertel  112:     if ($userenv{'wysiwygeditor'} eq 'on') {
1.44      www       113: 	$onselect='';
1.78      albertel  114: 	$offselect='checked="checked"';
1.44      www       115:     }
                    116:     my $switchoff=&mt('Disable WYSIWYG editor');
                    117:     my $switchon=&mt('Enable WYSIWYG editor');
1.124     www       118:     my $warning='';
                    119:     if ($env{'user.adv'}) {
                    120:        $warning.="<p>".&mt("The WYSIWYG editor only supports simple HTML and is in many cases unsuited for advanced authoring. In a number of cases, it may destroy advanced authoring involving LaTeX and script function calls.")."</p>";
                    121:     }
1.44      www       122:     $r->print(<<ENDLSCREEN);
1.88      albertel  123: <form name="prefs" action="/adm/preferences" method="post">
1.44      www       124: <input type="hidden" name="action" value="set_wysiwyg" />
1.124     www       125: $warning
1.44      www       126: <br />
1.65      albertel  127: <label><input type="radio" name="wysiwyg" value="off" $onselect /> $switchoff</label><br />
                    128: <label><input type="radio" name="wysiwyg" value="on" $offselect /> $switchon</label>
1.44      www       129: ENDLSCREEN
1.136     schafran  130:     $r->print('<br /><input type="submit" value="'.&mt('Save').'" />');
1.44      www       131: }
                    132: 
                    133: 
                    134: sub verify_and_change_wysiwyg {
                    135:     my $r = shift;
1.59      albertel  136:     my $newsetting=$env{'form.wysiwyg'};
1.44      www       137:     &Apache::lonnet::put('environment',{'wysiwygeditor' => $newsetting});
1.116     raeburn   138:     &Apache::lonnet::appenv({'environment.wysiwygeditor' => $newsetting});
1.158     bisitz    139:     my $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.&mt('WYSIWYG Editor').'</i>','<tt>'.&mt($newsetting).'</tt>'));
                    140:     $message=&Apache::loncommon::confirmwrapper($message);
                    141:     &print_main_menu($r,$message);
1.44      www       142: }
                    143: 
                    144: ################################################################
                    145: #         Language Change Subroutines                          #
                    146: ################################################################
1.28      www       147: sub languagechanger {
                    148:     my $r = shift;
1.126     droeschl  149:     
                    150:     Apache::lonhtmlcommon::add_breadcrumb(
                    151: 	    {	href => '/adm/preferences?action=changelanguages',
1.127     droeschl  152:                 text => 'Change Language'});
1.147     schafran  153:     $r->print(Apache::loncommon::start_page('Content Display Settings'));
1.126     droeschl  154:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Language')); 
1.59      albertel  155:     my $user       = $env{'user.name'};
                    156:     my $domain     = $env{'user.domain'};
1.28      www       157:     my %userenv = &Apache::lonnet::get
1.32      www       158:         ('environment',['languages']);
1.29      www       159:     my $language=$userenv{'languages'};
1.32      www       160: 
1.33      www       161:     my $pref=&mt('Preferred language');
                    162:     my %langchoices=('' => 'No language preference');
                    163:     foreach (&Apache::loncommon::languageids()) {
                    164: 	if (&Apache::loncommon::supportedlanguagecode($_)) {
                    165: 	    $langchoices{&Apache::loncommon::supportedlanguagecode($_)}
                    166: 	               = &Apache::loncommon::plainlanguagedescription($_);
                    167: 	}
                    168:     }
1.179     bisitz    169:     my $selectionbox=
                    170:            &Apache::loncommon::select_form(
                    171:                $language,
                    172:                'language',
                    173:                &Apache::lonlocal::texthash(%langchoices));
1.28      www       174:     $r->print(<<ENDLSCREEN);
1.88      albertel  175: <form name="prefs" action="/adm/preferences" method="post">
1.28      www       176: <input type="hidden" name="action" value="verify_and_change_languages" />
1.33      www       177: <br />$pref: $selectionbox
1.28      www       178: ENDLSCREEN
1.136     schafran  179:     $r->print('<br /><input type="submit" value="'.&mt('Save').'" />');
1.28      www       180: }
                    181: 
                    182: 
                    183: sub verify_and_change_languages {
                    184:     my $r = shift;
1.59      albertel  185:     my $user       = $env{'user.name'};
                    186:     my $domain     = $env{'user.domain'};
1.28      www       187: # Screenname
1.59      albertel  188:     my $newlanguage  = $env{'form.language'};
1.28      www       189:     $newlanguage=~s/[^\-\w]//g;
                    190:     my $message='';
                    191:     if ($newlanguage) {
1.29      www       192:         &Apache::lonnet::put('environment',{'languages' => $newlanguage});
1.116     raeburn   193:         &Apache::lonnet::appenv({'environment.languages' => $newlanguage});
1.158     bisitz    194:         $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.&mt('Preferred language').'</i>','<tt>"'.$newlanguage.'"</tt>.'));
1.28      www       195:     } else {
1.29      www       196:         &Apache::lonnet::del('environment',['languages']);
1.139     raeburn   197:         &Apache::lonnet::delenv('environment.languages');
1.158     bisitz    198:         $message=&Apache::lonhtmlcommon::confirm_success(&mt('Reset [_1]','<i>'.&mt('Preferred language').'</i>'));
1.28      www       199:     }
1.158     bisitz    200:     $message=&Apache::loncommon::confirmwrapper($message);
1.132     raeburn   201:     &Apache::loncommon::flush_langs_cache($user,$domain);
1.152     www       202:     &print_main_menu($r, $message);
1.28      www       203: }
                    204: 
1.50      albertel  205: ################################################################
1.54      albertel  206: #         Tex Engine Change Subroutines                        #
                    207: ################################################################
                    208: sub texenginechanger {
                    209:     my $r = shift;
1.126     droeschl  210:     Apache::lonhtmlcommon::add_breadcrumb(
                    211: 	    {	href => '/adm/preferences?action=changetexenginepref',
1.177     raeburn   212:                 text => 'Math display settings'});
1.147     schafran  213:     $r->print(Apache::loncommon::start_page('Content Display Settings'));
1.177     raeburn   214:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Math display settings'));
1.59      albertel  215:     my $user       = $env{'user.name'};
                    216:     my $domain     = $env{'user.domain'};
1.54      albertel  217:     my %userenv = &Apache::lonnet::get('environment',['texengine']);
                    218:     my $texengine=$userenv{'texengine'};
                    219: 
1.69      albertel  220:     my %mathchoices=('' => 'Default',
1.123     bisitz    221: 		     'tth' => 'tth (TeX to HTML)',
1.64      albertel  222: 		     #'ttm' => 'TeX to MathML',
1.54      albertel  223: 		     'jsMath' => 'jsMath',
1.168     www       224: 		     'mimetex' => 'mimetex (Convert to Images)',
                    225:                      'raw' => 'Raw (Screen Reader)'
1.54      albertel  226:                      );
1.179     bisitz    227:     my $selectionbox=
                    228:            &Apache::loncommon::select_form(
                    229:                $texengine,
                    230:                'texengine',
                    231:                &Apache::lonlocal::texthash(%mathchoices));
1.67      albertel  232:     my $jsMath_start=&Apache::lontexconvert::jsMath_header();
1.123     bisitz    233:     my %lt=&Apache::lonlocal::texthash(
1.177     raeburn   234:       'headline' => 'Change how math is displayed',
                    235:       'preftxt'  => 'Preferred method to display math',
1.136     schafran  236:       'change'   => 'Save',
1.123     bisitz    237:       'exmpl'    => 'Examples',
                    238:       'jsmath'   => 'jsMath:',
                    239:       'tth'      => 'tth (TeX to HTML):',
                    240:       'mimetex'  => 'mimetex (Convert to Images):',
                    241:     );
                    242: 
1.162     bisitz    243:     my $jsMathWarning='<p>'
                    244:                      .'<div class="LC_warning">'
                    245:                      .&mt("It looks like you don't have the TeX math fonts installed.")
                    246:                      .'</div>'
                    247:                      .'<div>'
                    248:                      .&mt('The jsMath example on this page may not look right without them. '
                    249:                          .'The [_1]jsMath Home Page[_2] has information on how to download the '
                    250:                          .'needed fonts. In the meantime, jsMath will do the best it can '
                    251:                          .'with the fonts you have, but it may not be pretty and some equations '
                    252:                          .'may not be rendered correctly.'
                    253:                          ,'<a href="http://www.math.union.edu/locate/jsMath/" target="_blank">'
                    254:                          ,'</a>')
                    255:                      .'</div>'
                    256:                      .'</p>';
                    257: 
1.54      albertel  258:     $r->print(<<ENDLSCREEN);
1.123     bisitz    259: <h2>$lt{'headline'}</h2>
1.88      albertel  260: <form name="prefs" action="/adm/preferences" method="post">
1.54      albertel  261: <input type="hidden" name="action" value="verify_and_change_texengine" />
1.123     bisitz    262: <p>
1.136     schafran  263: $lt{'preftxt'}: $selectionbox 
                    264: <br />
                    265: <input type="submit" value="$lt{'change'}" />
1.123     bisitz    266: </p>
1.54      albertel  267: </form>
1.123     bisitz    268: <br />
                    269: <hr />
                    270: $lt{'exmpl'}
                    271: 
                    272: <h3>$lt{'jsmath'}</h3> 
                    273: <p>
1.67      albertel  274: $jsMath_start
1.148     bisitz    275: <script type="text/javascript" language="JavaScript">
1.54      albertel  276: if (jsMath.nofonts == 1) {
1.162     bisitz    277:     document.writeln($jsMathWarning);
1.54      albertel  278: }
                    279: </script>
1.122     www       280: <iframe src="/res/adm/pages/math_example.tex?inhibitmenu=yes&texengine=jsMath" width="400" height="120"></iframe>
1.123     bisitz    281: </p>
1.54      albertel  282: 
1.123     bisitz    283: <h3>$lt{'mimetex'}</h3>
                    284: <p>
                    285: <iframe src="/res/adm/pages/math_example.tex?inhibitmenu=yes&texengine=mimetex" width="400" height="100"></iframe>
1.67      albertel  286: </p>
1.123     bisitz    287: 
                    288: <h3>$lt{'tth'}</h3>
                    289: <p>
1.177     raeburn   290: <iframe src="/res/adm/pages/math_example.tex?inhibitmenu=yes&texengine=tth" width="400" height="220"></iframe>
1.67      albertel  291: </p>
1.54      albertel  292: ENDLSCREEN
1.59      albertel  293:     if ($env{'environment.texengine'} ne 'jsMath') {
1.148     bisitz    294: 	$r->print('<script type="text/javascript" language="JavaScript">jsMath.Process()</script>');
1.55      albertel  295:     }
1.54      albertel  296: }
                    297: 
                    298: 
                    299: sub verify_and_change_texengine {
                    300:     my $r = shift;
1.59      albertel  301:     my $user       = $env{'user.name'};
                    302:     my $domain     = $env{'user.domain'};
1.54      albertel  303: # Screenname
1.59      albertel  304:     my $newtexengine  = $env{'form.texengine'};
1.54      albertel  305:     $newtexengine=~s/[^\-\w]//g;
1.56      albertel  306:     if ($newtexengine eq 'ttm') {
1.116     raeburn   307: 	&Apache::lonnet::appenv({'browser.mathml' => 1});
1.56      albertel  308:     } else {
1.59      albertel  309: 	if ($env{'environment.texengine'} eq 'ttm') {
1.116     raeburn   310: 	    &Apache::lonnet::appenv({'browser.mathml' => 0});
1.56      albertel  311: 	}
                    312:     }
1.54      albertel  313:     my $message='';
                    314:     if ($newtexengine) {
                    315:         &Apache::lonnet::put('environment',{'texengine' => $newtexengine});
1.116     raeburn   316:         &Apache::lonnet::appenv({'environment.texengine' => $newtexengine});
1.158     bisitz    317:         $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.&mt('Preferred method to display Math').'</i>','<tt>"'.$newtexengine.'"</tt>'));
1.54      albertel  318:     } else {
                    319:         &Apache::lonnet::del('environment',['texengine']);
1.139     raeburn   320:         &Apache::lonnet::delenv('environment.texengine');
1.158     bisitz    321:         $message=&Apache::lonhtmlcommon::confirm_success(&mt('Reset [_1]','<i>'.&mt('Preferred method to display Math').'</i>'));
1.54      albertel  322:     }
1.158     bisitz    323:     $message=&Apache::loncommon::confirmwrapper($message);
1.152     www       324:     &print_main_menu($r, $message);
1.54      albertel  325: }
                    326: 
                    327: ################################################################
1.50      albertel  328: #         Roles Page Preference Change Subroutines         #
                    329: ################################################################
                    330: sub rolesprefchanger {
                    331:     my $r = shift;
1.96      albertel  332:     my $role    = ($env{'user.adv'} ? 'Role' : 'Course');
                    333:     my $lc_role = ($env{'user.adv'} ? 'role' : 'course');
1.59      albertel  334:     my $user       = $env{'user.name'};
                    335:     my $domain     = $env{'user.domain'};
1.50      albertel  336:     my %userenv = &Apache::lonnet::get
                    337:         ('environment',['recentroles','recentrolesn']);
1.126     droeschl  338:     Apache::lonhtmlcommon::add_breadcrumb(
                    339: 	    {	href => '/adm/preferences?action=changerolespref',
                    340:                 text => 'Change '.$role.' Page Pref'});
1.147     schafran  341:     $r->print(Apache::loncommon::start_page('Content Display Settings'));
1.126     droeschl  342:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change '.$role.' Page Pref'));
1.50      albertel  343:     my $hotlist_flag=$userenv{'recentroles'};
                    344:     my $hotlist_n=$userenv{'recentrolesn'};
                    345:     my $checked;
                    346:     if ($hotlist_flag) {
                    347: 	$checked = 'checked="checked"';
                    348:     }
                    349:     
                    350:     if (!$hotlist_n) { $hotlist_n=3; }
                    351:     my $options;
                    352:     for (my $i=1; $i<10; $i++) {
                    353: 	my $select;
                    354: 	if ($hotlist_n == $i) { $select = 'selected="selected"'; }
                    355: 	$options .= "<option $select>$i</option>\n";
                    356:     }
                    357: 
1.89      albertel  358: # Get list of recent roles and display with checkbox in front
                    359:     my $roles_check_list = '';
                    360:     my $role_key='';
                    361:     if ($env{'environment.recentroles'}) {
                    362:         my %recent_roles =
                    363:                &Apache::lonhtmlcommon::get_recent('roles',$env{'environment.recentrolesn'});
1.91      albertel  364:         my %frozen_roles =
                    365:                &Apache::lonhtmlcommon::get_recent_frozen('roles',$env{'environment.recentrolesn'});
1.89      albertel  366:         
1.93      albertel  367:         my %role_text = &rolespref_get_role_text([keys(%recent_roles)]);
1.92      albertel  368:         my @sorted_roles = sort {$role_text{$a} cmp $role_text{$b}} keys(%role_text);
                    369: 
1.89      albertel  370:         $roles_check_list .=
                    371: 	    &Apache::loncommon::start_data_table().
                    372: 	    &Apache::loncommon::start_data_table_header_row().
1.96      albertel  373: 	    "<th>".&mt('Freeze '.$role)."</th>".
                    374: 	    "<th>".&mt($role)."</td>".
1.89      albertel  375: 	    &Apache::loncommon::end_data_table_header_row().
                    376: 	    "\n";
                    377: 	my $count;
1.92      albertel  378:         foreach $role_key (@sorted_roles) {
1.89      albertel  379:             my $checked = "";
                    380:             my $value = $recent_roles{$role_key};
1.91      albertel  381:             if ($frozen_roles{$role_key}) {
1.159     bisitz    382:                 $checked = ' checked="checked"';
1.89      albertel  383:             }
                    384: 	    $count++;
                    385:             $roles_check_list .=
                    386: 		&Apache::loncommon::start_data_table_row().
                    387: 		'<td class="LC_table_cell_checkbox">'.
1.159     bisitz    388: 		"<input type=\"checkbox\"$checked name=\"freezeroles\"".
1.89      albertel  389: 		" id=\"freezeroles$count\" value=\"$role_key\" /></td>".
                    390: 		"<td><label for=\"freezeroles$count\">".
1.92      albertel  391: 		"$role_text{$role_key}</label></td>".
1.89      albertel  392: 		&Apache::loncommon::end_data_table_row(). "\n";
                    393:         }
                    394:         $roles_check_list .= "</table>\n";
                    395:     }
                    396: 
                    397:     $r->print('
1.96      albertel  398: <p>'.&mt('Some LON-CAPA users have a long list of '.$lc_role.'s. The Recent '.$role.'s Hotlist feature keeps track of the last N '.$lc_role.'s which have been visited and places a table of these at the top of the '.$lc_role.'s page. People with very few '.$lc_role.'s should leave this feature disabled.').'
1.50      albertel  399: </p>
1.160     bisitz    400: <form name="prefs" action="/adm/preferences" method="post">
1.50      albertel  401: <input type="hidden" name="action" value="verify_and_change_rolespref" />
1.96      albertel  402: <br /><label>'.&mt('Enable Recent '.$role.'s Hotlist:').'
1.159     bisitz    403: <input type="checkbox"'.$checked.' name="recentroles" value="true" /></label>
1.96      albertel  404: <br />'.&mt('Number of '.$role.'s in Hotlist:').'
1.50      albertel  405: <select name="recentrolesn" size="1">
1.89      albertel  406: '.$options.'
1.50      albertel  407: </select>
1.96      albertel  408: <p>'.&mt('This list below can be used to <q>freeze</q> '.$lc_role.'s on your screen. Those marked as frozen will not be removed from the list, even if they have not been used recently.').'
1.89      albertel  409: </p>
                    410: '.$roles_check_list.'
1.50      albertel  411: <br />
1.136     schafran  412: <input type="submit" value="'.&mt('Save').'" />
1.89      albertel  413: </form>');
1.50      albertel  414: }
                    415: 
1.92      albertel  416: sub rolespref_get_role_text {
                    417: # Get a line of text for each role
                    418:     my ($roles) = @_;
                    419:     my %roletext = ();
                    420: 
                    421:     foreach my $item (@$roles) {
                    422: # get course information
                    423:         my ($role,$rest) = split(/\./, $item);
1.93      albertel  424:         my $trole = "";
                    425:         $trole = &Apache::lonnet::plaintext($role);
1.92      albertel  426:         my ($tdomain,$other,$tsection)= split(/\//,Apache::lonnet::declutter($rest));
                    427:         my $tother = '-';
1.93      albertel  428:         if ($role =~ /^(cc|st|in|ta|ep|cr)/ ) {
1.92      albertel  429:             my %newhash=&Apache::lonnet::coursedescription($tdomain."_".$other);
                    430:             $tother = " - ".$newhash{'description'};
                    431:         } elsif ($role =~ /dc/) {
                    432:             $tother = "";
                    433:         } else {
                    434:             $tother = " - $other";
                    435:         }
                    436:  
                    437:         my $section="";
                    438:         if ($tsection) {
                    439:             $section = " - Section/Group: $tsection";
                    440:         }
                    441:         $roletext{$item} = $tdomain." - ".$trole.$tother.$section;
                    442:     }
                    443:     return %roletext;
                    444: }
                    445: 
1.50      albertel  446: sub verify_and_change_rolespref {
                    447:     my $r = shift;
1.96      albertel  448:     my $role = ($env{'user.adv'} ? 'Role' : 'Course');
1.59      albertel  449:     my $user       = $env{'user.name'};
                    450:     my $domain     = $env{'user.domain'};
1.50      albertel  451: # Recent Roles Hotlist Flag
1.59      albertel  452:     my $hotlist_flag  = $env{'form.recentroles'};
                    453:     my $hotlist_n  = $env{'form.recentrolesn'};
1.89      albertel  454:     my $message='<hr />';
1.50      albertel  455:     if ($hotlist_flag) {
                    456:         &Apache::lonnet::put('environment',{'recentroles' => $hotlist_flag});
1.116     raeburn   457:         &Apache::lonnet::appenv({'environment.recentroles' => $hotlist_flag});
1.96      albertel  458:         $message=&mt('Recent '.$role.'s Hotlist is Enabled');
1.50      albertel  459:     } else {
                    460:         &Apache::lonnet::del('environment',['recentroles']);
1.139     raeburn   461:         &Apache::lonnet::delenv('environment.recentroles');
1.96      albertel  462:         $message=&mt('Recent '.$role.'s Hotlist is Disabled');
1.50      albertel  463:     }
                    464:     if ($hotlist_n) {
                    465:         &Apache::lonnet::put('environment',{'recentrolesn' => $hotlist_n});
1.116     raeburn   466:         &Apache::lonnet::appenv({'environment.recentrolesn' => $hotlist_n});
1.50      albertel  467:         if ($hotlist_flag) {
1.90      albertel  468:             $message.="<br />".
1.96      albertel  469: 		&mt('Display [_1] Most Recent '.$role.'s',$hotlist_n)."\n";
1.89      albertel  470:         }
                    471:     }
                    472: 
                    473: # Get list of froze roles and list of recent roles
                    474:     my @freeze_list = &Apache::loncommon::get_env_multiple('form.freezeroles');
                    475:     my %freeze = ();
1.92      albertel  476:     my %roletext = ();
                    477: 
1.89      albertel  478:     foreach my $key (@freeze_list) {
1.91      albertel  479:         $freeze{$key}='1';
1.89      albertel  480:     }
1.92      albertel  481: 
1.89      albertel  482:     my %recent_roles =
                    483:         &Apache::lonhtmlcommon::get_recent('roles',$env{'environment.recentrolesn'});
1.91      albertel  484:     my %frozen_roles =
                    485:         &Apache::lonhtmlcommon::get_recent_frozen('roles',$env{'environment.recentrolesn'});
1.92      albertel  486:     my %role_text = &rolespref_get_role_text([keys(%recent_roles)]);
1.89      albertel  487: 
                    488: # Unset any roles that were previously frozen but aren't in list
                    489:     foreach my $role_key (sort(keys(%recent_roles))) {
1.91      albertel  490:         if (($frozen_roles{$role_key}) && (!exists($freeze{$role_key}))) {
1.158     bisitz    491: 	    $message .= "<br />".&Apache::lonhtmlcommon::confirm_success(&mt('Unfreezing '.$role.': [_1]','<i>'.$role_text{$role_key}.'</i>'));
1.91      albertel  492: 	    &Apache::lonhtmlcommon::store_recent('roles',$role_key,' ',0);
1.89      albertel  493:         }
                    494:     }
                    495: 
                    496: # Freeze selected roles
                    497:     foreach my $role_key (@freeze_list) {
1.91      albertel  498:         if (!$frozen_roles{$role_key}) {
1.154     www       499:              $message .= "<br />".
1.158     bisitz    500:              &Apache::lonhtmlcommon::confirm_success(&mt('Freezing '.$role.': [_1]','<i>'.$role_text{$role_key}.'</i>'));
1.89      albertel  501:              &Apache::lonhtmlcommon::store_recent('roles',
1.91      albertel  502:                                           $role_key,' ',1);
1.50      albertel  503:         }
                    504:     }
1.158     bisitz    505:     $message=&Apache::loncommon::confirmwrapper($message);
1.152     www       506:     &print_main_menu($r, $message);
1.50      albertel  507: }
                    508: 
                    509: 
1.28      www       510: 
                    511: ################################################################
1.9       matthew   512: #         Anonymous Discussion Name Change Subroutines         #
                    513: ################################################################
1.5       www       514: sub screennamechanger {
                    515:     my $r = shift;
1.59      albertel  516:     my $user       = $env{'user.name'};
                    517:     my $domain     = $env{'user.domain'};
1.14      www       518:     my %userenv = &Apache::lonnet::get
                    519:         ('environment',['screenname','nickname']);
1.6       www       520:     my $screenname=$userenv{'screenname'};
1.14      www       521:     my $nickname=$userenv{'nickname'};
1.126     droeschl  522:     Apache::lonhtmlcommon::add_breadcrumb(
                    523: 		{ href => '/adm/preferences?action=changescreenname',
                    524:                   text => 'Change Screen Name'});
1.147     schafran  525:     $r->print(Apache::loncommon::start_page('Personal Data'));
1.126     droeschl  526:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Screen Name'));
1.133     bisitz    527:     $r->print('<p>'
                    528:              .&mt('Change the name that is displayed in your posts.')
                    529:              .'</p>'
                    530:     );
                    531:     $r->print('<form name="prefs" action="/adm/preferences" method="post">'
                    532:              .'<input type="hidden" name="action" value="verify_and_change_screenname" />'
                    533:              .&Apache::lonhtmlcommon::start_pick_box()
1.158     bisitz    534:              .&Apache::lonhtmlcommon::row_title(&mt('Screenname').' '.&mt('(shown if you post anonymously)'))
1.133     bisitz    535:              .'<input type="text" size="20" value="'.$screenname.'" name="screenname" />'
                    536:              .&Apache::lonhtmlcommon::row_closure()
1.158     bisitz    537:              .&Apache::lonhtmlcommon::row_title(&mt('Nickname').' '.&mt('(shown if you post non-anonymously)'))
1.133     bisitz    538:              .'<input type="text" size="20" value="'.$nickname.'" name="nickname" />'
                    539:              .&Apache::lonhtmlcommon::row_closure()
                    540:              .&Apache::lonhtmlcommon::row_title()
                    541:              .'<input type="submit" value="'.&mt('Save').'" />'
                    542:              .&Apache::lonhtmlcommon::row_closure(1)
                    543:              .&Apache::lonhtmlcommon::end_pick_box()
                    544:              .'</form>'
                    545:     );
1.5       www       546: }
1.6       www       547: 
                    548: sub verify_and_change_screenname {
                    549:     my $r = shift;
1.59      albertel  550:     my $user       = $env{'user.name'};
                    551:     my $domain     = $env{'user.domain'};
1.14      www       552: # Screenname
1.59      albertel  553:     my $newscreen  = $env{'form.screenname'};
1.14      www       554:     $newscreen=~s/[^ \w]//g;
1.6       www       555:     my $message='';
                    556:     if ($newscreen) {
1.7       www       557:         &Apache::lonnet::put('environment',{'screenname' => $newscreen});
1.116     raeburn   558:         &Apache::lonnet::appenv({'environment.screenname' => $newscreen});
1.161     bisitz    559:         $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.&mt('Screenname').'</i>','<tt>"'.$newscreen.'"</tt>'));
1.6       www       560:     } else {
                    561:         &Apache::lonnet::del('environment',['screenname']);
1.139     raeburn   562:         &Apache::lonnet::delenv('environment.screenname');
1.158     bisitz    563:         $message=&Apache::lonhtmlcommon::confirm_success(&mt('Reset [_1]','<i>'.&mt('Screenname').'</i>'));
1.6       www       564:     }
1.14      www       565: # Nickname
                    566:     $message.='<br />';
1.59      albertel  567:     $newscreen  = $env{'form.nickname'};
1.14      www       568:     $newscreen=~s/[^ \w]//g;
                    569:     if ($newscreen) {
                    570:         &Apache::lonnet::put('environment',{'nickname' => $newscreen});
1.116     raeburn   571:         &Apache::lonnet::appenv({'environment.nickname' => $newscreen});
1.161     bisitz    572:         $message.=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.&mt('Nickname').'</i>','<tt>"'.$newscreen.'"</tt>'));
1.14      www       573:     } else {
                    574:         &Apache::lonnet::del('environment',['nickname']);
1.139     raeburn   575:         &Apache::lonnet::delenv('environment.nickname');
1.158     bisitz    576:         $message.=&Apache::lonhtmlcommon::confirm_success(&mt('Reset [_1]','<i>'.&mt('Nickname').'</i>'));
1.14      www       577:     }
1.68      www       578:     &Apache::lonnet::devalidate_cache_new('namescache',$user.':'.$domain);
1.158     bisitz    579:     $message=&Apache::loncommon::confirmwrapper($message);
1.152     www       580:     &print_main_menu($r, $message);
1.20      www       581: }
                    582: 
                    583: ################################################################
1.98      www       584: #                     Icon Subroutines                         #
                    585: ################################################################
                    586: sub iconchanger {
                    587:     my $r = shift;
1.154     www       588:     &Apache::lonhtmlcommon::add_breadcrumb(
1.126     droeschl  589: 	    {	href => '/adm/preferences?action=changeicons',
                    590:                 text => 'Change Main Menu'});
1.147     schafran  591:     $r->print(Apache::loncommon::start_page('Page Display Settings'));
1.126     droeschl  592:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Main Menu'));
                    593: 
1.98      www       594:     my $user       = $env{'user.name'};
                    595:     my $domain     = $env{'user.domain'};
                    596:     my %userenv = &Apache::lonnet::get
                    597:         ('environment',['icons']);
                    598:     my $iconic='checked="checked"';
                    599:     my $classic='';
1.100     www       600:     my $onlyicon='';
1.98      www       601:     if ($userenv{'icons'} eq 'classic') {
                    602:        $classic='checked="checked"';
                    603:        $iconic='';
                    604:     }
1.100     www       605:     if ($userenv{'icons'} eq 'iconsonly') {
                    606:        $onlyicon='checked="checked"';
                    607:        $iconic='';
                    608:     }
                    609:     my $useicons=&mt('Use icons and text');
                    610:     my $usebuttons=&mt('Use buttons and text');
                    611:     my $useicononly=&mt('Use icons only');
1.136     schafran  612:     my $change=&mt('Save');
1.98      www       613:     $r->print(<<ENDSCREEN);
                    614: <form name="prefs" action="/adm/preferences" method="post">
                    615: <input type="hidden" name="action" value="verify_and_change_icons" />
                    616: <label><input type="radio" name="menumode" value="iconic" $iconic /> $useicons</label><br />
                    617: <label><input type="radio" name="menumode" value="classic" $classic /> $usebuttons</label><br />
1.100     www       618: <label><input type="radio" name="menumode" value="iconsonly" $onlyicon /> $useicononly</label><br />
1.98      www       619: <input type="submit" value="$change" />
                    620: </form>
                    621: ENDSCREEN
                    622: }
                    623: 
                    624: sub verify_and_change_icons {
                    625:     my $r = shift;
                    626:     my $user       = $env{'user.name'};
                    627:     my $domain     = $env{'user.domain'};
1.158     bisitz    628:     my $newicons   = $env{'form.menumode'};
1.98      www       629: 
                    630:     &Apache::lonnet::put('environment',{'icons' => $newicons});
1.116     raeburn   631:     &Apache::lonnet::appenv({'environment.icons' => $newicons});
1.158     bisitz    632:     my $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.&mt('Menu Display').'</i>','<tt>'.$newicons.'</tt>'));
                    633:     $message=&Apache::loncommon::confirmwrapper($message);
                    634:     &print_main_menu($r, $message);
1.98      www       635: }
                    636: 
                    637: ################################################################
1.105     www       638: #                     Clicker Subroutines                      #
                    639: ################################################################
                    640: 
                    641: sub clickerchanger {
                    642:     my $r = shift;
1.152     www       643:     &Apache::lonhtmlcommon::add_breadcrumb(
1.126     droeschl  644: 	    {	href => '/adm/preferences?action=changeclicker',
                    645:                 text => 'Register Clicker'});
1.147     schafran  646:     $r->print(Apache::loncommon::start_page('Other'));
1.126     droeschl  647:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Register Clicker'));
1.105     www       648:     my $user       = $env{'user.name'};
                    649:     my $domain     = $env{'user.domain'};
                    650:     my %userenv = &Apache::lonnet::get
                    651:         ('environment',['clickers']);
                    652:     my $clickers=$userenv{'clickers'};
                    653:     $clickers=~s/\,/\n/gs;
                    654:     my $text=&mt('Enter response device ("clicker") numbers');
1.151     bisitz    655:     my $change=&mt('Save');
1.114     bisitz    656:     my $helplink=&Apache::loncommon::help_open_topic('Clicker_Registration',&mt('Locating your clicker ID'));
1.105     www       657:     $r->print(<<ENDSCREEN);
                    658: <form name="prefs" action="/adm/preferences" method="post">
                    659: <input type="hidden" name="action" value="verify_and_change_clicker" />
1.151     bisitz    660: <label>$helplink<br /><br />$text<br />
1.108     www       661: <textarea name="clickers" rows="5" cols="20">$clickers</textarea>
1.105     www       662: </label>
1.151     bisitz    663: <br />
1.105     www       664: <input type="submit" value="$change" />
                    665: </form>
                    666: ENDSCREEN
                    667: }
                    668: 
                    669: sub verify_and_change_clicker {
                    670:     my $r = shift;
                    671:     my $user       = $env{'user.name'};
                    672:     my $domain     = $env{'user.domain'};
                    673:     my $newclickers  = $env{'form.clickers'};
1.108     www       674:     $newclickers=~s/[^\w\:\-]+/\,/gs;
1.105     www       675:     $newclickers=~tr/a-z/A-Z/;
1.108     www       676:     $newclickers=~s/[\:\-]+/\-/g;
                    677:     $newclickers=~s/\,+/\,/g;
1.105     www       678:     $newclickers=~s/^\,//;
                    679:     $newclickers=~s/\,$//;
                    680:     &Apache::lonnet::put('environment',{'clickers' => $newclickers});
1.116     raeburn   681:     &Apache::lonnet::appenv({'environment.clickers' => $newclickers});
1.158     bisitz    682:     my $message=&Apache::lonhtmlcommon::confirm_success(&mt('Registering clickers: [_1]',$newclickers));
                    683:     $message=&Apache::loncommon::confirmwrapper($message);
                    684:     &print_main_menu($r, $message);
1.105     www       685: }
                    686: 
1.119     www       687: ################################################################
                    688: #               Domcoord Access Subroutines                    #
                    689: ################################################################
                    690: 
                    691: sub domcoordchanger {
                    692:     my $r = shift;
1.154     www       693:     &Apache::lonhtmlcommon::add_breadcrumb(
1.126     droeschl  694: 	    {	href => '/adm/preferences?action=changedomcoord',
                    695:                 text => 'Restrict Domain Coordinator Access'});
                    696:     $r->print(Apache::loncommon::start_page('Restrict Domain Coordinator Access'));
                    697:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Restrict Domain Coordinator Access'));
1.119     www       698:     my $user       = $env{'user.name'};
                    699:     my $domain     = $env{'user.domain'};
                    700:     my %userenv = &Apache::lonnet::get
1.120     www       701:         ('environment',['domcoord.author']);
1.119     www       702:     my $constchecked='';
                    703:     if ($userenv{'domcoord.author'} eq 'blocked') {
1.159     bisitz    704:        $constchecked=' checked="checked"';
1.119     www       705:     }
1.120     www       706:     my $text=&mt('By default, the Domain Coordinator can enter your construction space.');
1.119     www       707:     my $construction=&mt('Block access to construction space');
1.136     schafran  708:     my $change=&mt('Save');
1.119     www       709:     $r->print(<<ENDSCREEN);
                    710: <form name="prefs" action="/adm/preferences" method="post">
                    711: <input type="hidden" name="action" value="verify_and_change_domcoord" />
                    712: $text<br />
1.159     bisitz    713: <label><input type="checkbox" name="construction"$constchecked />$construction</label><br />
1.119     www       714: <input type="submit" value="$change" />
                    715: </form>
                    716: ENDSCREEN
                    717: }
                    718: 
                    719: sub verify_and_change_domcoord {
                    720:     my $r = shift;
                    721:     my $user       = $env{'user.name'};
                    722:     my $domain     = $env{'user.domain'};
1.120     www       723:     my %domcoord=('domcoord.author' => '');
1.119     www       724:     if ($env{'form.construction'}) { $domcoord{'domcoord.author'}='blocked'; }
                    725:     &Apache::lonnet::put('environment',\%domcoord);
1.120     www       726:     &Apache::lonnet::appenv({'environment.domcoord.author' => $domcoord{'domcoord.author'}});
1.158     bisitz    727:     my $status='';
                    728:     if ($domcoord{'domcoord.author'} eq 'blocked') {
                    729:         $status=&mt('on');
                    730:     } else {
                    731:         $status=&mt('off');
                    732:     }
                    733:     my $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.&mt('Block access to construction space').'</i>','<tt>'.$status.'</tt>'));
                    734:     $message=&Apache::loncommon::confirmwrapper($message);
                    735:     &print_main_menu($r,$message);
1.119     www       736: }
                    737: 
1.118     www       738: #################################################################
                    739: ##                      Lock Subroutines                        #
                    740: #################################################################
                    741: 
                    742: sub lockwarning {
                    743:     my $r = shift;
                    744:     my $title=&mt('Action locked');
                    745:     my $texttop=&mt('LON-CAPA is currently performing the following actions:');
                    746:     my $textbottom=&mt('Changing roles or logging out may result in data corruption.');
                    747:     my ($num,%which)=&Apache::lonnet::get_locks();
                    748:     my $which='';
                    749:     foreach my $id (keys %which) {
                    750:        $which.='<li>'.$which{$id}.'</li>';
                    751:     }
                    752:     my $change=&mt('Override');
                    753:     $r->print(<<ENDSCREEN);
                    754: <form name="prefs" action="/adm/preferences" method="post">
                    755: <input type="hidden" name="action" value="verify_and_change_locks" />
                    756: <h1>$title</h1>
                    757: $texttop
                    758: <ul>
                    759: $which
                    760: </ul>
                    761: $textbottom
                    762: <input type="submit" value="$change" />
                    763: </form>
                    764: ENDSCREEN
                    765: }
                    766: 
                    767: sub verify_and_change_lockwarning {
                    768:     my $r = shift;
                    769:     &Apache::lonnet::remove_all_locks();
                    770:     $r->print(&mt('Cleared locks.'));
                    771: }
                    772: 
                    773: 
1.105     www       774: ################################################################
1.20      www       775: #         Message Forward                                      #
                    776: ################################################################
                    777: 
                    778: sub msgforwardchanger {
1.102     raeburn   779:     my ($r,$message) = @_;
1.59      albertel  780:     my $user       = $env{'user.name'};
                    781:     my $domain     = $env{'user.domain'};
1.102     raeburn   782:     my %userenv = &Apache::lonnet::get('environment',['msgforward','notification','critnotification','notifywithhtml']);
1.20      www       783:     my $msgforward=$userenv{'msgforward'};
1.102     raeburn   784:     my %lt = &Apache::lonlocal::texthash(
                    785:                                           all   => 'All',
                    786:                                           crit  => 'Critical only',
                    787:                                           reg   => 'Non-critical only',
1.175     raeburn   788:                                           foad  => 'Forward to account(s)',
                    789:                                           fwdm  => 'Forward messages to other account(s) in LON-CAPA',
                    790:                                           noti  => 'E-mail notification of LON-CAPA messages',
1.110     bisitz    791:                                           foad_exmpl => 'e.g. <tt>userA:domain1,userB:domain2,...</tt>',
1.175     raeburn   792:                                           mnot  => 'E-mail address(es) which should be notified about new LON-CAPA messages',
1.110     bisitz    793:                                           mnot_exmpl => 'e.g. <tt>joe@doe.com</tt>',
1.136     schafran  794:                                           chg   => 'Save',
1.104     raeburn   795:                                           email => 'The e-mail address entered in row ',
1.102     raeburn   796:                                           notv => 'is not a valid e-mail address',
1.103     raeburn   797:                                           toen => "To enter multiple addresses, enter one address at a time, click 'Change' and then add the next one", 
1.136     schafran  798:                                           prme => 'Back',
1.102     raeburn   799:                                         );
1.126     droeschl  800:     Apache::lonhtmlcommon::add_breadcrumb(
                    801: 	    {	href => '/adm/preferences?action=changemsgforward',
1.176     raeburn   802: 		text => 'Messages & Notifications'});
1.178     bisitz    803:     $r->print(Apache::loncommon::start_page('Messages &amp; Notifications'));
                    804:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Messages &amp; Notifications'));
1.113     raeburn   805:     my $forwardingHelp = &Apache::loncommon::help_open_topic("Prefs_Forwarding");
                    806:     my $notificationHelp = &Apache::loncommon::help_open_topic("Prefs_Notification");
                    807:     my $criticalMessageHelp = &Apache::loncommon::help_open_topic("Course_Critical_Message");
1.102     raeburn   808:     my @allow_html = split(/,/,$userenv{'notifywithhtml'});
                    809:     my %allnot = &get_notifications(\%userenv);
                    810:     my $validatescript = &Apache::lonhtmlcommon::javascript_valid_email();
                    811:     my $jscript = qq|
1.148     bisitz    812: <script type="text/javascript" language="JavaScript">
1.102     raeburn   813: function validate() {
                    814:     for (var i=0; i<document.prefs.numnotify.value; i++) {
1.104     raeburn   815:         var checkaddress = 0;
1.102     raeburn   816:         var addr = document.prefs.elements['address_'+i].value;
1.104     raeburn   817:         var rownum = i+1;
1.102     raeburn   818:         if (i < document.prefs.numnotify.value-1) {
1.104     raeburn   819:             if (document.prefs.elements['modify_notify_'+i].checked) {
1.102     raeburn   820:                 checkaddress = 1;
1.104     raeburn   821:             }
1.102     raeburn   822:         } else {
                    823:             if (document.prefs.elements['add_notify_'+i].checked == true) { 
                    824:                 checkaddress = 1;
                    825:             }
                    826:         }
1.104     raeburn   827:         if (checkaddress == 1)  {
1.102     raeburn   828:             var addr = document.prefs.elements['address_'+i].value;
                    829:             if (validmail(document.prefs.elements['address_'+i]) == false) {
1.104     raeburn   830:                 var multimsg = '';
                    831:                 if (addr.indexOf(",") >= 0) {
                    832:                     multimsg = "\\n($lt{'toen'}).";
                    833:                 }
1.110     bisitz    834:                 alert("$lt{'email'} "+rownum+" ('"+addr+"') $lt{'notv'}."+multimsg);
1.102     raeburn   835:                 return;
                    836:             }
                    837:         }
                    838:     }
                    839:     document.prefs.submit();
                    840: }
1.104     raeburn   841: 
                    842: function address_changes (adnum) {
                    843:      if (!document.prefs.elements['del_notify_'+adnum].checked) { 
                    844:          document.prefs.elements['modify_notify_'+adnum].checked = true;
                    845:      }   
                    846: }
                    847: 
                    848: function new_address(adnum) {
                    849:      document.prefs.elements['add_notify_'+adnum].checked = true;
                    850: }
                    851: 
                    852: function delete_address(adnum) {
                    853:      if (document.prefs.elements['del_notify_'+adnum].checked) {
                    854:           document.prefs.elements['modify_notify_'+adnum].checked = false;
                    855:      }
                    856: }
                    857: 
                    858: function modify_address(adnum) {
                    859:     if (document.prefs.elements['modify_notify_'+adnum].checked) {
                    860:         document.prefs.elements['del_notify_'+adnum].checked = false;
                    861:     }
                    862: } 
                    863: 
1.102     raeburn   864: $validatescript
                    865: </script>
                    866: |;
1.20      www       867:     $r->print(<<ENDMSG);
1.102     raeburn   868: $jscript
                    869: $message
1.175     raeburn   870: <h3>$lt{'fwdm'} $forwardingHelp</h3>
1.88      albertel  871: <form name="prefs" action="/adm/preferences" method="post">
1.20      www       872: <input type="hidden" name="action" value="verify_and_change_msgforward" />
1.110     bisitz    873: $lt{'foad'} ($lt{'foad_exmpl'}):
1.175     raeburn   874: <input type="text" size="40" value="$msgforward" name="msgforward" />
                    875: <br /><br />
1.113     raeburn   876: <h3>$lt{'noti'} $notificationHelp</h3>
1.110     bisitz    877: $lt{'mnot'} ($lt{'mnot_exmpl'}):<br />
1.102     raeburn   878: ENDMSG
                    879:     my @sortforwards = sort (keys(%allnot));
                    880:     my $output = &Apache::loncommon::start_data_table().
                    881:                  &Apache::loncommon::start_data_table_header_row().
1.104     raeburn   882:                  '<th>&nbsp;</th>'.
1.102     raeburn   883:                  '<th>'.&mt('Action').'</th>'.
                    884:                  '<th>'.&mt('Notification address').'</th><th>'.
1.113     raeburn   885:                  &mt('Types of message for which notification is sent').
                    886:                  $criticalMessageHelp.'</th><th>'.
1.104     raeburn   887:                  &mt('Excerpt retains HTML tags in message').'</th>'.
1.102     raeburn   888:                  &Apache::loncommon::end_data_table_header_row();
                    889:     my $num = 0;
1.104     raeburn   890:     my $counter = 1;
1.102     raeburn   891:     foreach my $item (@sortforwards) {
                    892:         $output .= &Apache::loncommon::start_data_table_row().
1.104     raeburn   893:                    '<td><b>'.$counter.'</b></td>'.
                    894:                    '<td><span class="LC_nobreak"><label>'.
                    895:                    '<input type="checkbox" name="modify_notify_'.
                    896:                    $num.'" onclick="javscript:modify_address('."'$num'".')" />'.
                    897:                    &mt('Modify').'</label></span>&nbsp;&nbsp; '.
                    898:                    '<span class="LC_nobreak"><label>'.
                    899:                    '<input type="checkbox" name="del_notify_'.$num.
                    900:                    '" onclick="javscript:delete_address('."'$num'".')" />'.
                    901:                    &mt('Delete').'</label></span></td>'.
1.102     raeburn   902:                    '<td><input type="text" value="'.$item.'" name="address_'.
1.104     raeburn   903:                    $num.'" onFocus="javascript:address_changes('."'$num'".
                    904:                    ')" /></td><td>';
1.102     raeburn   905:         my %chk;
                    906:         if (defined($allnot{$item}{'crit'})) {
                    907:             if (defined($allnot{$item}{'reg'})) {
                    908:                 $chk{'all'} = 'checked="checked" ';
                    909:             } else {
                    910:                 $chk{'crit'} = 'checked="checked" ';
                    911:             }
                    912:         } else {
                    913:             $chk{'reg'} = 'checked="checked" ';
                    914:         }
                    915:         foreach my $type ('all','crit','reg') {
                    916:             $output .= '<span class="LC_nobreak"><label>'.
                    917:                        '<input type="radio" name="notify_type_'.$num. 
1.104     raeburn   918:                        '" value="'.$type.'" '.$chk{$type}.
                    919:                        ' onchange="javascript:address_changes('."'$num'".')" />'.
1.175     raeburn   920:                        $lt{$type}.'</label></span>'.('&nbsp;' x4);
1.102     raeburn   921:         }
                    922:         my $htmlon = '';
                    923:         my $htmloff = '';
                    924:         if (grep/^\Q$item\E/,@allow_html) {
                    925:             $htmlon = 'checked="checked" '; 
                    926:         } else {
                    927:             $htmloff = 'checked="checked" ';
                    928:         }
                    929:         $output .= '</td><td><label><input type="radio" name="html_'.$num.
1.104     raeburn   930:                    '" value="1" '.$htmlon.
                    931:                    ' onchange="javascript:address_changes('."'$num'".')" />'.
1.175     raeburn   932:                    &mt('Yes').'</label>'.('&nbsp;' x3).
1.102     raeburn   933:                    '<label><input type="radio" name="html_'.$num.'" value="0" '.
1.104     raeburn   934:                    $htmloff. ' onchange="javascript:address_changes('."'$num'".
                    935: ')" />'.
                    936:                    &mt('No').'</label></td>'.
1.102     raeburn   937:                    &Apache::loncommon::end_data_table_row();
                    938:         $num ++;
1.104     raeburn   939:         $counter ++;
1.102     raeburn   940:     }
                    941:     my %defchk = (
                    942:                    all => 'checked="checked" ',
                    943:                    crit => '',
                    944:                    reg => '',
                    945:                  );
                    946:     $output .= &Apache::loncommon::start_data_table_row().
1.104     raeburn   947:                '<td><b>'.$counter.'</b></td>'.
                    948:                '<td><span class="LC_nobreak"><label>'.
                    949:                '<input type="checkbox" name="add_notify_'.$num.
                    950:                '" value="1" />'.&mt('Add new address').'</label></span></td>'.
1.102     raeburn   951:                '<td><input type="text" value="" name="address_'.$num.
1.104     raeburn   952:                '" onFocus="javascript:new_address('."'$num'".')" /></td><td>';
1.102     raeburn   953:     foreach my $type ('all','crit','reg') {
                    954:         $output .= '<span class="LC_nobreak"><label>'.
                    955:                    '<input type="radio" name="notify_type_'.$num.
                    956:                    '" value="'.$type.'" '.$defchk{$type}.'/>'.
1.175     raeburn   957:                    $lt{$type}.'</label></span>'.('&nbsp;' x4);
1.102     raeburn   958:     }
                    959:     $output .= '</td><td><label><input type="radio" name="html_'.$num.
1.175     raeburn   960:                '" value="1" />'.&mt('Yes').'</label>'.('&nbsp;' x3).
1.102     raeburn   961:                '<label><input type="radio" name="html_'.$num.'" value="0" '.
                    962:                ' checked="checked" />'.
                    963:                &mt('No').'</label></td>'.
                    964:                &Apache::loncommon::end_data_table_row().
                    965:                &Apache::loncommon::end_data_table();
                    966:     $num ++;
                    967:     $r->print($output);
                    968:     $r->print(qq|
1.113     raeburn   969: <br /><hr />
1.102     raeburn   970: <input type="hidden" name="numnotify" value="$num" />
1.136     schafran  971: <input type="button" value="$lt{'prme'}" onclick="location.href='/adm/preferences'" />
1.102     raeburn   972: <input type="button" value="$lt{'chg'}" onclick="javascript:validate()" />
1.20      www       973: </form>
1.102     raeburn   974: |);
                    975: 
                    976: }
                    977: 
                    978: sub get_notifications {
                    979:     my ($userenv) = @_;
                    980:     my %allnot;
                    981:     my @critnot = split(/,/,$userenv->{'critnotification'});
                    982:     my @regnot = split(/,/,$userenv->{'notification'});
                    983:     foreach my $item (@critnot) {
                    984:         $allnot{$item}{crit} = 1;
                    985:     }
                    986:     foreach my $item (@regnot) {
                    987:         $allnot{$item}{reg} = 1;
                    988:     }
                    989:     return %allnot;
1.20      www       990: }
                    991: 
                    992: sub verify_and_change_msgforward {
                    993:     my $r = shift;
1.59      albertel  994:     my $user       = $env{'user.name'};
                    995:     my $domain     = $env{'user.domain'};
1.20      www       996:     my $newscreen  = '';
                    997:     my $message='';
1.179.2.3  raeburn   998:     foreach my $recip (split(/\,/,$env{'form.msgforward'})) {
                    999:         my ($msuser,$msdomain);
                   1000:         if ($recip =~ /:/) {
                   1001:             ($msuser,$msdomain)=split(':',$recip);
                   1002:         } else {
                   1003:             ($msuser,$msdomain)=split(/\@/,$recip);
                   1004:         }
1.95      albertel 1005:         $msuser = &LONCAPA::clean_username($msuser);
                   1006:         $msdomain = &LONCAPA::clean_domain($msdomain);
1.20      www      1007:         if (($msuser) && ($msdomain)) {
1.179.2.3  raeburn  1008:             if (&Apache::lonnet::homeserver($msuser,$msdomain) ne 'no_host') {
1.179.2.4  raeburn  1009:                 $newscreen.=$msuser.':'.$msdomain.',';
                   1010:             } else {
                   1011:                 $message.= &mt('No such user: ').'<tt>'.$msuser.':'.$msdomain.'</tt><br />';
                   1012:             }
1.20      www      1013:         }
                   1014:     }
                   1015:     $newscreen=~s/\,$//;
                   1016:     if ($newscreen) {
                   1017:         &Apache::lonnet::put('environment',{'msgforward' => $newscreen});
1.116     raeburn  1018:         &Apache::lonnet::appenv({'environment.msgforward' => $newscreen});
1.110     bisitz   1019:         $message .= &mt('Set message forwarding to ').'<tt>"'.$newscreen.'"</tt>.'
                   1020:                     .'<br />';
1.20      www      1021:     } else {
                   1022:         &Apache::lonnet::del('environment',['msgforward']);
1.139     raeburn  1023:         &Apache::lonnet::delenv('environment.msgforward');
1.102     raeburn  1024:         $message.= &mt("Set message forwarding to 'off'.").'<br />';
1.20      www      1025:     }
1.102     raeburn  1026:     my $critnotification;
                   1027:     my $notification;
                   1028:     my $notify_with_html;
                   1029:     my $lastnotify = $env{'form.numnotify'}-1;
1.104     raeburn  1030:     my $totaladdresses = 0;
1.102     raeburn  1031:     for (my $i=0; $i<$env{'form.numnotify'}; $i++) {
                   1032:         if ((!defined($env{'form.del_notify_'.$i})) &&  
1.104     raeburn  1033:            ((($i==$lastnotify) && ($env{'form.add_notify_'.$lastnotify} == 1)) ||
1.102     raeburn  1034:             ($i<$lastnotify))) {
                   1035:             if (defined($env{'form.address_'.$i})) {
                   1036:                 if ($env{'form.notify_type_'.$i} eq 'all') {
                   1037:                     $critnotification .= $env{'form.address_'.$i}.',';
                   1038:                     $notification .= $env{'form.address_'.$i}.',';
                   1039:                 } elsif ($env{'form.notify_type_'.$i} eq 'crit') {
                   1040:                     $critnotification .= $env{'form.address_'.$i}.',';
                   1041:                 } elsif ($env{'form.notify_type_'.$i} eq 'reg') {
                   1042:                     $notification .= $env{'form.address_'.$i}.','; 
                   1043:                 }
                   1044:                 if ($env{'form.html_'.$i} eq '1') {
                   1045: 		    $notify_with_html .= $env{'form.address_'.$i}.',';       	
                   1046:                 }
1.104     raeburn  1047:                 $totaladdresses ++;
1.102     raeburn  1048:             }
                   1049:         }
                   1050:     }
                   1051:     $critnotification =~ s/,$//;
                   1052:     $critnotification=~s/\s//gs;
                   1053:     $notification =~ s/,$//;
1.20      www      1054:     $notification=~s/\s//gs;
1.102     raeburn  1055:     $notify_with_html =~ s/,$//;
                   1056:     $notify_with_html =~ s/\s//gs;
1.20      www      1057:     if ($notification) {
                   1058:         &Apache::lonnet::put('environment',{'notification' => $notification});
1.116     raeburn  1059:         &Apache::lonnet::appenv({'environment.notification' => $notification});
1.110     bisitz   1060:         $message.=&mt('Set non-critical message notification address(es) to ').'<tt>"'.$notification.'"</tt>.<br />';
1.20      www      1061:     } else {
                   1062:         &Apache::lonnet::del('environment',['notification']);
1.139     raeburn  1063:         &Apache::lonnet::delenv('environment.notification');
1.110     bisitz   1064:         $message.=&mt("Set non-critical message notification to 'off'.").'<br />';
1.20      www      1065:     }
                   1066:     if ($critnotification) {
                   1067:         &Apache::lonnet::put('environment',{'critnotification' => $critnotification});
1.116     raeburn  1068:         &Apache::lonnet::appenv({'environment.critnotification' => $critnotification});
1.110     bisitz   1069:         $message.=&mt('Set critical message notification address(es) to ').'<tt>"'.$critnotification.'"</tt>.<br />';
1.20      www      1070:     } else {
                   1071:         &Apache::lonnet::del('environment',['critnotification']);
1.139     raeburn  1072:         &Apache::lonnet::delenv('environment.critnotification');
1.110     bisitz   1073:         $message.=&mt("Set critical message notification to 'off'.").'<br />';
1.102     raeburn  1074:     }
                   1075:     if ($critnotification || $notification) {
                   1076:         if ($notify_with_html) {
                   1077:             &Apache::lonnet::put('environment',{'notifywithhtml' => $notify_with_html});
1.116     raeburn  1078:             &Apache::lonnet::appenv({'environment.notifywithhtml' => $notify_with_html});
1.110     bisitz   1079:             $message.=&mt('Set address(es) to receive excerpts with html retained ').'<tt>"'.$notify_with_html.'"</tt>.';
1.102     raeburn  1080:         } else {
                   1081:             &Apache::lonnet::del('environment',['notifywithhtml']);
1.139     raeburn  1082:             &Apache::lonnet::delenv('environment.notifywithhtml');
1.104     raeburn  1083:             if ($totaladdresses == 1) {
                   1084:                 $message.=&mt("Set notification address to receive excerpts with html stripped.");
                   1085:             } else {
                   1086:                 $message.=&mt("Set all notification addresses to receive excerpts with html stripped.");
                   1087:             }
1.102     raeburn  1088:         }
                   1089:     } else {
                   1090:         &Apache::lonnet::del('environment',['notifywithhtml']);
1.139     raeburn  1091:         &Apache::lonnet::delenv('environment.notifywithhtml');
1.102     raeburn  1092:     }
                   1093:     if ($message) {
                   1094:         $message .= '<br /><hr />';
1.20      www      1095:     }
1.109     albertel 1096:     &Apache::loncommon::flush_email_cache($user,$domain);
1.102     raeburn  1097:     &msgforwardchanger($r,$message);
1.6       www      1098: }
                   1099: 
1.12      www      1100: ################################################################
1.19      www      1101: #         Colors                                               #
1.12      www      1102: ################################################################
                   1103: 
1.19      www      1104: sub colorschanger {
1.12      www      1105:     my $r = shift;
1.126     droeschl 1106:     Apache::lonhtmlcommon::add_breadcrumb(
                   1107: 	    {	href => '/adm/preferences?action=changecolors',
                   1108:                 text => 'Change Colors'});
1.147     schafran 1109:     $r->print(Apache::loncommon::start_page('Page Display Settings'));
1.126     droeschl 1110:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Colors'));
1.19      www      1111: # figure out colors
1.80      albertel 1112:     my $function=&Apache::loncommon::get_users_function();
1.19      www      1113:     my $domain=&Apache::loncommon::determinedomain();
1.157     bisitz   1114:     my %colortypes=&Apache::lonlocal::texthash(
                   1115:         'pgbg'     => 'Page Background Color',
                   1116:         'tabbg'    => 'Header Background Color',
                   1117:         'sidebg'   => 'Header Border Color',
                   1118:         'font'     => 'Font Color',
                   1119:         'fontmenu' => 'Font Menu Color',
                   1120:         'link'     => 'Un-Visited Link Color',
                   1121:         'vlink'    => 'Visited Link Color',
                   1122:         'alink'    => 'Active Link Color',
                   1123:     );
1.82      albertel 1124:     my $start_data_table = &Apache::loncommon::start_data_table();
1.19      www      1125:     my $chtable='';
1.22      matthew  1126:     foreach my $item (sort(keys(%colortypes))) {
1.19      www      1127:        my $curcol=&Apache::loncommon::designparm($function.'.'.$item,$domain);
1.82      albertel 1128:        $chtable.=&Apache::loncommon::start_data_table_row().
1.83      albertel 1129: 	   '<td>'.$colortypes{$item}.'</td><td style="background: '.$curcol.
1.19      www      1130:         '">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td><td><input name="'.$item.
1.21      www      1131:         '" size="10" value="'.$curcol.
                   1132: '" /></td><td><a href="javascript:pjump('."'color_custom','".$colortypes{$item}.
1.19      www      1133: "','".$curcol."','"
1.157     bisitz   1134: 	    .$item."','parmform.pres','psub'".');">'.&mt('Select').'</a></td>'.
1.83      albertel 1135: 	    &Apache::loncommon::end_data_table_row()."\n";
1.19      www      1136:     }
1.82      albertel 1137:     my $end_data_table = &Apache::loncommon::end_data_table();
1.23      matthew  1138:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.157     bisitz   1139:     my $savebutton = &mt('Save');
                   1140:     my $resetbutton = &mt('Reset All');
                   1141:     my $resetbuttondesc = &mt('Reset All Colors to Default');
1.19      www      1142:     $r->print(<<ENDCOL);
1.148     bisitz   1143: <script type="text/javascript" language="JavaScript">
1.19      www      1144: 
                   1145:     function pclose() {
                   1146:         parmwin=window.open("/adm/rat/empty.html","LONCAPAparms",
                   1147:                  "height=350,width=350,scrollbars=no,menubar=no");
                   1148:         parmwin.close();
                   1149:     }
                   1150: 
1.23      matthew  1151:     $pjump_def
1.19      www      1152: 
                   1153:     function psub() {
                   1154:         pclose();
                   1155:         if (document.parmform.pres_marker.value!='') {
1.21      www      1156:             if (document.parmform.pres_type.value!='') {
1.77      albertel 1157:                 eval('document.prefs.'+
1.21      www      1158:                      document.parmform.pres_marker.value+
1.19      www      1159: 		     '.value=document.parmform.pres_value.value;');
1.21      www      1160: 	    }
1.19      www      1161:         } else {
                   1162:             document.parmform.pres_value.value='';
                   1163:             document.parmform.pres_marker.value='';
                   1164:         }
                   1165:     }
                   1166: 
                   1167: 
                   1168: </script>
1.21      www      1169: <form name="parmform">
                   1170: <input type="hidden" name="pres_marker" />
                   1171: <input type="hidden" name="pres_type" />
                   1172: <input type="hidden" name="pres_value" />
                   1173: </form>
1.88      albertel 1174: <form name="prefs" action="/adm/preferences" method="post">
1.19      www      1175: <input type="hidden" name="action" value="verify_and_change_colors" />
1.82      albertel 1176: $start_data_table
1.19      www      1177: $chtable
1.82      albertel 1178: $end_data_table
1.19      www      1179: </table>
1.157     bisitz   1180: <p>
                   1181: <input type="submit" value="$savebutton" />
                   1182: <input type="submit" name="resetall" value="$resetbutton" title="$resetbuttondesc" />
                   1183: </p>
1.12      www      1184: </form>
1.19      www      1185: ENDCOL
1.12      www      1186: }
                   1187: 
1.19      www      1188: sub verify_and_change_colors {
1.12      www      1189:     my $r = shift;
1.19      www      1190: # figure out colors
1.80      albertel 1191:     my $function=&Apache::loncommon::get_users_function();
1.19      www      1192:     my $domain=&Apache::loncommon::determinedomain();
1.157     bisitz   1193:     my %colortypes=&Apache::lonlocal::texthash(
                   1194:         'pgbg'     => 'Page Background Color',
                   1195:         'tabbg'    => 'Header Background Color',
                   1196:         'sidebg'   => 'Header Border Color',
                   1197:         'font'     => 'Font Color',
                   1198: 	'fontmenu' => 'Font Menu Color',
                   1199:         'link'     => 'Un-Visited Link Color',
                   1200:         'vlink'    => 'Visited Link Color',
                   1201:         'alink'    => 'Active Link Color',
                   1202:     );
1.19      www      1203: 
1.12      www      1204:     my $message='';
1.21      www      1205:     foreach my $item (keys %colortypes) {
1.59      albertel 1206:         my $color=$env{'form.'.$item};
1.21      www      1207:         my $entry='color.'.$function.'.'.$item;
1.59      albertel 1208: 	if (($color=~/^\#[0-9A-Fa-f]{6}$/) && (!$env{'form.resetall'})) {
1.21      www      1209: 	    &Apache::lonnet::put('environment',{$entry => $color});
1.116     raeburn  1210: 	    &Apache::lonnet::appenv({'environment.'.$entry => $color});
1.157     bisitz   1211:             $message.=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]','<i>'.$colortypes{$item}.'</i>','<tt>"'.$color.'"</tt>'))
                   1212:                     .'<br />';
1.21      www      1213: 	} else {
                   1214: 	    &Apache::lonnet::del('environment',[$entry]);
1.138     schafran 1215: 	    &Apache::lonnet::delenv('environment.'.$entry);
1.157     bisitz   1216:             $message.=&Apache::lonhtmlcommon::confirm_success(&mt('Reset [_1]','<i>'.$colortypes{$item}.'</i>'))
                   1217:                      .'<br />';
1.21      www      1218: 	}
                   1219:     }
1.158     bisitz   1220:     $message=&Apache::loncommon::confirmwrapper($message);
1.157     bisitz   1221: 
1.84      albertel 1222:     my $now = time;
                   1223:     &Apache::lonnet::put('environment',{'color.timestamp' => $now});
1.116     raeburn  1224:     &Apache::lonnet::appenv({'environment.color.timestamp' => $now});
1.84      albertel 1225: 
1.152     www      1226:     &print_main_menu($r, $message);
1.12      www      1227: }
                   1228: 
1.4       matthew  1229: ######################################################
                   1230: #            password handler subroutines            #
                   1231: ######################################################
1.3       matthew  1232: sub passwordchanger {
1.94      raeburn  1233:     my ($r,$errormessage,$caller,$mailtoken) = @_;
1.4       matthew  1234:     # This function is a bit of a mess....
1.3       matthew  1235:     # Passwords are encrypted using londes.js (DES encryption)
1.4       matthew  1236:     $errormessage = ($errormessage || '');
1.94      raeburn  1237:     my ($user,$domain,$currentpass,$defdom);
1.152     www      1238:     &Apache::lonhtmlcommon::add_breadcrumb(
1.126     droeschl 1239: 		{ href => '/adm/preferences?action=changepass',
                   1240:                   text => 'Change Password'});
1.144     raeburn  1241:     unless ($caller eq 'reset_by_email') {
1.147     schafran 1242:         $r->print(Apache::loncommon::start_page('Personal Data'));
1.144     raeburn  1243:         $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Password'));
                   1244:     }
1.94      raeburn  1245:     if ((!defined($caller)) || ($caller eq 'preferences')) {
                   1246:         $user = $env{'user.name'};
                   1247:         $domain = $env{'user.domain'};
                   1248:         if (!defined($caller)) {
                   1249:             $caller = 'preferences';
                   1250:         }
                   1251:     } elsif ($caller eq 'reset_by_email') {
                   1252:             $defdom = $r->dir_config('lonDefDomain');
                   1253:             my %data = &Apache::lonnet::tmpget($mailtoken);
                   1254:             if (keys(%data) == 0) {
1.155     bisitz   1255:                 $r->print(&mt('Sorry, the URL you provided to complete the reset of your password was invalid. Either the token included in the URL has been deleted or the URL you provided was invalid. Please submit a [_1]new request[_2] for a password reset, and follow the link to the new URL included in the e-mail that will be sent to you, to allow you to enter a new password.'
                   1256:                              ,'<a href="/adm/resetpw">','</a>')
                   1257:                 );
1.94      raeburn  1258:                 return;
                   1259:             }
                   1260:             if (defined($data{time})) {
                   1261:                 if (time - $data{'time'} < 7200) {
                   1262:                     $user = $data{'username'};
                   1263:                     $domain = $data{'domain'};
                   1264:                     $currentpass = $data{'temppasswd'};
                   1265:                 } else {
                   1266:                     $r->print(&mt('Sorry, the token generated when you requested a password reset has expired.').'<br />');
                   1267:                     return;
                   1268:                 }
                   1269:             } else {
                   1270:                 $r->print(&mt('Sorry, the URL generated when you requested reset of your password contained incomplete information.').'<br />');
                   1271:                 return;
                   1272:             }
                   1273:    } else {
                   1274:         $r->print(&mt('Page requested in unexpected context').'<br />');
                   1275:         return;
                   1276:     }
1.3       matthew  1277:     my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
                   1278:     # Check for authentication types that allow changing of the password.
                   1279:     return if ($currentauth !~ /^(unix|internal):/);
                   1280:     #
                   1281:     # Generate keys
                   1282:     my ($lkey_cpass ,$ukey_cpass ) = &des_keys();
                   1283:     my ($lkey_npass1,$ukey_npass1) = &des_keys();
                   1284:     my ($lkey_npass2,$ukey_npass2) = &des_keys();
1.4       matthew  1285:     # Store the keys in the log files
1.3       matthew  1286:     my $lonhost = $r->dir_config('lonHostID');
                   1287:     my $logtoken=Apache::lonnet::reply('tmpput:'
                   1288: 				       .$ukey_cpass  . $lkey_cpass .'&'
                   1289: 				       .$ukey_npass1 . $lkey_npass1.'&'
                   1290: 				       .$ukey_npass2 . $lkey_npass2,
                   1291: 				       $lonhost);
1.4       matthew  1292:     # Hexify the keys for output as javascript variables
1.94      raeburn  1293:     my %hexkey;
                   1294:     $hexkey{'ukey_cpass'}  = hex($ukey_cpass);
                   1295:     $hexkey{'lkey_cpass'}  = hex($lkey_cpass);
                   1296:     $hexkey{'ukey_npass1'} = hex($ukey_npass1);
                   1297:     $hexkey{'lkey_npass1'} = hex($lkey_npass1);
                   1298:     $hexkey{'ukey_npass2'} = hex($ukey_npass2);
                   1299:     $hexkey{'lkey_npass2'} = hex($lkey_npass2);
1.3       matthew  1300:     # Output javascript to deal with passwords
1.4       matthew  1301:     # Output DES javascript
1.3       matthew  1302:     {
                   1303: 	my $include = $r->dir_config('lonIncludes');
                   1304: 	my $jsh=Apache::File->new($include."/londes.js");
                   1305: 	$r->print(<$jsh>);
                   1306:     }
1.94      raeburn  1307:     $r->print(&jscript_send($caller));
1.3       matthew  1308:     $r->print(<<ENDFORM);
1.94      raeburn  1309: $errormessage
                   1310: 
                   1311: <p>
                   1312: <!-- We separate the forms into 'server' and 'client' in order to
                   1313:      ensure that unencrypted passwords will not be sent out by a
                   1314:      crappy browser -->
                   1315: ENDFORM
                   1316:     $r->print(&server_form($logtoken,$caller,$mailtoken));
                   1317:     $r->print(&client_form($caller,\%hexkey,$currentpass,$defdom));
                   1318: 
                   1319:     #
                   1320:     return;
                   1321: }
                   1322: 
                   1323: sub jscript_send {
                   1324:     my ($caller) = @_;
                   1325:     my $output = qq|
1.148     bisitz   1326: <script type="text/javascript" language="JavaScript">
1.3       matthew  1327: 
                   1328:     function send() {
                   1329:         uextkey=this.document.client.elements.ukey_cpass.value;
                   1330:         lextkey=this.document.client.elements.lkey_cpass.value;
                   1331:         initkeys();
                   1332: 
1.52      raeburn  1333:         this.document.pserver.elements.currentpass.value
1.3       matthew  1334:             =crypted(this.document.client.elements.currentpass.value);
                   1335: 
                   1336:         uextkey=this.document.client.elements.ukey_npass1.value;
                   1337:         lextkey=this.document.client.elements.lkey_npass1.value;
                   1338:         initkeys();
1.52      raeburn  1339:         this.document.pserver.elements.newpass_1.value
1.3       matthew  1340:             =crypted(this.document.client.elements.newpass_1.value);
                   1341: 
                   1342:         uextkey=this.document.client.elements.ukey_npass2.value;
                   1343:         lextkey=this.document.client.elements.lkey_npass2.value;
                   1344:         initkeys();
1.52      raeburn  1345:         this.document.pserver.elements.newpass_2.value
1.3       matthew  1346:             =crypted(this.document.client.elements.newpass_2.value);
1.94      raeburn  1347: |;
                   1348:     if ($caller eq 'reset_by_email') {
                   1349:         $output .= qq|
                   1350:         this.document.pserver.elements.uname.value =
                   1351:                    this.document.client.elements.uname.value;
                   1352:         this.document.pserver.elements.udom.value =
                   1353:                    this.document.client.elements.udom.options[this.document.client.elements.udom.selectedIndex].value;
1.173     raeburn  1354:         this.document.pserver.elements.email.value =
                   1355:                    this.document.client.elements.email.value;
1.94      raeburn  1356: |;
                   1357:     }
                   1358:     $ output .= qq|
1.52      raeburn  1359:         this.document.pserver.submit();
1.3       matthew  1360:     }
                   1361: </script>
1.94      raeburn  1362: |;
                   1363: }
1.3       matthew  1364: 
1.94      raeburn  1365: sub client_form {
                   1366:     my ($caller,$hexkey,$currentpass,$defdom) = @_;
1.99      www      1367:     my %lt=&Apache::lonlocal::texthash(
1.115     raeburn  1368:                 'email' => 'E-mail Address',
1.99      www      1369:                 'username' => 'Username',
                   1370:                 'domain' => 'Domain',
                   1371:                 'currentpass' => 'Current Password',
                   1372:                 'newpass' => 'New Password',
                   1373:                 'confirmpass' => 'Confirm Password',
1.169     raeburn  1374:                 'changepass' => 'Save',
                   1375:     );
1.99      www      1376: 
1.164     bisitz   1377:     my $output = '<form name="client">'
                   1378:                 .&Apache::lonhtmlcommon::start_pick_box();
1.94      raeburn  1379:     if ($caller eq 'reset_by_email') {
1.164     bisitz   1380:         $output .= &Apache::lonhtmlcommon::row_title(
                   1381:                        '<label for="email">'.$lt{'email'}.'</label>')
                   1382:                   .'<input type="text" name="email" size="30" />'
                   1383:                   .&Apache::lonhtmlcommon::row_closure()
                   1384:                   .&Apache::lonhtmlcommon::row_title(
                   1385:                        '<label for="uname">'.$lt{'username'}.'</label>')
1.179.2.4  raeburn  1386:                   .'<input type="text" name="uname" size="30" />'
1.164     bisitz   1387:                   .'<input type="hidden" name="currentpass" value="'.$currentpass.'" />'
                   1388:                   .&Apache::lonhtmlcommon::row_closure()
                   1389:                   .&Apache::lonhtmlcommon::row_title(
                   1390:                        '<label for="udom">'.$lt{'domain'}.'</label>')
                   1391:                   .&Apache::loncommon::select_dom_form($defdom,'udom')
                   1392:                   .&Apache::lonhtmlcommon::row_closure();
1.94      raeburn  1393:     } else {
1.164     bisitz   1394:         $output .= &Apache::lonhtmlcommon::row_title(
                   1395:                        '<label for="currentpass">'.$lt{'currentpass'}.'</label>')
                   1396:                   .'<input type="password" name="currentpass" size="10"/>'
                   1397:                   .&Apache::lonhtmlcommon::row_closure();
                   1398:     }
                   1399:     $output .= &Apache::lonhtmlcommon::row_title(
                   1400:                    '<label for="newpass_1">'.$lt{'newpass'}.'</label>')
                   1401:               .'<input type="password" name="newpass_1" size="10" />'
                   1402:               .&Apache::lonhtmlcommon::row_closure()
                   1403:               .&Apache::lonhtmlcommon::row_title(
                   1404:                    '<label for="newpass_2">'.$lt{'confirmpass'}.'</label>')
                   1405:               .'<input type="password" name="newpass_2" size="10" />'
                   1406:               .&Apache::lonhtmlcommon::row_closure(1)
                   1407:               .&Apache::lonhtmlcommon::end_pick_box();
                   1408:     $output .= '<p><input type="button" value="'.$lt{'changepass'}.'" onClick="send();" /></p>'
                   1409:               .qq|
1.94      raeburn  1410: <input type="hidden" name="ukey_cpass"  value="$hexkey->{'ukey_cpass'}" />
                   1411: <input type="hidden" name="lkey_cpass"  value="$hexkey->{'lkey_cpass'}" />
                   1412: <input type="hidden" name="ukey_npass1" value="$hexkey->{'ukey_npass1'}" />
                   1413: <input type="hidden" name="lkey_npass1" value="$hexkey->{'lkey_npass1'}" />
                   1414: <input type="hidden" name="ukey_npass2" value="$hexkey->{'ukey_npass2'}" />
                   1415: <input type="hidden" name="lkey_npass2" value="$hexkey->{'lkey_npass2'}" />
1.3       matthew  1416: </form>
                   1417: </p>
1.164     bisitz   1418: |;
1.94      raeburn  1419:     return $output;
                   1420: }
                   1421: 
                   1422: sub server_form {
                   1423:     my ($logtoken,$caller,$mailtoken) = @_;
                   1424:     my $action = '/adm/preferences';
                   1425:     if ($caller eq 'reset_by_email') {
                   1426:         $action = '/adm/resetpw';
                   1427:     }
                   1428:     my $output = qq|
                   1429: <form name="pserver" action="$action" method="post">
                   1430: <input type="hidden" name="logtoken"    value="$logtoken" />
                   1431: <input type="hidden" name="currentpass" value="" />
                   1432: <input type="hidden" name="newpass_1"   value="" />
                   1433: <input type="hidden" name="newpass_2"   value="" />
                   1434:     |;
                   1435:     if ($caller eq 'reset_by_email') {
                   1436:         $output .=  qq|
                   1437: <input type="hidden" name="token"   value="$mailtoken" />
                   1438: <input type="hidden" name="uname"   value="" />
                   1439: <input type="hidden" name="udom"   value="" />
1.173     raeburn  1440: <input type="hidden" name="email"   value="" />
1.94      raeburn  1441: 
                   1442: |;
                   1443:     }
                   1444:     $output .= qq|
                   1445: <input type="hidden" name="action" value="verify_and_change_pass" />
                   1446: </form>
                   1447: |;
                   1448:     return $output;
1.3       matthew  1449: }
                   1450: 
                   1451: sub verify_and_change_password {
1.94      raeburn  1452:     my ($r,$caller,$mailtoken) = @_;
                   1453:     my ($user,$domain,$homeserver);
                   1454:     if ($caller eq 'reset_by_email') {
                   1455:         $user       = $env{'form.uname'};
                   1456:         $domain     = $env{'form.udom'};
                   1457:         if ($user ne '' && $domain ne '') {
                   1458:             $homeserver = &Apache::lonnet::homeserver($user,$domain);
                   1459:             if ($homeserver eq 'no_host') {
1.99      www      1460:         &passwordchanger($r,"<p>\n<span class='LC_error'>".
                   1461:                          &mt("Invalid username and/or domain")."</span>\n</p>",
1.94      raeburn  1462:                          $caller,$mailtoken);
                   1463:                 return 1;
                   1464:             }
                   1465:         } else {
1.99      www      1466:             &passwordchanger($r,"<p>\n<span class='LC_error'>".
                   1467:                              &mt("Username and domain were blank")."</span>\n</p>",
1.94      raeburn  1468:                              $caller,$mailtoken);
                   1469:             return 1;
                   1470:         }
                   1471:     } else {
                   1472:         $user       = $env{'user.name'};
                   1473:         $domain     = $env{'user.domain'};
                   1474:         $homeserver = $env{'user.home'};
                   1475:     }
1.3       matthew  1476:     my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
1.4       matthew  1477:     # Check for authentication types that allow changing of the password.
1.94      raeburn  1478:     if ($currentauth !~ /^(unix|internal):/) {
                   1479:         if ($caller eq 'reset_by_email') {
1.99      www      1480:             &passwordchanger($r,"<p>\n<span class='LC_error'>".
                   1481:                              &mt("Authentication type for this user can not be changed by this mechanism").
                   1482:                              "</span>\n</p>",
1.94      raeburn  1483:                               $caller,$mailtoken);
                   1484:             return 1;
                   1485:         } else {
                   1486:             return;
                   1487:         }
                   1488:     }
1.3       matthew  1489:     #
1.59      albertel 1490:     my $currentpass = $env{'form.currentpass'}; 
                   1491:     my $newpass1    = $env{'form.newpass_1'}; 
                   1492:     my $newpass2    = $env{'form.newpass_2'};
                   1493:     my $logtoken    = $env{'form.logtoken'};
1.3       matthew  1494:     # Check for empty data 
1.4       matthew  1495:     unless (defined($currentpass) && 
                   1496: 	    defined($newpass1)    && 
                   1497: 	    defined($newpass2)    ){
1.99      www      1498: 	&passwordchanger($r,"<p>\n<span class='LC_error'>".
                   1499: 			 &mt("One or more password fields were blank").
                   1500:                          "</span>\n</p>",$caller,$mailtoken);
1.3       matthew  1501: 	return;
                   1502:     }
1.16      albertel 1503:     # Get the keys
                   1504:     my $lonhost = $r->dir_config('lonHostID');
1.3       matthew  1505:     my $tmpinfo = Apache::lonnet::reply('tmpget:'.$logtoken,$lonhost);
                   1506:     if (($tmpinfo=~/^error/) || ($tmpinfo eq 'con_lost')) {
1.4       matthew  1507:         # I do not a have a better idea about how to handle this
1.94      raeburn  1508:         my $tryagain_text = &mt('Please log out and try again.');
                   1509:         if ($caller eq 'reset_by_email') {
                   1510:             $tryagain_text = &mt('Please try again later.');
                   1511:         }
1.101     albertel 1512:         my $unable=&mt("Unable to retrieve saved token for password decryption");
1.3       matthew  1513: 	$r->print(<<ENDERROR);
                   1514: <p>
1.99      www      1515: <span class="LC_error">$unable.  $tryagain_text</span>
1.3       matthew  1516: </p>
                   1517: ENDERROR
1.4       matthew  1518:         # Probably should log an error here
1.75      albertel 1519:         return 1;
1.3       matthew  1520:     }
                   1521:     my ($ckey,$n1key,$n2key)=split(/&/,$tmpinfo);
1.4       matthew  1522:     # 
1.17      matthew  1523:     $currentpass = &des_decrypt($ckey ,$currentpass);
                   1524:     $newpass1    = &des_decrypt($n1key,$newpass1);
                   1525:     $newpass2    = &des_decrypt($n2key,$newpass2);
1.94      raeburn  1526:     #
                   1527:     if ($caller eq 'reset_by_email') {
                   1528:         my %data = &Apache::lonnet::tmpget($mailtoken);
1.117     raeburn  1529:         if (keys(%data) == 0) {
                   1530:             &passwordchanger($r,
                   1531:                          '<span class="LC_error">'.
                   1532:                          &mt('Could not verify current authentication.').'  '.
                   1533:                          &mt('Please try again.').'</span>',$caller,$mailtoken);
                   1534:             return 1;
                   1535:         }
1.94      raeburn  1536:         if ($currentpass ne $data{'temppasswd'}) {
                   1537:             &passwordchanger($r,
1.99      www      1538:                          '<span class="LC_error">'.
1.110     bisitz   1539:                          &mt('Could not verify current authentication.').'  '.
                   1540:                          &mt('Please try again.').'</span>',$caller,$mailtoken);
1.94      raeburn  1541:             return 1;
                   1542:         }
                   1543:     } 
1.3       matthew  1544:     if ($newpass1 ne $newpass2) {
1.4       matthew  1545: 	&passwordchanger($r,
1.99      www      1546: 			 '<span class="LC_error">'.
1.110     bisitz   1547: 			 &mt('The new passwords you entered do not match.').'  '.
                   1548: 			 &mt('Please try again.').'</span>',$caller,$mailtoken);
1.75      albertel 1549: 	return 1;
1.4       matthew  1550:     }
                   1551:     if (length($newpass1) < 7) {
                   1552: 	&passwordchanger($r,
1.99      www      1553: 			 '<span class="LC_error">'.
1.110     bisitz   1554: 			 &mt('Passwords must be a minimum of 7 characters long.').'  '.
                   1555: 			 &mt('Please try again.').'</span>',$caller,$mailtoken);
1.75      albertel 1556: 	return 1;
1.3       matthew  1557:     }
1.4       matthew  1558:     #
                   1559:     # Check for bad characters
                   1560:     my $badpassword = 0;
                   1561:     foreach (split(//,$newpass1)) {
                   1562: 	$badpassword = 1 if ((ord($_)<32)||(ord($_)>126));
                   1563:     }
                   1564:     if ($badpassword) {
                   1565: 	# I can't figure out how to enter bad characters on my browser.
1.99      www      1566: 	my $errormessage ='<span class="LC_error">'.
1.110     bisitz   1567:            &mt('The password you entered contained illegal characters.').'<br />'.
1.99      www      1568:            &mt('Valid characters are').(<<"ENDERROR");
                   1569: : space and <br />
1.4       matthew  1570: <pre>
                   1571: !&quot;\#$%&amp;\'()*+,-./0123456789:;&lt;=&gt;?\@
                   1572: ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_\`abcdefghijklmnopqrstuvwxyz{|}~
1.99      www      1573: </pre></span>
1.4       matthew  1574: ENDERROR
1.94      raeburn  1575:         &passwordchanger($r,$errormessage,$caller,$mailtoken);
                   1576:         return 1;
1.4       matthew  1577:     }
                   1578:     # 
                   1579:     # Change the password (finally)
                   1580:     my $result = &Apache::lonnet::changepass
1.94      raeburn  1581: 	($user,$domain,$currentpass,$newpass1,$homeserver,$caller);
1.4       matthew  1582:     # Inform the user the password has (not?) been changed
1.126     droeschl 1583:     my $message;
1.4       matthew  1584:     if ($result =~ /^ok$/) {
1.170     bisitz   1585:         $message = &Apache::lonhtmlcommon::confirm_success(&mt('The password for user [_1] was successfully changed.','<i>'.$user.'</i>'));
1.144     raeburn  1586:         if ($caller eq 'reset_by_email') {
                   1587:             $r->print($message.'<br />');
                   1588:         } else {
                   1589:             &print_main_menu($r, $message);
                   1590:         }
1.4       matthew  1591:     } else {
                   1592: 	# error error: run in circles, scream and shout
1.173     raeburn  1593:         if ($caller eq 'reset_by_email') {
                   1594:             if (!$result) {
                   1595:                 return 1;
                   1596:             } else {
                   1597:                 return $result;
                   1598:             }
                   1599:         } else {
                   1600:             $message = &Apache::lonhtmlcommon::confirm_success(
                   1601:                 &mt("The password for user [_1] was not changed.",'<i>'.$user.'</i>').' '.&mt('Please make sure your old password was entered correctly.'),1);
1.158     bisitz   1602:             $message=&Apache::loncommon::confirmwrapper($message);
1.144     raeburn  1603:             &print_main_menu($r, $message);
                   1604:         }
1.4       matthew  1605:     }
                   1606:     return;
1.3       matthew  1607: }
                   1608: 
1.42      raeburn  1609: ################################################################
                   1610: #            discussion display subroutines 
                   1611: ################################################################
                   1612: sub discussionchanger {
                   1613:     my $r = shift;
1.126     droeschl 1614:     Apache::lonhtmlcommon::add_breadcrumb(
                   1615: 	    {	href => '/adm/preferences?action=changediscussions',
                   1616:                 text => 'Change Discussion Preferences'});
1.178     bisitz   1617:     $r->print(Apache::loncommon::start_page('Change Discussion Preferences'));
1.126     droeschl 1618:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Discussion Preferences'));
1.59      albertel 1619:     my $user       = $env{'user.name'};
                   1620:     my $domain     = $env{'user.domain'};
1.42      raeburn  1621:     my %userenv = &Apache::lonnet::get
1.43      raeburn  1622:         ('environment',['discdisplay','discmarkread']);
                   1623:     my $discdisp = 'allposts';
                   1624:     my $discmark = 'onmark';
                   1625: 
                   1626:     if (defined($userenv{'discdisplay'})) {
                   1627:         unless ($userenv{'discdisplay'} eq '') { 
                   1628:             $discdisp = $userenv{'discdisplay'};
                   1629:         }
                   1630:     }
                   1631:     if (defined($userenv{'discmarkread'})) {
1.171     raeburn  1632:         unless ($userenv{'discmarkread'} eq '') { 
1.43      raeburn  1633:             $discmark = $userenv{'discmarkread'};
                   1634:         }
                   1635:     }
                   1636: 
                   1637:     my $newdisp = 'unread';
                   1638:     my $newmark = 'ondisp';
                   1639: 
                   1640:     my $function = &Apache::loncommon::get_users_function();
                   1641:     my $color = &Apache::loncommon::designparm($function.'.tabbg',
1.59      albertel 1642:                                                     $env{'user.domain'});
1.43      raeburn  1643:     my %lt = &Apache::lonlocal::texthash(
                   1644:         'pref' => 'Display Preference',
                   1645:         'curr' => 'Current setting ',
                   1646:         'actn' => 'Action',
1.135     schafran 1647:         'sdpf' => 'Set display preferences for discussion posts for both discussion boards and individual resources in all your courses.',
1.43      raeburn  1648:         'prca' => 'Preferences can be set that determine',
1.135     schafran 1649:         'whpo' => 'Which posts are displayed when you display a discussion board or resource, and',
1.43      raeburn  1650:         'unwh' => 'Under what circumstances posts are identfied as "New"',
                   1651:         'allposts' => 'All posts',
                   1652:         'unread' => 'New posts only',
                   1653:         'ondisp' => 'Once displayed',
                   1654:         'onmark' => 'Once marked as read',
                   1655:         'disa' => 'Posts displayed?',
                   1656:         'npmr' => 'New posts cease to be identified as "New"?',
                   1657:         'thde'  => 'The preferences you set here can be overridden within each individual discussion.',
                   1658:         'chgt' => 'Change to '
                   1659:     );
                   1660:     my $dispchange = $lt{'unread'};
                   1661:     my $markchange = $lt{'ondisp'};
                   1662:     my $currdisp = $lt{'allposts'};
                   1663:     my $currmark = $lt{'onmark'};
                   1664: 
                   1665:     if ($discdisp eq 'unread') {
                   1666:         $dispchange = $lt{'allposts'};
                   1667:         $currdisp = $lt{'unread'};
                   1668:         $newdisp = 'allposts';
                   1669:     }
                   1670: 
                   1671:     if ($discmark eq 'ondisp') {
                   1672:         $markchange = $lt{'onmark'};
                   1673:         $currmark = $lt{'ondisp'};
                   1674:         $newmark = 'onmark';
1.42      raeburn  1675:     }
1.171     raeburn  1676: 
1.43      raeburn  1677:     $r->print(<<"END");
1.88      albertel 1678: <form name="prefs" action="/adm/preferences" method="post">
1.42      raeburn  1679: <input type="hidden" name="action" value="verify_and_change_discussion" />
                   1680: <br />
1.87      albertel 1681: $lt{'sdpf'}<br /> $lt{'prca'}  <ol><li>$lt{'whpo'}</li><li>$lt{'unwh'}</li></ol> 
1.82      albertel 1682: END
1.158     bisitz   1683: 
                   1684:     $r->print('<p class="LC_info">'.$lt{'thde'}.'</p>');
                   1685: 
1.82      albertel 1686:     $r->print(&Apache::loncommon::start_data_table());
                   1687:     $r->print(<<"END");
                   1688:        <tr>
                   1689:         <th>$lt{'pref'}</th>
                   1690:         <th>$lt{'curr'}</th>
                   1691:         <th>$lt{'actn'}?</th>
1.43      raeburn  1692:        </tr>
1.82      albertel 1693: END
                   1694:     $r->print(&Apache::loncommon::start_data_table_row());
                   1695:     $r->print(<<"END");
1.43      raeburn  1696:        <td>$lt{'disa'}</td>
                   1697:        <td>$lt{$discdisp}</td>
1.82      albertel 1698:        <td><label><input type="checkbox" name="discdisp" /><input type="hidden" name="newdisp" value="$newdisp" />&nbsp;$lt{'chgt'} "$dispchange"</label></td>
                   1699: END
                   1700:     $r->print(&Apache::loncommon::end_data_table_row().
                   1701: 	      &Apache::loncommon::start_data_table_row());
                   1702:     $r->print(<<"END");
1.43      raeburn  1703:        <td>$lt{'npmr'}</td>
                   1704:        <td>$lt{$discmark}</td>
1.82      albertel 1705:        <td><label><input type="checkbox" name="discmark" /><input type="hidden" name="newmark" value="$newmark" />&nbsp;$lt{'chgt'} "$markchange"</label></td>
1.43      raeburn  1706:       </tr>
1.82      albertel 1707: END
                   1708:     $r->print(&Apache::loncommon::end_data_table_row().
                   1709: 	      &Apache::loncommon::end_data_table());
1.142     zhu      1710: 
1.158     bisitz   1711:     $r->print('<br />'
                   1712:              .'<input type="submit" name="sub" value="'.&mt('Save').'" />'
                   1713:              .'</form>'
                   1714:     );
1.42      raeburn  1715: }
                   1716:                                                                                                                 
                   1717: sub verify_and_change_discussion {
                   1718:     my $r = shift;
1.59      albertel 1719:     my $user     = $env{'user.name'};
                   1720:     my $domain   = $env{'user.domain'};
1.42      raeburn  1721:     my $message='';
1.59      albertel 1722:     if (defined($env{'form.discdisp'}) ) {
                   1723:         my $newdisp  = $env{'form.newdisp'};
1.43      raeburn  1724:         if ($newdisp eq 'unread') {
1.171     raeburn  1725:             $message .=&Apache::lonhtmlcommon::confirm_success(&mt('In discussions: only new posts will be displayed.')).'<br />';
1.43      raeburn  1726:             &Apache::lonnet::put('environment',{'discdisplay' => $newdisp});
1.116     raeburn  1727:             &Apache::lonnet::appenv({'environment.discdisplay' => $newdisp});
1.43      raeburn  1728:         } else {
1.171     raeburn  1729:             $message .= &Apache::lonhtmlcommon::confirm_success(&mt('In discussions: all posts will be displayed.')).'<br />';
1.43      raeburn  1730:             &Apache::lonnet::del('environment',['discdisplay']);
1.139     raeburn  1731:             &Apache::lonnet::delenv('environment.discdisplay');
1.43      raeburn  1732:         }
                   1733:     }
1.59      albertel 1734:     if (defined($env{'form.discmark'}) ) {
                   1735:         my $newmark = $env{'form.newmark'};
1.43      raeburn  1736:         if ($newmark eq 'ondisp') {
1.152     www      1737:             $message.=&Apache::lonhtmlcommon::confirm_success(&mt('In discussions: new posts will be cease to be identified as "NEW" after display.')).'<br />';
1.43      raeburn  1738:             &Apache::lonnet::put('environment',{'discmarkread' => $newmark});
1.116     raeburn  1739:             &Apache::lonnet::appenv({'environment.discmarkread' => $newmark});
1.43      raeburn  1740:         } else {
1.152     www      1741:             $message.=&Apache::lonhtmlcommon::confirm_success(&mt('In discussions: posts will be identified as "NEW" until marked as read by the reader.')).'<br />';
1.43      raeburn  1742:             &Apache::lonnet::del('environment',['discmarkread']);
1.139     raeburn  1743:             &Apache::lonnet::delenv('environment.discmarkread');
1.43      raeburn  1744:         }
1.42      raeburn  1745:     }
1.158     bisitz   1746:     $message=&Apache::loncommon::confirmwrapper($message);
1.152     www      1747:     &print_main_menu($r, $message);
1.42      raeburn  1748: }
                   1749: 
1.63      raeburn  1750: ################################################################
                   1751: # Subroutines for page display on course access (Course Coordinators)
                   1752: ################################################################
                   1753: sub coursedisplaychanger {
                   1754:     my $r = shift;
1.152     www      1755:     &Apache::lonhtmlcommon::add_breadcrumb(
1.126     droeschl 1756: 	    {	href => '/adm/preferences?action=changecourseinit',
                   1757:                 text => 'Change Course Init. Pref.'});
                   1758:     $r->print(Apache::loncommon::start_page('Change Course Initialization Preference'));
                   1759:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Course Init. Pref.'));
1.63      raeburn  1760:     my $user       = $env{'user.name'};
                   1761:     my $domain     = $env{'user.domain'};
1.66      albertel 1762:     my %userenv = &Apache::lonnet::get('environment',['course_init_display']);
1.71      raeburn  1763:     my $currvalue = 'whatsnew';
1.73      albertel 1764:     my $firstselect = '';
                   1765:     my $whatsnewselect = 'checked="checked"';
1.71      raeburn  1766:     if (exists($userenv{'course_init_display'})) {
                   1767:         if ($userenv{'course_init_display'} eq 'firstres') {
                   1768:             $currvalue = 'firstres';
1.73      albertel 1769:             $firstselect = 'checked="checked"';
                   1770: 	    $whatsnewselect = '';
1.71      raeburn  1771:         }
1.63      raeburn  1772:     }
1.134     bisitz   1773:     my %pagenames = &Apache::lonlocal::texthash(
1.71      raeburn  1774:                        firstres => 'First resource',
1.143     hauer    1775:                        whatsnew => "What's New Page",
1.71      raeburn  1776:                     );
1.134     bisitz   1777:     my $whatsnew_off=&mt('Display the [_1]first resource[_2] in the course.','<b>','</b>');
1.143     hauer    1778:     my $whatsnew_on=&mt("Display the [_1]What's New Page[_2] - a summary of items in the course which require attention.",'<b>','</b>');
1.63      raeburn  1779: 
1.134     bisitz   1780:     $r->print('<br /><b>'
                   1781:              .&mt('Set the default page to be displayed when you select a course role')
                   1782:              .'</b>&nbsp;'
                   1783:              .&mt('(Currently: [_1])',$pagenames{$currvalue})
                   1784:              .'<br />'
1.143     hauer    1785:              .&mt("The global user preference you set for your courses can be overridden in an individual course by setting a course specific setting via the [_1]What's New Page[_2] in the course.",'<i>','</i>')
1.134     bisitz   1786:              .'<br /><br />'
                   1787:     );
1.63      raeburn  1788:     $r->print(<<ENDLSCREEN);
1.88      albertel 1789: <form name="prefs" action="/adm/preferences" method="post">
1.63      raeburn  1790: <input type="hidden" name="action" value="verify_and_change_coursepage" />
1.72      albertel 1791: <br />
1.65      albertel 1792: <label><input type="radio" name="newdisp" value="firstres" $firstselect /> $whatsnew_off</label><br />
1.70      raeburn  1793: <label><input type="radio" name="newdisp" value="whatsnew" $whatsnewselect /> $whatsnew_on</label><input type="hidden" name="refpage" value="$env{'form.refpage'}" />
1.63      raeburn  1794: ENDLSCREEN
1.140     schafran 1795:     $r->print('<br /><br /><input type="submit" value="'.&mt('Save').'" />
1.63      raeburn  1796: </form>');
                   1797: }
                   1798: 
                   1799: sub verify_and_change_coursepage {
                   1800:     my $r = shift;
                   1801:     my $message='';
                   1802:     my %lt = &Apache::lonlocal::texthash(
1.70      raeburn  1803:         'defs' => 'Default now set',
1.71      raeburn  1804:         'when' => 'when you select a course role from the roles screen',
1.63      raeburn  1805:         'ywbt' => 'you will be taken to the start of the course.',
                   1806:         'apwb' => 'a page will be displayed that lists items in the course that may require action from you.',
                   1807:         'gtts' => 'Go to the start of the course',
1.146     hauer    1808:         'dasp' => "Display the What's New Page", 
1.63      raeburn  1809:     );
                   1810:     my $newdisp  = $env{'form.newdisp'};
1.70      raeburn  1811:     $message = '<b>'.$lt{'defs'}.'</b>: '.$lt{'when'}.', ';
1.63      raeburn  1812:     if ($newdisp eq 'firstres') {
1.87      albertel 1813:         $message .= $lt{'ywbt'}.'<br />';
1.63      raeburn  1814:         &Apache::lonnet::put('environment',{'course_init_display' => $newdisp});
1.116     raeburn  1815:         &Apache::lonnet::appenv({'environment.course_init_display' => $newdisp});
1.63      raeburn  1816:     } else {
1.87      albertel 1817:         $message .= $lt{'apwb'}.'<br />';
1.63      raeburn  1818:         &Apache::lonnet::del('environment',['course_init_display']);
1.139     raeburn  1819:         &Apache::lonnet::delenv('environment.course_init_display');
1.63      raeburn  1820:     }
1.70      raeburn  1821:     my $refpage = $env{'form.refpage'};
1.63      raeburn  1822:     if (($env{'request.course.fn'}) && ($env{'request.course.id'})) {
                   1823:         if ($newdisp eq 'firstres') {
                   1824:             my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1825:             my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; 
                   1826:             my ($furl,$ferr)=
                   1827:                 &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
                   1828:             $message .= '<br /><font size="+1"><a href="'.$furl.'">'.$lt{'gtts'}.' <i>'.&mt('now').'</i></a></font>';
                   1829:         } else {
1.70      raeburn  1830:             $message .= '<br /><font size="+1"><a href="/adm/whatsnew?refpage='.
                   1831:                         $refpage.'">'.$lt{'dasp'}.'</a></font>';
1.63      raeburn  1832:         }
                   1833:     }
1.152     www      1834:     &print_main_menu($r, &Apache::lonhtmlcommon::confirm_success($message));
1.63      raeburn  1835: }
                   1836: 
1.126     droeschl 1837: sub print_main_menu {
                   1838:     my ($r, $message) = @_;
                   1839:     # Determine current authentication method
                   1840:     my $user = $env{'user.name'};
                   1841:     my $domain = $env{'user.domain'};
                   1842:     my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
                   1843: 
                   1844:     # build the data structure for menu generation
                   1845: my $aboutmeurl='/adm/'.$env{'user.domain'}.'/'.$env{'user.name'}.'/aboutme';
                   1846: my $role = ($env{'user.adv'} ? 'Roles' : 'Course');
1.131     raeburn  1847: my %permissions;
                   1848: if (&Apache::lonnet::usertools_access($user,$domain,'aboutme')) {
                   1849:     $permissions{'aboutme'} = 'F';
                   1850: }
1.126     droeschl 1851: my @menu=
                   1852:     ({	categorytitle=>'Personal Data',
1.179.2.2  raeburn  1853:         items =>[]
                   1854:      },
1.126     droeschl 1855:     {	categorytitle=>'Page Display Settings',
                   1856: 	items =>[
                   1857: 	    {	linktext => 'Color Scheme',
                   1858: 		url => '/adm/preferences?action=changecolors',
                   1859: 		permission => 'F',
                   1860: 		#help => 'Change_Colors',
                   1861: 		icon => 'preferences-desktop-theme.png',
                   1862: 		linktitle => 'Change LON-CAPA default colors.'
                   1863: 	    },
                   1864: 		]
                   1865:     },
                   1866:     {	categorytitle=>'Content Display Settings',
                   1867: 	items =>[
1.128     droeschl 1868: 	    {	linktext => 'WYSIWYG Editor',
1.126     droeschl 1869: 		url => '/adm/preferences?action=changewysiwyg',
                   1870: 		permission => 'F',
                   1871: 		#help => '',
                   1872: 		icon => 'edit-select-all.png',
                   1873: 		linktitle => 'Enable or disable the WYSIWYG-Editor.'
                   1874: 	    },
1.177     raeburn  1875: 	    {	linktext => 'Math display settings',
1.126     droeschl 1876: 		url => '/adm/preferences?action=changetexenginepref',
                   1877: 		permission => 'F',
                   1878: 		#help => '',
                   1879: 		icon => 'stat.png',
1.177     raeburn  1880: 		linktitle => 'Change how math is displayed.'
1.126     droeschl 1881: 	    },
                   1882: 		]
                   1883:     },
1.178     bisitz   1884:     {	categorytitle=>'Messages &amp; Notifications',
1.128     droeschl 1885: 	items =>[
1.153     www      1886: 	    {	linktext => 'Messages &amp; Notifications',
1.128     droeschl 1887: 		url => '/adm/preferences?action=changemsgforward',
                   1888: 		permission => 'F',
                   1889: 		#help => 'Prefs_Messages',
                   1890: 		icon => 'mail-reply-all.png',
                   1891: 		linktitle => 'Change messageforwarding or notifications settings.'
                   1892: 	    },
                   1893: 		]
                   1894:     },
1.126     droeschl 1895:     {	categorytitle=>'Other',
1.179.2.1  raeburn  1896: 	items =>[]
1.126     droeschl 1897:     },
                   1898:     );
                   1899: 
1.179.2.2  raeburn  1900:     if (&Apache::lonnet::usertools_access($env{'user.name'},
                   1901:                                           $env{'user.domain'},'aboutme')) {
                   1902:         push(@{ $menu[0]->{items} },
                   1903:                 {   linktext   => 'Personal Information Page',
                   1904:                     url        => $aboutmeurl,
                   1905:                     permission => $permissions{'aboutme'},
                   1906:                     #help      => 'Prefs_About_Me',
                   1907:                     icon       => 'system-users.png',
                   1908:                     linktitle  => 'Edit information about yourself that should be displayed on your public profile.'
                   1909:                 });
                   1910:     }
                   1911: 
1.179.2.5! raeburn  1912:     unless ($env{'user.domain'} =~ /^\w+citest$/) {
1.179.2.2  raeburn  1913:         push(@{ $menu[0]->{items} },
                   1914:             {   linktext => 'Screen Name',
                   1915:                 url => '/adm/preferences?action=changescreenname',
                   1916:                 permission => 'F',
                   1917:                 #help => 'Prefs_Screen_Name_Nickname',
                   1918:                 icon => 'preferences-desktop-font.png',
                   1919:                 linktitle => 'Change the name that is displayed in your posts.'
                   1920:             });
                   1921:     }
                   1922: 
1.126     droeschl 1923:     if ($currentauth =~ /^(unix|internal):/) {
                   1924: push(@{ $menu[0]->{items} }, {
                   1925: 	linktext => 'Password',
                   1926: 	url => '/adm/preferences?action=changepass',
                   1927: 	permission => 'F',
                   1928: 	#help => 'Change_Password',
                   1929: 	icon => 'emblem-readonly.png',
                   1930: 	linktitle => 'Change your password.',
                   1931: 	});
                   1932:     }
1.179.2.2  raeburn  1933: 
1.179.2.5! raeburn  1934:     unless ((&Apache::loncommon::needs_gci_custom()) || ($env{'user.domain'} =~ /^\w+citest$/)) {
1.179.2.2  raeburn  1935:         push(@{ $menu[1]->{items} },
                   1936:           {   linktext => 'Menu Display',
                   1937:               url => '/adm/preferences?action=changeicons',
                   1938:               permission => 'F',
                   1939:               #help => '',
                   1940:               icon => 'preferences-system-windows.png',
                   1941:               linktitle => 'Change whether the menus are displayed with buttons, icons or icons and text.'
                   1942:           });
                   1943:     }
                   1944: 
1.179.2.5! raeburn  1945:     unless ($env{'user.domain'} =~ /^\w+citest$/) {
1.179.2.2  raeburn  1946:         push(@{ $menu[3]->{items} },
                   1947:             {   linktext => 'Discussion Display',
                   1948:                 url => '/adm/preferences?action=changediscussions',
                   1949:                 permission => 'F',
                   1950:                 #help => 'Change_Discussion_Display',
                   1951:                 icon => 'mail-message-new.png',
                   1952:                 linktitle => 'Set display preferences for discussion posts for both discussion boards and individual resources in all your courses.'
                   1953:             });
                   1954:     }
                   1955: 
1.126     droeschl 1956:     my %author_roles = &Apache::lonnet::get_my_roles($user,$domain,'userroles','',['au']);
                   1957:     if (keys(%author_roles) > 0) {
                   1958: push(@{ $menu[4]->{items} }, {
                   1959: 	linktext => 'Restrict Domain Coordinator Access',
                   1960: 	url => '/adm/preferences?action=changedomcoord',
                   1961: 	permission => 'F',
                   1962: 	#help => '',
                   1963: 	icon => 'system-lock-screen.png',
                   1964: 	linktitle => 'Restrict domain coordinator access.',
                   1965: 	});
                   1966:     }
                   1967: 
1.179.2.5! raeburn  1968:     unless ((&Apache::loncommon::needs_gci_custom()) || ($env{'user.domain'} =~ /^\w+citest/)) { 
1.179.2.2  raeburn  1969:         if (&Apache::lonnet::allowed('whn',$env{'request.course.id'})
                   1970: 	    || &Apache::lonnet::allowed('whn',$env{'request.course.id'}.'/'
                   1971: 	   			        .$env{'request.course.sec'})) {
1.126     droeschl 1972: push(@{ $menu[4]->{items} }, {
1.128     droeschl 1973: 	linktext => 'Course Initialization',
1.126     droeschl 1974: 	url => '/adm/preferences?action=changecourseinit',
                   1975: 	permission => 'F',
                   1976: 	#help => '',
                   1977: 	icon => 'edit-copy.png',
                   1978: 	linktitle => 'Set the default page to be displayed when you select a course role.',
                   1979: 	});
                   1980: 
1.179.2.2  raeburn  1981:         }
1.126     droeschl 1982:     }
1.174     raeburn  1983:     if (&can_toggle_debug()) {
1.126     droeschl 1984: push(@{ $menu[4]->{items} }, {
1.174     raeburn  1985: 	linktext => 'Toggle Debug Messages (Currently '.($env{'user.debug'} ? 'on)' : 'off)'),
1.126     droeschl 1986: 	url => '/adm/preferences?action=debugtoggle',
                   1987: 	permission => 'F',
                   1988: 	#help => '',
                   1989: 	icon => 'blog.png',
                   1990: 	linktitle => 'Toggle Debug Messages.',
                   1991: 	});
1.179.2.2  raeburn  1992:     }
1.126     droeschl 1993: 
1.147     schafran 1994:     $r->print(&Apache::loncommon::start_page('My Space'));
1.126     droeschl 1995:     $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Preferences'));
                   1996:     $r->print($message);
                   1997:     $r->print(Apache::lonhtmlcommon::generate_menu(@menu));
                   1998:     $r->print(Apache::loncommon::end_page());
                   1999: }
1.63      raeburn  2000: 
1.4       matthew  2001: ######################################################
                   2002: #            other handler subroutines               #
                   2003: ######################################################
                   2004: 
1.3       matthew  2005: ################################################################
                   2006: #                          Main handler                        #
                   2007: ################################################################
1.126     droeschl 2008: sub handler {    
                   2009:     my $r = shift;
                   2010:     Apache::loncommon::content_type($r,'text/html');
                   2011:     # Some pages contain DES keys and should not be cached.
                   2012:     Apache::loncommon::no_cache($r);
                   2013:     $r->send_http_header;
                   2014:     return OK if $r->header_only;
                   2015:     #
                   2016:     Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   2017:                                    ['action','wysiwyg','returnurl','refpage']);
                   2018:     #
                   2019:     Apache::lonhtmlcommon::clear_breadcrumbs();
                   2020:     Apache::lonhtmlcommon::add_breadcrumb
                   2021:         ({href => '/adm/preferences',
1.150     droeschl 2022:           text => 'Set User Preferences',
                   2023:           help =>
                   2024:           'Prefs_About_Me,Prefs_Language,Prefs_Screen_Name_Nickname,Change_Colors,Change_Password,Prefs_Messages,Change_Discussion_Display'});
1.126     droeschl 2025:     if(!exists $env{'form.action'}) {
1.150     droeschl 2026: 	    &print_main_menu($r);
1.126     droeschl 2027:     }elsif($env{'form.action'} eq 'changepass'){
                   2028:         &passwordchanger($r);
                   2029:     }elsif($env{'form.action'} eq 'verify_and_change_pass'){
                   2030:         &verify_and_change_password($r);
                   2031:     }elsif($env{'form.action'} eq 'changescreenname'){
                   2032:         &screennamechanger($r);
                   2033:     }elsif($env{'form.action'} eq 'verify_and_change_screenname'){
                   2034:         &verify_and_change_screenname($r);
                   2035:     }elsif($env{'form.action'} eq 'changemsgforward'){
                   2036:         &msgforwardchanger($r);
                   2037:     }elsif($env{'form.action'} eq 'verify_and_change_msgforward'){
                   2038:         &verify_and_change_msgforward($r);
                   2039:     }elsif($env{'form.action'} eq 'changecolors'){
                   2040:         &colorschanger($r);
                   2041:     }elsif($env{'form.action'} eq 'verify_and_change_colors'){
                   2042:         &verify_and_change_colors($r);
                   2043:     }elsif($env{'form.action'} eq 'changelanguages'){
                   2044:         &languagechanger($r);
                   2045:     }elsif($env{'form.action'} eq 'verify_and_change_languages'){
                   2046:         &verify_and_change_languages($r);
                   2047:     }elsif($env{'form.action'} eq 'changewysiwyg'){
                   2048:         &wysiwygchanger($r);
                   2049:     }elsif($env{'form.action'} eq 'set_wysiwyg'){
                   2050:         &verify_and_change_wysiwyg($r);
                   2051:     }elsif($env{'form.action'} eq 'changediscussions'){
                   2052:         &discussionchanger($r);
                   2053:     }elsif($env{'form.action'} eq 'verify_and_change_discussion'){
                   2054:         &verify_and_change_discussion($r);
                   2055:     }elsif($env{'form.action'} eq 'changerolespref'){
                   2056:         &rolesprefchanger($r);
                   2057:     }elsif($env{'form.action'} eq 'verify_and_change_rolespref'){
                   2058:         &verify_and_change_rolespref($r);
                   2059:     }elsif($env{'form.action'} eq 'changetexenginepref'){
                   2060:         &texenginechanger($r);
                   2061:     }elsif($env{'form.action'} eq 'verify_and_change_texengine'){
                   2062:         &verify_and_change_texengine($r);
                   2063:     }elsif($env{'form.action'} eq 'changeicons'){
                   2064:         &iconchanger($r);
                   2065:     }elsif($env{'form.action'} eq 'verify_and_change_icons'){
                   2066:         &verify_and_change_icons($r);
                   2067:     }elsif($env{'form.action'} eq 'changeclicker'){
                   2068:         &clickerchanger($r);
                   2069:     }elsif($env{'form.action'} eq 'verify_and_change_clicker'){
                   2070:         &verify_and_change_clicker($r);
                   2071:     }elsif($env{'form.action'} eq 'changedomcoord'){
                   2072:         &domcoordchanger($r);
                   2073:     }elsif($env{'form.action'} eq 'verify_and_change_domcoord'){
                   2074:         &verify_and_change_domcoord($r);
                   2075:     }elsif($env{'form.action'} eq 'lockwarning'){
                   2076:         &lockwarning($r);
                   2077:     }elsif($env{'form.action'} eq 'verify_and_change_locks'){
                   2078:         &verify_and_change_lockwarning($r);
                   2079:     }elsif($env{'form.action'} eq 'changecourseinit'){
                   2080:         &coursedisplaychanger($r);
                   2081:     }elsif($env{'form.action'} eq 'verify_and_change_coursepage'){
                   2082:         &verify_and_change_coursepage($r);
                   2083:     }elsif($env{'form.action'} eq 'debugtoggle'){
1.174     raeburn  2084:         if (&can_toggle_debug()) {
                   2085:             &toggle_debug();
                   2086:         }
1.154     www      2087: 	&print_main_menu($r);
1.126     droeschl 2088:     }
                   2089: 
1.165     bisitz   2090:     # Properly end the HTML page of all preference pages
                   2091:     # started in each sub routine
                   2092:     # Exception: print_main_menu has its own end_page call
                   2093:     unless (!exists $env{'form.action'} ||
                   2094:             $env{'form.action'} eq 'debugtoggle') {
                   2095:         $r->print(&Apache::loncommon::end_page());
                   2096:     }
                   2097: 
1.126     droeschl 2098:     return OK;
1.35      matthew  2099: }
                   2100: 
                   2101: sub toggle_debug {
1.59      albertel 2102:     if ($env{'user.debug'}) {
1.139     raeburn  2103:         &Apache::lonnet::delenv('user.debug');
1.35      matthew  2104:     } else {
1.116     raeburn  2105:         &Apache::lonnet::appenv({'user.debug' => 1});
1.35      matthew  2106:     }
1.13      www      2107: }
1.1       www      2108: 
1.174     raeburn  2109: sub can_toggle_debug {
                   2110:     my $can_toggle = 0;
                   2111:     my $page = 'toggledebug';
                   2112:     if (&LONCAPA::lonauthcgi::can_view($page)) {
                   2113:         $can_toggle = 1;
                   2114:     } elsif (&LONCAPA::lonauthcgi::check_ipbased_access($page)) {
                   2115:         $can_toggle = 1;
                   2116:     }
                   2117:     return $can_toggle;
                   2118: }
                   2119: 
1.1       www      2120: 1;
                   2121: __END__

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