# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
# $Id: domainprefs.pm,v 1.229 2014/03/17 02:36:56 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
#
###############################################################
##############################################################
=pod
=head1 NAME
Apache::domainprefs.pm
=head1 SYNOPSIS
Handles configuration of a LON-CAPA domain.
This is part of the LearningOnline Network with CAPA project
described at http://www.lon-capa.org.
=head1 OVERVIEW
Each institution using LON-CAPA will typically have a single domain designated
for use by individuals affiliated with the institution. Accordingly, each domain
may define a default set of logos and a color scheme which can be used to "brand"
the LON-CAPA instance. In addition, an institution will typically have a language
and timezone which are used for the majority of courses.
LON-CAPA provides a mechanism to display and modify these defaults, as well as a
host of other domain-wide settings which determine the types of functionality
available to users and courses in the domain.
There is also a mechanism to configure cataloging of courses in the domain, and
controls on the operation of automated processes which govern such things as
roster updates, user directory updates and processing of course requests.
The domain coordination manual which is built dynamically on install/update of
LON-CAPA from the relevant help items provides more information about domain
configuration.
Most of the domain settings are stored in the configuration.db GDBM file which is
housed on the primary library server for the domain in /home/httpd/lonUsers/$dom,
where $dom is the domain. The configuration.db stores settings in a number of
frozen hashes of hashes. In a few cases, domain information must be uploaded to
the domain as files (e.g., image files for logos etc., or plain text files for
bubblesheet formats). In this case the domainprefs.pm must be running in a user
session hosted on the primary library server in the domain, as these files are
stored in author space belonging to a special $dom-domainconfig user.
domainprefs.pm in combination with lonconfigsettings.pm will retrieve and display
the current settings, and provides an interface to make modifications.
=head1 SUBROUTINES
=over
=item print_quotas()
Inputs: 4
$dom,$settings,$rowtotal,$action.
$dom is the domain, $settings is a reference to a hash of current settings for
the current context, $rowtotal is a reference to the scalar used to record the
number of rows displayed on the page, and $action is the context (quotas,
requestcourses or requestauthor).
The print_quotas routine was orginally created to display/store information
about default quota sizes for portfolio spaces for the different types of
institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.),
but is now also used to manage availability of user tools:
i.e., blogs, aboutme page, and portfolios, and the course request tool,
used by course owners to request creation of a course, and to display/store
default quota sizes for Authoring Spaces.
Outputs: 1
$datatable - HTML containing form elements which allow settings to be changed.
In the case of course requests, radio buttons are displayed for each institutional
affiliate type (and also default, and _LC_adv) for each of the course types
(official, unofficial, community, and textbook). In each case the radio buttons
allow the selection of one of four values:
0, approval, validate, autolimit=N (where N is blank, or a positive integer).
which have the following effects:
0
=over
- course requests are not allowed for this course types/affiliation
=back
approval
=over
- course requests must be approved by a Doman Coordinator in the
course's domain
=back
validate
=over
- an institutional validation (e.g., check requestor is instructor
of record) needs to be passed before the course will be created. The required
validation is in localenroll.pm on the primary library server for the course
domain.
=back
autolimit
=over
- course requests will be processed automatically up to a limit of
N requests for the course type for the particular requestor.
If N is undefined, there is no limit to the number of course requests
which a course owner may submit and have processed automatically.
=back
=item modify_quotas()
=back
=cut
package Apache::domainprefs;
use strict;
use Apache::Constants qw(:common :http);
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon();
use Apache::lonlocal;
use Apache::lonmsg();
use Apache::lonconfigsettings;
use LONCAPA qw(:DEFAULT :match);
use LONCAPA::Enrollment;
use LONCAPA::lonauthcgi();
use File::Copy;
use Locale::Language;
use DateTime::TimeZone;
use DateTime::Locale;
my $registered_cleanup;
my $modified_urls;
sub handler {
my $r=shift;
if ($r->header_only) {
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK;
}
my $context = 'domain';
my $dom = $env{'request.role.domain'};
my $domdesc = &Apache::lonnet::domain($dom,'description');
if (&Apache::lonnet::allowed('mau',$dom)) {
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
} else {
$env{'user.error.msg'}=
"/adm/domainprefs:mau:0:0:Cannot modify domain settings";
return HTTP_NOT_ACCEPTABLE;
}
$registered_cleanup=0;
@{$modified_urls}=();
&Apache::lonhtmlcommon::clear_breadcrumbs();
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['phase','actions']);
my $phase = 'pickactions';
if ( exists($env{'form.phase'}) ) {
$phase = $env{'form.phase'};
}
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %domconfig =
&Apache::lonnet::get_dom('configuration',['login','rolecolors',
'quotas','autoenroll','autoupdate','autocreate',
'directorysrch','usercreation','usermodification',
'contacts','defaults','scantron','coursecategories',
'serverstatuses','requestcourses','helpsettings',
'coursedefaults','usersessions','loadbalancing',
'requestauthor'],$dom);
my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
'autoupdate','autocreate','directorysrch','contacts',
'usercreation','selfcreation','usermodification','scantron',
'requestcourses','requestauthor','coursecategories',
'serverstatuses','helpsettings',
'coursedefaults','usersessions');
my %existing;
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
}
if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
push(@prefs_order,'loadbalancing');
}
my %prefs = (
'rolecolors' =>
{ text => 'Default color schemes',
help => 'Domain_Configuration_Color_Schemes',
header => [{col1 => 'Student Settings',
col2 => '',},
{col1 => 'Coordinator Settings',
col2 => '',},
{col1 => 'Author Settings',
col2 => '',},
{col1 => 'Administrator Settings',
col2 => '',}],
},
'login' =>
{ text => 'Log-in page options',
help => 'Domain_Configuration_Login_Page',
header => [{col1 => 'Log-in Page Items',
col2 => '',},
{col1 => 'Log-in Help',
col2 => 'Value'}],
},
'defaults' =>
{ text => 'Default authentication/language/timezone/portal',
help => 'Domain_Configuration_LangTZAuth',
header => [{col1 => 'Setting',
col2 => 'Value'}],
},
'quotas' =>
{ text => 'Blogs, personal web pages, webDAV/quotas, portfolios',
help => 'Domain_Configuration_Quotas',
header => [{col1 => 'User affiliation',
col2 => 'Available tools',
col3 => 'Quotas, MB; (Authoring requires role)',}],
},
'autoenroll' =>
{ text => 'Auto-enrollment settings',
help => 'Domain_Configuration_Auto_Enrollment',
header => [{col1 => 'Configuration setting',
col2 => 'Value(s)'}],
},
'autoupdate' =>
{ text => 'Auto-update settings',
help => 'Domain_Configuration_Auto_Updates',
header => [{col1 => 'Setting',
col2 => 'Value',},
{col1 => 'Setting',
col2 => 'Affiliation'},
{col1 => 'User population',
col2 => 'Updatable user data'}],
},
'autocreate' =>
{ text => 'Auto-course creation settings',
help => 'Domain_Configuration_Auto_Creation',
header => [{col1 => 'Configuration Setting',
col2 => 'Value',}],
},
'directorysrch' =>
{ text => 'Institutional directory searches',
help => 'Domain_Configuration_InstDirectory_Search',
header => [{col1 => 'Setting',
col2 => 'Value',}],
},
'contacts' =>
{ text => 'Contact Information',
help => 'Domain_Configuration_Contact_Info',
header => [{col1 => 'Setting',
col2 => 'Value',}],
},
'usercreation' =>
{ text => 'User creation',
help => 'Domain_Configuration_User_Creation',
header => [{col1 => 'Format rule type',
col2 => 'Format rules in force'},
{col1 => 'User account creation',
col2 => 'Usernames which may be created',},
{col1 => 'Context',
col2 => 'Assignable authentication types'}],
},
'selfcreation' =>
{ text => 'Users self-creating accounts',
help => 'Domain_Configuration_Self_Creation',
header => [{col1 => 'Self-creation with institutional username',
col2 => 'Enabled?'},
{col1 => 'Institutional user type (login/SSO self-creation)',
col2 => 'Information user can enter'},
{col1 => 'Self-creation with e-mail as username',
col2 => 'Settings'}],
},
'usermodification' =>
{ text => 'User modification',
help => 'Domain_Configuration_User_Modification',
header => [{col1 => 'Target user has role',
col2 => 'User information updatable in author context'},
{col1 => 'Target user has role',
col2 => 'User information updatable in course context'}],
},
'scantron' =>
{ text => 'Bubblesheet format file',
help => 'Domain_Configuration_Scantron_Format',
header => [ {col1 => 'Item',
col2 => '',
}],
},
'requestcourses' =>
{text => 'Request creation of courses',
help => 'Domain_Configuration_Request_Courses',
header => [{col1 => 'User affiliation',
col2 => 'Availability/Processing of requests',},
{col1 => 'Setting',
col2 => 'Value'},
{col1 => 'Available textbooks',
col2 => ''}],
},
'requestauthor' =>
{text => 'Request Authoring Space',
help => 'Domain_Configuration_Request_Author',
header => [{col1 => 'User affiliation',
col2 => 'Availability/Processing of requests',},
{col1 => 'Setting',
col2 => 'Value'}],
},
'coursecategories' =>
{ text => 'Cataloging of courses/communities',
help => 'Domain_Configuration_Cataloging_Courses',
header => [{col1 => 'Category settings',
col2 => '',},
{col1 => 'Categories',
col2 => '',
}],
},
'serverstatuses' =>
{text => 'Access to server status pages',
help => 'Domain_Configuration_Server_Status',
header => [{col1 => 'Status Page',
col2 => 'Other named users',
col3 => 'Specific IPs',
}],
},
'helpsettings' =>
{text => 'Help page settings',
help => 'Domain_Configuration_Help_Settings',
header => [{col1 => 'Help Settings (logged-in users)',
col2 => 'Value'}],
},
'coursedefaults' =>
{text => 'Course/Community defaults',
help => 'Domain_Configuration_Course_Defaults',
header => [{col1 => 'Defaults which can be overridden in each course by a CC',
col2 => 'Value',},
{col1 => 'Defaults which can be overridden for each course by a DC',
col2 => 'Value',},],
},
'privacy' =>
{text => 'User Privacy',
help => 'Domain_Configuration_User_Privacy',
header => [{col1 => 'Setting',
col2 => 'Value',}],
},
'usersessions' =>
{text => 'User session hosting/offloading',
help => 'Domain_Configuration_User_Sessions',
header => [{col1 => 'Domain server',
col2 => 'Servers to offload sessions to when busy'},
{col1 => 'Hosting of users from other domains',
col2 => 'Rules'},
{col1 => "Hosting domain's own users elsewhere",
col2 => 'Rules'}],
},
'loadbalancing' =>
{text => 'Dedicated Load Balancer(s)',
help => 'Domain_Configuration_Load_Balancing',
header => [{col1 => 'Balancers',
col2 => 'Default destinations',
col3 => 'User affiliation',
col4 => 'Overrides'},
],
},
);
if (keys(%servers) > 1) {
$prefs{'login'} = { text => 'Log-in page options',
help => 'Domain_Configuration_Login_Page',
header => [{col1 => 'Log-in Service',
col2 => 'Server Setting',},
{col1 => 'Log-in Page Items',
col2 => ''},
{col1 => 'Log-in Help',
col2 => 'Value'}],
};
}
my @roles = ('student','coordinator','author','admin');
my @actions = &Apache::loncommon::get_env_multiple('form.actions');
&Apache::lonhtmlcommon::add_breadcrumb
({href=>"javascript:changePage(document.$phase,'pickactions')",
text=>"Settings to display/modify"});
my $confname = $dom.'-domainconfig';
if ($phase eq 'process') {
my $result = &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,
\%prefs,\%domconfig,$confname,\@roles);
if ((ref($result) eq 'HASH') && (keys(%{$result}))) {
$r->rflush();
&devalidate_remote_domconfs($dom,$result);
}
} elsif ($phase eq 'display') {
my $js = &recaptcha_js().
&credits_js();
if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
my ($othertitle,$usertypes,$types) =
&Apache::loncommon::sorted_inst_types($dom);
$js .= &lonbalance_targets_js($dom,$types,\%servers,
$domconfig{'loadbalancing'}).
&new_spares_js().
&common_domprefs_js().
&Apache::loncommon::javascript_array_indexof();
}
if (grep(/^requestcourses$/,@actions)) {
my $javascript_validations;
my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'});
$js .= <<END;
<script type="text/javascript">
$javascript_validations
</script>
$coursebrowserjs
END
}
&Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
} else {
# check if domconfig user exists for the domain.
my $servadm = $r->dir_config('lonAdmEMail');
my ($configuserok,$author_ok,$switchserver) =
&config_check($dom,$confname,$servadm);
unless ($configuserok eq 'ok') {
&Apache::lonconfigsettings::print_header($r,$phase,$context);
$r->print(&mt('The domain configuration user "[_1]" has yet to be created.',
$confname).
'<br />'
);
if ($switchserver) {
$r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.').
'<br />'.
&mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.').
'<br />'.
&mt('The "[_1]" user can be created automatically when a Domain Coordinator visits the web-based "Set domain configuration" screen, in a session hosted on the primary library server.',$confname).
'<br />'.
&mt('To do that now, use the following link: [_1]',$switchserver)
);
} else {
$r->print(&mt('To create that user from the command line run the ./UPDATE script found in the top level directory of the extracted LON-CAPA tarball.').
'<br />'.
&mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain')
);
}
$r->print(&Apache::loncommon::end_page());
return OK;
}
if (keys(%domconfig) == 0) {
my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
my @ids=&Apache::lonnet::current_machine_ids();
if (!grep(/^\Q$primarylibserv\E$/,@ids)) {
my %designhash = &Apache::loncommon::get_domainconf($dom);
my @loginimages = ('img','logo','domlogo','login');
my $custom_img_count = 0;
foreach my $img (@loginimages) {
if ($designhash{$dom.'.login.'.$img} ne '') {
$custom_img_count ++;
}
}
foreach my $role (@roles) {
if ($designhash{$dom.'.'.$role.'.img'} ne '') {
$custom_img_count ++;
}
}
if ($custom_img_count > 0) {
&Apache::lonconfigsettings::print_header($r,$phase,$context);
my $switch_server = &check_switchserver($dom,$confname);
$r->print(
&mt('Domain configuration settings have yet to be saved for this domain via the web-based domain preferences interface.').'<br />'.
&mt("While this remains so, you must switch to the domain's primary library server in order to update settings.").'<br /><br />'.
&mt("Thereafter, (with a Domain Coordinator role selected in the domain) you will be able to update settings when logged in to any server in the LON-CAPA network.").'<br />'.
&mt("However, you will still need to switch to the domain's primary library server to upload new images or logos.").'<br /><br />');
if ($switch_server) {
$r->print($switch_server.' '.&mt('to primary library server for domain: [_1]',$dom));
}
$r->print(&Apache::loncommon::end_page());
return OK;
}
}
}
&Apache::lonconfigsettings::display_choices($r,$phase,$context,\@prefs_order,\%prefs);
}
return OK;
}
sub process_changes {
my ($r,$dom,$confname,$action,$roles,$values,$lastactref) = @_;
my %domconfig;
if (ref($values) eq 'HASH') {
%domconfig = %{$values};
}
my $output;
if ($action eq 'login') {
$output = &modify_login($r,$dom,$confname,$lastactref,%domconfig);
} elsif ($action eq 'rolecolors') {
$output = &modify_rolecolors($r,$dom,$confname,$roles,
$lastactref,%domconfig);
} elsif ($action eq 'quotas') {
$output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
} elsif ($action eq 'autoenroll') {
$output = &modify_autoenroll($dom,$lastactref,%domconfig);
} elsif ($action eq 'autoupdate') {
$output = &modify_autoupdate($dom,%domconfig);
} elsif ($action eq 'autocreate') {
$output = &modify_autocreate($dom,%domconfig);
} elsif ($action eq 'directorysrch') {
$output = &modify_directorysrch($dom,%domconfig);
} elsif ($action eq 'usercreation') {
$output = &modify_usercreation($dom,%domconfig);
} elsif ($action eq 'selfcreation') {
$output = &modify_selfcreation($dom,%domconfig);
} elsif ($action eq 'usermodification') {
$output = &modify_usermodification($dom,%domconfig);
} elsif ($action eq 'contacts') {
$output = &modify_contacts($dom,$lastactref,%domconfig);
} elsif ($action eq 'defaults') {
$output = &modify_defaults($dom,$lastactref,%domconfig);
} elsif ($action eq 'scantron') {
$output = &modify_scantron($r,$dom,$confname,$lastactref,%domconfig);
} elsif ($action eq 'coursecategories') {
$output = &modify_coursecategories($dom,%domconfig);
} elsif ($action eq 'serverstatuses') {
$output = &modify_serverstatuses($dom,%domconfig);
} elsif ($action eq 'requestcourses') {
$output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
} elsif ($action eq 'requestauthor') {
$output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
} elsif ($action eq 'helpsettings') {
$output = &modify_helpsettings($r,$dom,$confname,%domconfig);
} elsif ($action eq 'coursedefaults') {
$output = &modify_coursedefaults($dom,$lastactref,%domconfig);
} elsif ($action eq 'usersessions') {
$output = &modify_usersessions($dom,$lastactref,%domconfig);
} elsif ($action eq 'loadbalancing') {
$output = &modify_loadbalancing($dom,%domconfig);
}
return $output;
}
sub print_config_box {
my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_;
my $rowtotal = 0;
my $output;
if ($action eq 'coursecategories') {
$output = &coursecategories_javascript($settings);
}
$output .=
'<table class="LC_nested_outer">
<tr>
<th align="left" valign="middle"><span class="LC_nobreak">'.
&mt($item->{text}).' '.
&Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".
'</tr>';
$rowtotal ++;
my $numheaders = 1;
if (ref($item->{'header'}) eq 'ARRAY') {
$numheaders = scalar(@{$item->{'header'}});
}
if ($numheaders > 1) {
my $colspan = '';
my $rightcolspan = '';
if (($action eq 'rolecolors') || ($action eq 'coursecategories') ||
(($action eq 'login') && ($numheaders < 3))) {
$colspan = ' colspan="2"';
}
if ($action eq 'usersessions') {
$rightcolspan = ' colspan="3"';
}
$output .= '
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
<td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
</tr>';
$rowtotal ++;
if ($action eq 'autoupdate') {
$output .= &print_autoupdate('top',$dom,$settings,\$rowtotal);
} elsif ($action eq 'usercreation') {
$output .= &print_usercreation('top',$dom,$settings,\$rowtotal);
} elsif ($action eq 'selfcreation') {
$output .= &print_selfcreation('top',$dom,$settings,\$rowtotal);
} elsif ($action eq 'usermodification') {
$output .= &print_usermodification('top',$dom,$settings,\$rowtotal);
} elsif ($action eq 'coursecategories') {
$output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal);
} elsif ($action eq 'login') {
if ($numheaders == 3) {
$colspan = ' colspan="2"';
$output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);
} else {
$output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal);
}
} elsif ($action eq 'requestcourses') {
$output .= &print_quotas($dom,$settings,\$rowtotal,$action);
} elsif ($action eq 'requestauthor') {
$output .= &print_quotas($dom,$settings,\$rowtotal,$action);
} elsif ($action eq 'usersessions') {
$output .= &print_usersessions('top',$dom,$settings,\$rowtotal);
} elsif ($action eq 'rolecolors') {
$output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'coursedefaults') {
$output .= &print_coursedefaults('top',$dom,$settings,\$rowtotal);
}
$output .= '
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';
$output .= '
<td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
</tr>';
$rowtotal ++;
if ($action eq 'autoupdate') {
$output .= &print_autoupdate('middle',$dom,$settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
<td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
&print_autoupdate('bottom',$dom,$settings,\$rowtotal);
$rowtotal ++;
} elsif ($action eq 'usercreation') {
$output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
<td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
&print_usercreation('bottom',$dom,$settings,\$rowtotal);
$rowtotal ++;
} elsif ($action eq 'selfcreation') {
$output .= &print_selfcreation('middle',$dom,$settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
<td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
</tr>'.
&print_selfcreation('bottom',$dom,$settings,\$rowtotal);
$rowtotal ++;
} elsif ($action eq 'usermodification') {
$output .= &print_usermodification('middle',$dom,$settings,\$rowtotal);
} elsif ($action eq 'coursecategories') {
$output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
} elsif ($action eq 'login') {
if ($numheaders == 3) {
$output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
<td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
&print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
$rowtotal ++;
} else {
$output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
}
} elsif ($action eq 'requestcourses') {
$output .= &print_requestmail($dom,$action,$settings,\$rowtotal).
&print_studentcode($settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
<td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
&print_textbookcourses($dom,$settings,\$rowtotal);
} elsif ($action eq 'requestauthor') {
$output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
} elsif ($action eq 'usersessions') {
$output .= &print_usersessions('middle',$dom,$settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
<td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
&print_usersessions('bottom',$dom,$settings,\$rowtotal);
$rowtotal ++;
} elsif ($action eq 'coursedefaults') {
$output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal);
} elsif ($action eq 'rolecolors') {
$output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.' valign="top">'.
&mt($item->{'header'}->[2]->{'col1'}).'</td>
<td class="LC_right_item" valign="top">'.
&mt($item->{'header'}->[2]->{'col2'}).'</td>
</tr>'.
&print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
</table>
</td>
</tr>
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">
<td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
<td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
</tr>'.
&print_rolecolors($phase,'admin',$dom,$confname,$settings,\$rowtotal);
$rowtotal += 2;
}
} else {
$output .= '
<tr>
<td>
<table class="LC_nested">
<tr class="LC_info_row">';
if (($action eq 'login') || ($action eq 'directorysrch')) {
$output .= '
<td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
} elsif ($action eq 'serverstatuses') {
$output .= '
<td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).
'<br />('.&mt('Automatic access for Dom. Coords.').')</td>';
} else {
$output .= '
<td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
}
if (defined($item->{'header'}->[0]->{'col3'})) {
$output .= '<td class="LC_left_item" valign="top">'.
&mt($item->{'header'}->[0]->{'col2'});
if ($action eq 'serverstatuses') {
$output .= '<br />(<tt>'.&mt('user1:domain1,user2:domain2 etc.').'</tt>)';
}
} else {
$output .= '<td class="LC_right_item" valign="top">'.
&mt($item->{'header'}->[0]->{'col2'});
}
$output .= '</td>';
if ($item->{'header'}->[0]->{'col3'}) {
if (defined($item->{'header'}->[0]->{'col4'})) {
$output .= '<td class="LC_left_item" valign="top">'.
&mt($item->{'header'}->[0]->{'col3'});
} else {
$output .= '<td class="LC_right_item" valign="top">'.
&mt($item->{'header'}->[0]->{'col3'});
}
if ($action eq 'serverstatuses') {
$output .= '<br />(<tt>'.&mt('IP1,IP2 etc.').'</tt>)';
}
$output .= '</td>';
}
if ($item->{'header'}->[0]->{'col4'}) {
$output .= '<td class="LC_right_item" valign="top">'.
&mt($item->{'header'}->[0]->{'col4'});
}
$output .= '</tr>';
$rowtotal ++;
if ($action eq 'quotas') {
$output .= &print_quotas($dom,$settings,\$rowtotal,$action);
} elsif ($action eq 'autoenroll') {
$output .= &print_autoenroll($dom,$settings,\$rowtotal);
} elsif ($action eq 'autocreate') {
$output .= &print_autocreate($dom,$settings,\$rowtotal);
} elsif ($action eq 'directorysrch') {
$output .= &print_directorysrch($dom,$settings,\$rowtotal);
} elsif ($action eq 'contacts') {
$output .= &print_contacts($dom,$settings,\$rowtotal);
} elsif ($action eq 'defaults') {
$output .= &print_defaults($dom,$settings,\$rowtotal);
} elsif ($action eq 'scantron') {
$output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'serverstatuses') {
$output .= &print_serverstatuses($dom,$settings,\$rowtotal);
} elsif ($action eq 'helpsettings') {
$output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'loadbalancing') {
$output .= &print_loadbalancing($dom,$settings,\$rowtotal);
}
}
$output .= '
</table>
</td>
</tr>
</table><br />';
return ($output,$rowtotal);
}
sub print_login {
my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_;
my ($css_class,$datatable);
my %choices = &login_choices();
if ($caller eq 'service') {
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my $choice = $choices{'disallowlogin'};
$css_class = ' class="LC_odd_row"';
$datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.
'<td align="right"><table><tr><th>'.$choices{'hostid'}.'</th>'.
'<th>'.$choices{'server'}.'</th>'.
'<th>'.$choices{'serverpath'}.'</th>'.
'<th>'.$choices{'custompath'}.'</th>'.
'<th><span class="LC_nobreak">'.$choices{'exempt'}.'</span></th></tr>'."\n";
my %disallowed;
if (ref($settings) eq 'HASH') {
if (ref($settings->{'loginvia'}) eq 'HASH') {
%disallowed = %{$settings->{'loginvia'}};
}
}
foreach my $lonhost (sort(keys(%servers))) {
my $direct = 'selected="selected"';
if (ref($disallowed{$lonhost}) eq 'HASH') {
if ($disallowed{$lonhost}{'server'} ne '') {
$direct = '';
}
}
$datatable .= '<tr><td>'.$servers{$lonhost}.'</td>'.
'<td><select name="'.$lonhost.'_server">'.
'<option value=""'.$direct.'>'.$choices{'directlogin'}.
'</option>';
foreach my $hostid (sort(keys(%servers))) {
next if ($servers{$hostid} eq $servers{$lonhost});
my $selected = '';
if (ref($disallowed{$lonhost}) eq 'HASH') {
if ($hostid eq $disallowed{$lonhost}{'server'}) {
$selected = 'selected="selected"';
}
}
$datatable .= '<option value="'.$hostid.'"'.$selected.'>'.
$servers{$hostid}.'</option>';
}
$datatable .= '</select></td>'.
'<td><select name="'.$lonhost.'_serverpath">';
foreach my $path ('','/','/adm/login','/adm/roles','custom') {
my $pathname = $path;
if ($path eq 'custom') {
$pathname = &mt('Custom Path').' ->';
}
my $selected = '';
if (ref($disallowed{$lonhost}) eq 'HASH') {
if ($path eq $disallowed{$lonhost}{'serverpath'}) {
$selected = 'selected="selected"';
}
} elsif ($path eq '') {
$selected = 'selected="selected"';
}
$datatable .= '<option value="'.$path.'"'.$selected.'>'.$pathname.'</option>';
}
$datatable .= '</select></td>';
my ($custom,$exempt);
if (ref($disallowed{$lonhost}) eq 'HASH') {
$custom = $disallowed{$lonhost}{'custompath'};
$exempt = $disallowed{$lonhost}{'exempt'};
}
$datatable .= '<td><input type="text" name="'.$lonhost.'_custompath" size="6" value="'.$custom.'" /></td>'.
'<td><input type="text" name="'.$lonhost.'_exempt" size="8" value="'.$exempt.'" /></td>'.
'</tr>';
}
$datatable .= '</table></td></tr>';
return $datatable;
} elsif ($caller eq 'page') {
my %defaultchecked = (
'coursecatalog' => 'on',
'helpdesk' => 'on',
'adminmail' => 'off',
'newuser' => 'off',
);
my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
my (%checkedon,%checkedoff);
foreach my $item (@toggles) {
if ($defaultchecked{$item} eq 'on') {
$checkedon{$item} = ' checked="checked" ';
$checkedoff{$item} = ' ';
} elsif ($defaultchecked{$item} eq 'off') {
$checkedoff{$item} = ' checked="checked" ';
$checkedon{$item} = ' ';
}
}
my @images = ('img','logo','domlogo','login');
my @logintext = ('textcol','bgcol');
my @bgs = ('pgbg','mainbg','sidebg');
my @links = ('link','alink','vlink');
my %designhash = &Apache::loncommon::get_domainconf($dom);
my %defaultdesign = %Apache::loncommon::defaultdesign;
my (%is_custom,%designs);
my %defaults = (
font => $defaultdesign{'login.font'},
);
foreach my $item (@images) {
$defaults{$item} = $defaultdesign{'login.'.$item};
$defaults{'showlogo'}{$item} = 1;
}
foreach my $item (@bgs) {
$defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};
}
foreach my $item (@logintext) {
$defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};
}
foreach my $item (@links) {
$defaults{'links'}{$item} = $defaultdesign{'login.'.$item};
}
if (ref($settings) eq 'HASH') {
foreach my $item (@toggles) {
if ($settings->{$item} eq '1') {
$checkedon{$item} = ' checked="checked" ';
$checkedoff{$item} = ' ';
} elsif ($settings->{$item} eq '0') {
$checkedoff{$item} = ' checked="checked" ';
$checkedon{$item} = ' ';
}
}
foreach my $item (@images) {
if (defined($settings->{$item})) {
$designs{$item} = $settings->{$item};
$is_custom{$item} = 1;
}
if (defined($settings->{'showlogo'}{$item})) {
$designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};
}
}
foreach my $item (@logintext) {
if ($settings->{$item} ne '') {
$designs{'logintext'}{$item} = $settings->{$item};
$is_custom{$item} = 1;
}
}
if ($settings->{'font'} ne '') {
$designs{'font'} = $settings->{'font'};
$is_custom{'font'} = 1;
}
foreach my $item (@bgs) {
if ($settings->{$item} ne '') {
$designs{'bgs'}{$item} = $settings->{$item};
$is_custom{$item} = 1;
}
}
foreach my $item (@links) {
if ($settings->{$item} ne '') {
$designs{'links'}{$item} = $settings->{$item};
$is_custom{$item} = 1;
}
}
} else {
if ($designhash{$dom.'.login.font'} ne '') {
$designs{'font'} = $designhash{$dom.'.login.font'};
$is_custom{'font'} = 1;
}
foreach my $item (@images) {
if ($designhash{$dom.'.login.'.$item} ne '') {
$designs{$item} = $designhash{$dom.'.login.'.$item};
$is_custom{$item} = 1;
}
}
foreach my $item (@bgs) {
if ($designhash{$dom.'.login.'.$item} ne '') {
$designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item};
$is_custom{$item} = 1;
}
}
foreach my $item (@links) {
if ($designhash{$dom.'.login.'.$item} ne '') {
$designs{'links'}{$item} = $designhash{$dom.'.login.'.$item};
$is_custom{$item} = 1;
}
}
}
my %alt_text = &Apache::lonlocal::texthash ( img => 'Log-in banner',
logo => 'Institution Logo',
domlogo => 'Domain Logo',
login => 'Login box');
my $itemcount = 1;
foreach my $item (@toggles) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .=
'<tr'.$css_class.'><td colspan="2">'.$choices{$item}.
'</td><td>'.
'<span class="LC_nobreak"><label><input type="radio" name="'.
$item.'"'.$checkedon{$item}.' value="1" />'.&mt('Yes').
'</label> <label><input type="radio" name="'.$item.'"'.
$checkedoff{$item}.' value="0" />'.&mt('No').'</label></span></td>'.
'</tr>';
$itemcount ++;
}
$datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext);
$datatable .= '</tr></table></td></tr>';
} elsif ($caller eq 'help') {
my ($defaulturl,$defaulttype,%url,%type,%lt,%langchoices);
my $switchserver = &check_switchserver($dom,$confname);
my $itemcount = 1;
$defaulturl = '/adm/loginproblems.html';
$defaulttype = 'default';
%lt = &Apache::lonlocal::texthash (
del => 'Delete?',
rep => 'Replace:',
upl => 'Upload:',
default => 'Default',
custom => 'Custom',
);
%langchoices = &Apache::lonlocal::texthash(&get_languages_hash());
my @currlangs;
if (ref($settings) eq 'HASH') {
if (ref($settings->{'helpurl'}) eq 'HASH') {
foreach my $key (sort(keys(%{$settings->{'helpurl'}}))) {
next if ($settings->{'helpurl'}{$key} eq '');
$url{$key} = $settings->{'helpurl'}{$key}.'?inhibitmenu=yes';
$type{$key} = 'custom';
unless ($key eq 'nolang') {
push(@currlangs,$key);
}
}
} elsif ($settings->{'helpurl'} ne '') {
$type{'nolang'} = 'custom';
$url{'nolang'} = $settings->{'helpurl'}.'?inhibitmenu=yes';
}
}
foreach my $lang ('nolang',sort(@currlangs)) {
$css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
$datatable .= '<tr'.$css_class.'>';
if ($url{$lang} eq '') {
$url{$lang} = $defaulturl;
}
if ($type{$lang} eq '') {
$type{$lang} = $defaulttype;
}
$datatable .= '<td colspan="2"><span class="LC_nobreak">';
if ($lang eq 'nolang') {
$datatable .= &mt('Log-in help page if no specific language file: [_1]',
&Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500));
} else {
$datatable .= &mt('Log-in help page for language: [_1] is [_2]',
$langchoices{$lang},
&Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500));
}
$datatable .= '</span></td>'."\n".
'<td class="LC_left_item">';
if ($type{$lang} eq 'custom') {
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="loginhelpurl_del" value="'.$lang.'" />'.
$lt{'del'}.'</label> '.$lt{'rep'}.'</span>';
} else {
$datatable .= $lt{'upl'};
}
$datatable .='<br />';
if ($switchserver) {
$datatable .= &mt('Upload to library server: [_1]',$switchserver);
} else {
$datatable .= '<input type="file" name="loginhelpurl_'.$lang.'" />';
}
$datatable .= '</td></tr>';
$itemcount ++;
}
my @addlangs;
foreach my $lang (sort(keys(%langchoices))) {
next if ((grep(/^\Q$lang\E$/,@currlangs)) || ($lang eq 'x_chef'));
push(@addlangs,$lang);
}
if (@addlangs > 0) {
my %toadd;
map { $toadd{$_} = $langchoices{$_} ; } @addlangs;
$toadd{''} = &mt('Select');
$css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
$datatable .= '<tr'.$css_class.'><td class="LC_left_item" colspan="2">'.
&mt('Add log-in help page for a specific language:').' '.
&Apache::loncommon::select_form('','loginhelpurl_add_lang',\%toadd).
'</td><td class="LC_left_item">'.$lt{'upl'}.'<br />';
if ($switchserver) {
$datatable .= &mt('Upload to library server: [_1]',$switchserver);
} else {
$datatable .= '<input type="file" name="loginhelpurl_add_file" />';
}
$datatable .= '</td></tr>';
$itemcount ++;
}
$datatable .= &captcha_choice('login',$settings,$itemcount);
}
return $datatable;
}
sub login_choices {
my %choices =
&Apache::lonlocal::texthash (
coursecatalog => 'Display Course/Community Catalog link?',
adminmail => "Display Administrator's E-mail Address?",
helpdesk => 'Display "Contact Helpdesk" link',
disallowlogin => "Login page requests redirected",
hostid => "Server",
server => "Redirect to:",
serverpath => "Path",
custompath => "Custom",
exempt => "Exempt IP(s)",
directlogin => "No redirect",
newuser => "Link to create a user account",
img => "Header",
logo => "Main Logo",
domlogo => "Domain Logo",
login => "Log-in Header",
textcol => "Text color",
bgcol => "Box color",
bgs => "Background colors",
links => "Link colors",
font => "Font color",
pgbg => "Header",
mainbg => "Page",
sidebg => "Login box",
link => "Link",
alink => "Active link",
vlink => "Visited link",
);
return %choices;
}
sub print_rolecolors {
my ($phase,$role,$dom,$confname,$settings,$rowtotal) = @_;
my %choices = &color_font_choices();
my @bgs = ('pgbg','tabbg','sidebg');
my @links = ('link','alink','vlink');
my @images = ('img');
my %alt_text = &Apache::lonlocal::texthash(img => "Banner for $role role");
my %designhash = &Apache::loncommon::get_domainconf($dom);
my %defaultdesign = %Apache::loncommon::defaultdesign;
my (%is_custom,%designs);
my %defaults = &role_defaults($role,\@bgs,\@links,\@images);
if (ref($settings) eq 'HASH') {
if (ref($settings->{$role}) eq 'HASH') {
if ($settings->{$role}->{'img'} ne '') {
$designs{'img'} = $settings->{$role}->{'img'};
$is_custom{'img'} = 1;
}
if ($settings->{$role}->{'font'} ne '') {
$designs{'font'} = $settings->{$role}->{'font'};
$is_custom{'font'} = 1;
}
if ($settings->{$role}->{'fontmenu'} ne '') {
$designs{'fontmenu'} = $settings->{$role}->{'fontmenu'};
$is_custom{'fontmenu'} = 1;
}
foreach my $item (@bgs) {
if ($settings->{$role}->{$item} ne '') {
$designs{'bgs'}{$item} = $settings->{$role}->{$item};
$is_custom{$item} = 1;
}
}
foreach my $item (@links) {
if ($settings->{$role}->{$item} ne '') {
$designs{'links'}{$item} = $settings->{$role}->{$item};
$is_custom{$item} = 1;
}
}
}
} else {
if ($designhash{$dom.'.'.$role.'.img'} ne '') {
$designs{img} = $designhash{$dom.'.'.$role.'.img'};
$is_custom{'img'} = 1;
}
if ($designhash{$dom.'.'.$role.'.fontmenu'} ne '') {
$designs{fontmenu} = $designhash{$dom.'.'.$role.'.fontmenu'};
$is_custom{'fontmenu'} = 1;
}
if ($designhash{$dom.'.'.$role.'.font'} ne '') {
$designs{font} = $designhash{$dom.'.'.$role.'.font'};
$is_custom{'font'} = 1;
}
foreach my $item (@bgs) {
if ($designhash{$dom.'.'.$role.'.'.$item} ne '') {
$designs{'bgs'}{$item} = $designhash{$dom.'.'.$role.'.'.$item};
$is_custom{$item} = 1;
}
}
foreach my $item (@links) {
if ($designhash{$dom.'.'.$role.'.'.$item} ne '') {
$designs{'links'}{$item} = $designhash{$dom.'.'.$role.'.'.$item};
$is_custom{$item} = 1;
}
}
}
my $itemcount = 1;
my $datatable = &display_color_options($dom,$confname,$phase,$role,$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal);
$datatable .= '</tr></table></td></tr>';
return $datatable;
}
sub role_defaults {
my ($role,$bgs,$links,$images,$logintext) = @_;
my %defaults;
unless ((ref($bgs) eq 'ARRAY') && (ref($links) eq 'ARRAY') && (ref($images) eq 'ARRAY')) {
return %defaults;
}
my %defaultdesign = %Apache::loncommon::defaultdesign;
if ($role eq 'login') {
%defaults = (
font => $defaultdesign{$role.'.font'},
);
if (ref($logintext) eq 'ARRAY') {
foreach my $item (@{$logintext}) {
$defaults{'logintext'}{$item} = $defaultdesign{$role.'.'.$item};
}
}
foreach my $item (@{$images}) {
$defaults{'showlogo'}{$item} = 1;
}
} else {
%defaults = (
img => $defaultdesign{$role.'.img'},
font => $defaultdesign{$role.'.font'},
fontmenu => $defaultdesign{$role.'.fontmenu'},
);
}
foreach my $item (@{$bgs}) {
$defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};
}
foreach my $item (@{$links}) {
$defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};
}
foreach my $item (@{$images}) {
$defaults{$item} = $defaultdesign{$role.'.'.$item};
}
return %defaults;
}
sub display_color_options {
my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,
$images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;
my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
my $css_class = $itemcount%2?' class="LC_odd_row"':'';
my $datatable = '<tr'.$css_class.'>'.
'<td>'.$choices->{'font'}.'</td>';
if (!$is_custom->{'font'}) {
$datatable .= '<td>'.&mt('Default in use:').' <span id="css_default_'.$role.'_font" style="color: '.$defaults->{'font'}.';">'.$defaults->{'font'}.'</span></td>';
} else {
$datatable .= '<td> </td>';
}
my $current_color = $designs->{'font'} ? $designs->{'font'} : $defaults->{'font'};
$datatable .= '<td><span class="LC_nobreak">'.
'<input type="text" class="colorchooser" size="10" name="'.$role.'_font"'.
' value="'.$current_color.'" /> '.
' </td></tr>';
unless ($role eq 'login') {
$datatable .= '<tr'.$css_class.'>'.
'<td>'.$choices->{'fontmenu'}.'</td>';
if (!$is_custom->{'fontmenu'}) {
$datatable .= '<td>'.&mt('Default in use:').' <span id="css_default_'.$role.'_font" style="color: '.$defaults->{'fontmenu'}.';">'.$defaults->{'fontmenu'}.'</span></td>';
} else {
$datatable .= '<td> </td>';
}
$current_color = $designs->{'fontmenu'} ?
$designs->{'fontmenu'} : $defaults->{'fontmenu'};
$datatable .= '<td><span class="LC_nobreak">'.
'<input class="colorchooser" type="text" size="10" name="'
.$role.'_fontmenu"'.
' value="'.$current_color.'" /> '.
' </td></tr>';
}
my $switchserver = &check_switchserver($dom,$confname);
foreach my $img (@{$images}) {
$itemcount ++;
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td>'.$choices->{$img};
my ($imgfile,$img_import,$login_hdr_pick,$logincolors);
if ($role eq 'login') {
if ($img eq 'login') {
$login_hdr_pick =
&login_header_options($img,$role,$defaults,$is_custom,$choices);
$logincolors =
&login_text_colors($img,$role,$logintext,$phase,$choices,
$designs,$defaults);
} elsif ($img ne 'domlogo') {
$datatable.= &logo_display_options($img,$defaults,$designs);
}
}
$datatable .= '</td>';
if ($designs->{$img} ne '') {
$imgfile = $designs->{$img};
$img_import = ($imgfile =~ m{^/adm/});
} else {
$imgfile = $defaults->{$img};
}
if ($imgfile) {
my ($showfile,$fullsize);
if ($imgfile =~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) {
my $urldir = $1;
my $filename = $2;
my @info = &Apache::lonnet::stat_file($designs->{$img});
if (@info) {
my $thumbfile = 'tn-'.$filename;
my @thumb=&Apache::lonnet::stat_file($urldir.'/'.$thumbfile);
if (@thumb) {
$showfile = $urldir.'/'.$thumbfile;
} else {
$showfile = $imgfile;
}
} else {
$showfile = '';
}
} elsif ($imgfile =~ m-^/(adm/[^/]+)/([^/]+)$-) {
$showfile = $imgfile;
my $imgdir = $1;
my $filename = $2;
if (-e "$londocroot/$imgdir/tn-".$filename) {
$showfile = "/$imgdir/tn-".$filename;
} else {
my $input = $londocroot.$imgfile;
my $output = "$londocroot/$imgdir/tn-".$filename;
if (!-e $output) {
my ($width,$height) = &thumb_dimensions();
my ($fullwidth,$fullheight) = &check_dimensions($input);
if ($fullwidth ne '' && $fullheight ne '') {
if ($fullwidth > $width && $fullheight > $height) {
my $size = $width.'x'.$height;
system("convert -sample $size $input $output");
$showfile = "/$imgdir/tn-".$filename;
}
}
}
}
}
if ($showfile) {
if ($showfile =~ m{^/(adm|res)/}) {
if ($showfile =~ m{^/res/}) {
my $local_showfile =
&Apache::lonnet::filelocation('',$showfile);
&Apache::lonnet::repcopy($local_showfile);
}
$showfile = &Apache::loncommon::lonhttpdurl($showfile);
}
if ($imgfile) {
if ($imgfile =~ m{^/(adm|res)/}) {
if ($imgfile =~ m{^/res/}) {
my $local_imgfile =
&Apache::lonnet::filelocation('',$imgfile);
&Apache::lonnet::repcopy($local_imgfile);
}
$fullsize = &Apache::loncommon::lonhttpdurl($imgfile);
} else {
$fullsize = $imgfile;
}
}
$datatable .= '<td>';
if ($img eq 'login') {
$datatable .= $login_hdr_pick;
}
$datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,
$showfile,$fullsize,$role,$img,$imgfile,$logincolors);
} else {
$datatable .= '<td> </td><td class="LC_left_item">'.
&mt('Upload:').'<br />';
}
} else {
$datatable .= '<td> </td><td class="LC_left_item">'.
&mt('Upload:').'<br />';
}
if ($switchserver) {
$datatable .= &mt('Upload to library server: [_1]',$switchserver);
} else {
if ($img ne 'login') { # suppress file selection for Log-in header
$datatable .=' <input type="file" name="'.$role.'_'.$img.'" />';
}
}
$datatable .= '</td></tr>';
}
$itemcount ++;
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td>'.$choices->{'bgs'}.'</td>';
my $bgs_def;
foreach my $item (@{$bgs}) {
if (!$is_custom->{$item}) {
$bgs_def .= '<td><span class="LC_nobreak">'.$choices->{$item}.'</span> <span id="css_default_'.$role.'_'.$item.'" style="background-color: '.$defaults->{'bgs'}{$item}.';"> </span><br />'.$defaults->{'bgs'}{$item}.'</td>';
}
}
if ($bgs_def) {
$datatable .= '<td>'.&mt('Default(s) in use:').'<br /><table border="0"><tr>'.$bgs_def.'</tr></table></td>';
} else {
$datatable .= '<td> </td>';
}
$datatable .= '<td class="LC_right_item">'.
'<table border="0"><tr>';
foreach my $item (@{$bgs}) {
$datatable .= '<td align="center">'.$choices->{$item};
my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};
if ($designs->{'bgs'}{$item}) {
$datatable .= ' ';
}
$datatable .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
'" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
}
$datatable .= '</tr></table></td></tr>';
$itemcount ++;
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td>'.$choices->{'links'}.'</td>';
my $links_def;
foreach my $item (@{$links}) {
if (!$is_custom->{$item}) {
$links_def .= '<td>'.$choices->{$item}.'<br /><span id="css_default_'.$role.'_'.$item.'" style="color: '.$defaults->{'links'}{$item}.';">'.$defaults->{'links'}{$item}.'</span></td>';
}
}
if ($links_def) {
$datatable .= '<td>'.&mt('Default(s) in use:').'<br /><table border="0"><tr>'.$links_def.'</tr></table></td>';
} else {
$datatable .= '<td> </td>';
}
$datatable .= '<td class="LC_right_item">'.
'<table border="0"><tr>';
foreach my $item (@{$links}) {
my $color = $designs->{'link'}{$item} ? $designs->{'link'}{$item} : $defaults->{'links'}{$item};
$datatable .= '<td align="center">'.$choices->{$item}."\n";
if ($designs->{'links'}{$item}) {
$datatable.=' ';
}
$datatable .= '<br /><input type="text" size="8" class="colorchooser" name="'.$role.'_'.$item.'" value="'.$color.
'" /></td>';
}
$$rowtotal += $itemcount;
return $datatable;
}
sub logo_display_options {
my ($img,$defaults,$designs) = @_;
my $checkedon;
if (ref($defaults) eq 'HASH') {
if (ref($defaults->{'showlogo'}) eq 'HASH') {
if ($defaults->{'showlogo'}{$img}) {
$checkedon = 'checked="checked" ';
}
}
}
if (ref($designs) eq 'HASH') {
if (ref($designs->{'showlogo'}) eq 'HASH') {
if (defined($designs->{'showlogo'}{$img})) {
if ($designs->{'showlogo'}{$img} == 0) {
$checkedon = '';
} elsif ($designs->{'showlogo'}{$img} == 1) {
$checkedon = 'checked="checked" ';
}
}
}
}
return '<br /><label> <input type="checkbox" name="'.
'login_showlogo_'.$img.'" value="1" '.$checkedon.'/>'.
&mt('show').'</label>'."\n";
}
sub login_header_options {
my ($img,$role,$defaults,$is_custom,$choices) = @_;
my $output = '';
if ((!$is_custom->{'textcol'}) || (!$is_custom->{'bgcol'})) {
$output .= &mt('Text default(s):').'<br />';
if (!$is_custom->{'textcol'}) {
$output .= $choices->{'textcol'}.': '.$defaults->{'logintext'}{'textcol'}.
' ';
}
if (!$is_custom->{'bgcol'}) {
$output .= $choices->{'bgcol'}.': '.
'<span id="css_'.$role.'_font" style="background-color: '.
$defaults->{'logintext'}{'bgcol'}.';"> </span>';
}
$output .= '<br />';
}
$output .='<br />';
return $output;
}
sub login_text_colors {
my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;
my $color_menu = '<table border="0"><tr>';
foreach my $item (@{$logintext}) {
$color_menu .= '<td align="center">'.$choices->{$item};
my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};
$color_menu .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
'" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
}
$color_menu .= '</tr></table><br />';
return $color_menu;
}
sub image_changes {
my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_;
my $output;
if ($img eq 'login') {
# suppress image for Log-in header
} elsif (!$is_custom) {
if ($img ne 'domlogo') {
$output .= &mt('Default image:').'<br />';
} else {
$output .= &mt('Default in use:').'<br />';
}
}
if ($img eq 'login') { # suppress image for Log-in header
$output .= '<td>'.$logincolors;
} else {
if ($img_import) {
$output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';
}
$output .= '<a href="'.$fullsize.'" target="_blank"><img src="'.
$showfile.'" alt="'.$alt_text.'" border="0" /></a></td>';
if ($is_custom) {
$output .= '<td>'.$logincolors.'<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.
$role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
'</label> '.&mt('Replace:').'</span><br />';
} else {
$output .= '<td valign="middle">'.$logincolors.&mt('Upload:').'<br />';
}
}
return $output;
}
sub print_quotas {
my ($dom,$settings,$rowtotal,$action) = @_;
my $context;
if ($action eq 'quotas') {
$context = 'tools';
} else {
$context = $action;
}
my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations);
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
my $typecount = 0;
my ($css_class,%titles);
if ($context eq 'requestcourses') {
@usertools = ('official','unofficial','community','textbook');
@options =('norequest','approval','validate','autolimit');
%validations = &Apache::lonnet::auto_courserequest_checks($dom);
%titles = &courserequest_titles();
} elsif ($context eq 'requestauthor') {
@usertools = ('author');
@options = ('norequest','approval','automatic');
%titles = &authorrequest_titles();
} else {
@usertools = ('aboutme','blog','webdav','portfolio');
%titles = &tool_titles();
}
if (ref($types) eq 'ARRAY') {
foreach my $type (@{$types}) {
my ($currdefquota,$currauthorquota);
unless (($context eq 'requestcourses') ||
($context eq 'requestauthor')) {
if (ref($settings) eq 'HASH') {
if (ref($settings->{defaultquota}) eq 'HASH') {
$currdefquota = $settings->{defaultquota}->{$type};
} else {
$currdefquota = $settings->{$type};
}
if (ref($settings->{authorquota}) eq 'HASH') {
$currauthorquota = $settings->{authorquota}->{$type};
}
}
}
if (defined($usertypes->{$type})) {
$typecount ++;
$css_class = $typecount%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td>'.$usertypes->{$type}.'</td>'.
'<td class="LC_left_item">';
if ($context eq 'requestcourses') {
$datatable .= '<table><tr>';
}
my %cell;
foreach my $item (@usertools) {
if ($context eq 'requestcourses') {
my ($curroption,$currlimit);
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
$curroption = $settings->{$item}->{$type};
if ($curroption =~ /^autolimit=(\d*)$/) {
$currlimit = $1;
}
}
}
if (!$curroption) {
$curroption = 'norequest';
}
$datatable .= '<th>'.$titles{$item}.'</th>';
foreach my $option (@options) {
my $val = $option;
if ($option eq 'norequest') {
$val = 0;
}
if ($option eq 'validate') {
my $canvalidate = 0;
if (ref($validations{$item}) eq 'HASH') {
if ($validations{$item}{$type}) {
$canvalidate = 1;
}
}
next if (!$canvalidate);
}
my $checked = '';
if ($option eq $curroption) {
$checked = ' checked="checked"';
} elsif ($option eq 'autolimit') {
if ($curroption =~ /^autolimit/) {
$checked = ' checked="checked"';
}
}
$cell{$item} .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="crsreq_'.$item.
'_'.$type.'" value="'.$val.'"'.$checked.' />'.
$titles{$option}.'</label>';
if ($option eq 'autolimit') {
$cell{$item} .= ' <input type="text" name="crsreq_'.
$item.'_limit_'.$type.'" size="1" '.
'value="'.$currlimit.'" />';
}
$cell{$item} .= '</span> ';
if ($option eq 'autolimit') {
$cell{$item} .= $titles{'unlimited'};
}
}
} elsif ($context eq 'requestauthor') {
my $curroption;
if (ref($settings) eq 'HASH') {
$curroption = $settings->{$type};
}
if (!$curroption) {
$curroption = 'norequest';
}
foreach my $option (@options) {
my $val = $option;
if ($option eq 'norequest') {
$val = 0;
}
my $checked = '';
if ($option eq $curroption) {
$checked = ' checked="checked"';
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="authorreq_'.$type.
'" value="'.$val.'"'.$checked.' />'.
$titles{$option}.'</label></span> ';
}
} else {
my $checked = 'checked="checked" ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
if ($settings->{$item}->{$type} == 0) {
$checked = '';
} elsif ($settings->{$item}->{$type} == 1) {
$checked = 'checked="checked" ';
}
}
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$context.'_'.$item.
'" value="'.$type.'" '.$checked.'/>'.$titles{$item}.
'</label></span> ';
}
}
if ($context eq 'requestcourses') {
$datatable .= '</tr><tr>';
foreach my $item (@usertools) {
$datatable .= '<td style="vertical-align: top">'.$cell{$item}.'</td>';
}
$datatable .= '</tr></table>';
}
$datatable .= '</td>';
unless (($context eq 'requestcourses') ||
($context eq 'requestauthor')) {
$datatable .=
'<td class="LC_right_item">'.
'<span class="LC_nobreak">'.&mt('Portfolio').': '.
'<input type="text" name="quota_'.$type.
'" value="'.$currdefquota.
'" size="5" /></span>'.(' ' x 2).
'<span class="LC_nobreak">'.&mt('Authoring').': '.
'<input type="text" name="authorquota_'.$type.
'" value="'.$currauthorquota.
'" size="5" /></span></td>';
}
$datatable .= '</tr>';
}
}
}
unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
$defaultquota = '20';
$authorquota = '500';
if (ref($settings) eq 'HASH') {
if (ref($settings->{'defaultquota'}) eq 'HASH') {
$defaultquota = $settings->{'defaultquota'}->{'default'};
} elsif (defined($settings->{'default'})) {
$defaultquota = $settings->{'default'};
}
if (ref($settings->{'authorquota'}) eq 'HASH') {
$authorquota = $settings->{'authorquota'}->{'default'};
}
}
}
$typecount ++;
$css_class = $typecount%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td>'.$othertitle.'</td>'.
'<td class="LC_left_item">';
if ($context eq 'requestcourses') {
$datatable .= '<table><tr>';
}
my %defcell;
foreach my $item (@usertools) {
if ($context eq 'requestcourses') {
my ($curroption,$currlimit);
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
$curroption = $settings->{$item}->{'default'};
if ($curroption =~ /^autolimit=(\d*)$/) {
$currlimit = $1;
}
}
}
if (!$curroption) {
$curroption = 'norequest';
}
$datatable .= '<th>'.$titles{$item}.'</th>';
foreach my $option (@options) {
my $val = $option;
if ($option eq 'norequest') {
$val = 0;
}
if ($option eq 'validate') {
my $canvalidate = 0;
if (ref($validations{$item}) eq 'HASH') {
if ($validations{$item}{'default'}) {
$canvalidate = 1;
}
}
next if (!$canvalidate);
}
my $checked = '';
if ($option eq $curroption) {
$checked = ' checked="checked"';
} elsif ($option eq 'autolimit') {
if ($curroption =~ /^autolimit/) {
$checked = ' checked="checked"';
}
}
$defcell{$item} .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="crsreq_'.$item.
'_default" value="'.$val.'"'.$checked.' />'.
$titles{$option}.'</label>';
if ($option eq 'autolimit') {
$defcell{$item} .= ' <input type="text" name="crsreq_'.
$item.'_limit_default" size="1" '.
'value="'.$currlimit.'" />';
}
$defcell{$item} .= '</span> ';
if ($option eq 'autolimit') {
$defcell{$item} .= $titles{'unlimited'};
}
}
} elsif ($context eq 'requestauthor') {
my $curroption;
if (ref($settings) eq 'HASH') {
$curroption = $settings->{'default'};
}
if (!$curroption) {
$curroption = 'norequest';
}
foreach my $option (@options) {
my $val = $option;
if ($option eq 'norequest') {
$val = 0;
}
my $checked = '';
if ($option eq $curroption) {
$checked = ' checked="checked"';
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="authorreq_default"'.
' value="'.$val.'"'.$checked.' />'.
$titles{$option}.'</label></span> ';
}
} else {
my $checked = 'checked="checked" ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
if ($settings->{$item}->{'default'} == 0) {
$checked = '';
} elsif ($settings->{$item}->{'default'} == 1) {
$checked = 'checked="checked" ';
}
}
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$context.'_'.$item.
'" value="default" '.$checked.'/>'.$titles{$item}.
'</label></span> ';
}
}
if ($context eq 'requestcourses') {
$datatable .= '</tr><tr>';
foreach my $item (@usertools) {
$datatable .= '<td style="vertical-align: top">'.$defcell{$item}.'</td>';
}
$datatable .= '</tr></table>';
}
$datatable .= '</td>';
unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
$datatable .= '<td class="LC_right_item">'.
'<span class="LC_nobreak">'.&mt('Portfolio').': '.
'<input type="text" name="defaultquota" value="'.
$defaultquota.'" size="5" /></span>'.(' ' x2).
'<span class="LC_nobreak">'.&mt('Authoring').': '.
'<input type="text" name="authorquota" value="'.
$authorquota.'" size="5" /></span></td>';
}
$datatable .= '</tr>';
$typecount ++;
$css_class = $typecount%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td>'.&mt('LON-CAPA Advanced Users').'<br />';
if ($context eq 'requestcourses') {
$datatable .= &mt('(overrides affiliation, if set)').
'</td>'.
'<td class="LC_left_item">'.
'<table><tr>';
} else {
$datatable .= &mt('(overrides affiliation, if checked)').
'</td>'.
'<td class="LC_left_item" colspan="2">'.
'<br />';
}
my %advcell;
foreach my $item (@usertools) {
if ($context eq 'requestcourses') {
my ($curroption,$currlimit);
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
$curroption = $settings->{$item}->{'_LC_adv'};
if ($curroption =~ /^autolimit=(\d*)$/) {
$currlimit = $1;
}
}
}
$datatable .= '<th>'.$titles{$item}.'</th>';
my $checked = '';
if ($curroption eq '') {
$checked = ' checked="checked"';
}
$advcell{$item} .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="crsreq_'.$item.
'__LC_adv" value=""'.$checked.' />'.
&mt('No override set').'</label></span> ';
foreach my $option (@options) {
my $val = $option;
if ($option eq 'norequest') {
$val = 0;
}
if ($option eq 'validate') {
my $canvalidate = 0;
if (ref($validations{$item}) eq 'HASH') {
if ($validations{$item}{'_LC_adv'}) {
$canvalidate = 1;
}
}
next if (!$canvalidate);
}
my $checked = '';
if ($val eq $curroption) {
$checked = ' checked="checked"';
} elsif ($option eq 'autolimit') {
if ($curroption =~ /^autolimit/) {
$checked = ' checked="checked"';
}
}
$advcell{$item} .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="crsreq_'.$item.
'__LC_adv" value="'.$val.'"'.$checked.' />'.
$titles{$option}.'</label>';
if ($option eq 'autolimit') {
$advcell{$item} .= ' <input type="text" name="crsreq_'.
$item.'_limit__LC_adv" size="1" '.
'value="'.$currlimit.'" />';
}
$advcell{$item} .= '</span> ';
if ($option eq 'autolimit') {
$advcell{$item} .= $titles{'unlimited'};
}
}
} elsif ($context eq 'requestauthor') {
my $curroption;
if (ref($settings) eq 'HASH') {
$curroption = $settings->{'_LC_adv'};
}
my $checked = '';
if ($curroption eq '') {
$checked = ' checked="checked"';
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="authorreq__LC_adv"'.
' value=""'.$checked.' />'.
&mt('No override set').'</label></span> ';
foreach my $option (@options) {
my $val = $option;
if ($option eq 'norequest') {
$val = 0;
}
my $checked = '';
if ($val eq $curroption) {
$checked = ' checked="checked"';
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="authorreq__LC_adv"'.
' value="'.$val.'"'.$checked.' />'.
$titles{$option}.'</label></span> ';
}
} else {
my $checked = 'checked="checked" ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
if ($settings->{$item}->{'_LC_adv'} == 0) {
$checked = '';
} elsif ($settings->{$item}->{'_LC_adv'} == 1) {
$checked = 'checked="checked" ';
}
}
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$context.'_'.$item.
'" value="_LC_adv" '.$checked.'/>'.$titles{$item}.
'</label></span> ';
}
}
if ($context eq 'requestcourses') {
$datatable .= '</tr><tr>';
foreach my $item (@usertools) {
$datatable .= '<td style="vertical-align: top">'.$advcell{$item}.'</td>';
}
$datatable .= '</tr></table>';
}
$datatable .= '</td></tr>';
$$rowtotal += $typecount;
return $datatable;
}
sub print_requestmail {
my ($dom,$action,$settings,$rowtotal) = @_;
my ($now,$datatable,%currapp);
$now = time;
if (ref($settings) eq 'HASH') {
if (ref($settings->{'notify'}) eq 'HASH') {
if ($settings->{'notify'}{'approval'} ne '') {
map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'});
}
}
}
my $numinrow = 2;
my $css_class;
$css_class = ($$rowtotal%2? ' class="LC_odd_row"':'');
my $text;
if ($action eq 'requestcourses') {
$text = &mt('Receive notification of course requests requiring approval');
} elsif ($action eq 'requestauthor') {
$text = &mt('Receive notification of Authoring Space requests requiring approval');
} else {
$text = &mt('Receive notification of queued requests for self-created user accounts requiring approval');
}
$datatable = '<tr'.$css_class.'>'.
' <td>'.$text.'</td>'.
' <td class="LC_left_item">';
my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',
$action.'notifyapproval',%currapp);
if ($numdc > 0) {
$datatable .= $table;
} else {
$datatable .= &mt('There are no active Domain Coordinators');
}
$datatable .='</td></tr>';
$$rowtotal += $rows;
return $datatable;
}
sub print_studentcode {
my ($settings,$rowtotal) = @_;
my $rownum = 0;
my ($output,%current);
my @crstypes = ('official','unofficial','community','textbook');
if (ref($settings->{'uniquecode'}) eq 'HASH') {
foreach my $type (@crstypes) {
$current{$type} = $settings->{'uniquecode'}{$type};
}
}
$output .= '<tr>'.
'<td class="LC_left_item">'.&mt('Generate unique six character code as course identifier?').'</td>'.
'<td class="LC_left_item">';
foreach my $type (@crstypes) {
my $check = ' ';
if ($current{$type}) {
$check = ' checked="checked" ';
}
$output .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="uniquecode" value="'.$type.'"'.$check.'/>'.
&mt($type).'</label></span>'.(' 'x2).' ';
}
$output .= '</td></tr>';
$$rowtotal ++;
return $output;
}
sub print_textbookcourses {
my ($dom,$settings,$rowtotal) = @_;
my $rownum = 0;
my $css_class;
my $itemcount = 1;
my $maxnum = 0;
my $bookshash;
if (ref($settings) eq 'HASH') {
$bookshash = $settings->{'textbooks'};
}
my %ordered;
if (ref($bookshash) eq 'HASH') {
foreach my $item (keys(%{$bookshash})) {
if (ref($bookshash->{$item}) eq 'HASH') {
my $num = $bookshash->{$item}{'order'};
$ordered{$num} = $item;
}
}
}
my $confname = $dom.'-domainconfig';
my $switchserver = &check_switchserver($dom,$confname);
my $maxnum = scalar(keys(%ordered));
my $datatable = &textbookcourses_javascript(\%ordered);
if (keys(%ordered)) {
my @items = sort { $a <=> $b } keys(%ordered);
for (my $i=0; $i<@items; $i++) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $key = $ordered{$items[$i]};
my %coursehash=&Apache::lonnet::coursedescription($key);
my $coursetitle = $coursehash{'description'};
my ($subject,$title,$author,$image,$imgsrc,$cdom,$cnum);
if (ref($bookshash->{$key}) eq 'HASH') {
$subject = $bookshash->{$key}->{'subject'};
$title = $bookshash->{$key}->{'title'};
$author = $bookshash->{$key}->{'author'};
$image = $bookshash->{$key}->{'image'};
if ($image ne '') {
my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$});
my $imagethumb = "$path/tn-".$imagefile;
$imgsrc = '<img src="'.$imagethumb.'" alt="'.&mt('Textbook image').'" />';
}
}
my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$key'".');"';
$datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
.'<select name="'.$key.'"'.$chgstr.'>';
for (my $k=0; $k<=$maxnum; $k++) {
my $vpos = $k+1;
my $selstr;
if ($k == $i) {
$selstr = ' selected="selected" ';
}
$datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
}
$datatable .= '</select>'.(' 'x2).
'<label><input type="checkbox" name="book_del" value="'.$key.'" />'.
&mt('Delete?').'</label></span></td>'.
'<td colspan="2">'.
'<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="book_subject_'.$i.'" value="'.$subject.'" /></span> '.
(' 'x2).
'<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="book_title_'.$i.'" value="'.$title.'" /></span> '.
(' 'x2).
'<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="book_author_'.$i.'" value="'.$author.'" /></span> '.
(' 'x2).
'<span class="LC_nobreak">'.&mt('Thumbnail:');
if ($image) {
$datatable .= '<span class="LC_nobreak">'.
$imgsrc.
'<label><input type="checkbox" name="book_image_del"'.
' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.
'<span class="LC_nobreak"> '.&mt('Replace:').' ';
}
if ($switchserver) {
$datatable .= &mt('Upload to library server: [_1]',$switchserver);
} else {
$datatable .= '<input type="file" name="book_image_'.$i.'" value="" />';
}
$datatable .= '<input type="hidden" name="book_id_'.$i.'" value="'.$key.'" /></span> '.
'<span class="LC_nobreak">'.&mt('LON-CAPA course:').' '.
$coursetitle.'</span></td></tr>'."\n";
$itemcount ++;
}
}
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'addbook_pos'".');"';
$datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
'<input type="hidden" name="book_maxnum" value="'.$maxnum.'" />'."\n".
'<select name="addbook_pos"'.$chgstr.'>';
for (my $k=0; $k<$maxnum+1; $k++) {
my $vpos = $k+1;
my $selstr;
if ($k == $maxnum) {
$selstr = ' selected="selected" ';
}
$datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
}
$datatable .= '</select> '."\n".
'<input type="checkbox" name="addbook" value="1" />'.&mt('Add').'</td>'."\n".
'<td colspan="2">'.
'<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="addbook_subject" value="" /></span> '."\n".
(' 'x2).
'<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="addbook_title" value="" /></span> '."\n".
(' 'x2).
'<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="addbook_author" value="" /></span> '."\n".
(' 'x2).
'<span class="LC_nobreak">'.&mt('Image:').' ';
if ($switchserver) {
$datatable .= &mt('Upload to library server: [_1]',$switchserver);
} else {
$datatable .= '<input type="file" name="addbook_image" value="" />';
}
$datatable .= '</span>'."\n".
'<span class="LC_nobreak">'.&mt('LON-CAPA course:').' '.
&Apache::loncommon::select_dom_form($env{'request.role.domain'},'addbook_cdom').
'<input type="text" size="25" name="addbook_cnum" value="" />'.
&Apache::loncommon::selectcourse_link
('display','addbook_cnum','addbook_cdom',undef,undef,undef,'Course');
'</span></td>'."\n".
'</tr>'."\n";
$itemcount ++;
return $datatable;
}
sub textbookcourses_javascript {
my ($textbooks) = @_;
return unless(ref($textbooks) eq 'HASH');
my $num = scalar(keys(%{$textbooks}));
my @jsarray;
foreach my $item (sort {$a <=> $b } (keys(%{$textbooks}))) {
push(@jsarray,$textbooks->{$item});
}
my $jstext = ' var textbooks = Array('."'".join("','",@jsarray)."'".');'."\n";
return <<"ENDSCRIPT";
<script type="text/javascript">
// <![CDATA[
function reorderBooks(form,item) {
var changedVal;
$jstext
var newpos = 'addbook_pos';
var current = new Array;
var maxh = 1 + $num;
var current = new Array;
var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
if (item == newpos) {
changedVal = newitemVal;
} else {
changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
current[newitemVal] = newpos;
}
for (var i=0; i<textbooks.length; i++) {
var elementName = textbooks[i];
if (elementName != item) {
if (form.elements[elementName]) {
var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
current[currVal] = elementName;
}
}
}
var oldVal;
for (var j=0; j<maxh; j++) {
if (current[j] == undefined) {
oldVal = j;
}
}
if (oldVal < changedVal) {
for (var k=oldVal+1; k<=changedVal ; k++) {
var elementName = current[k];
form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
}
} else {
for (var k=changedVal; k<oldVal; k++) {
var elementName = current[k];
form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
}
}
return;
}
// ]]>
</script>
ENDSCRIPT
}
sub print_autoenroll {
my ($dom,$settings,$rowtotal) = @_;
my $autorun = &Apache::lonnet::auto_run(undef,$dom),
my ($defdom,$runon,$runoff,$coownerson,$coownersoff);
if (ref($settings) eq 'HASH') {
if (exists($settings->{'run'})) {
if ($settings->{'run'} eq '0') {
$runoff = ' checked="checked" ';
$runon = ' ';
} else {
$runon = ' checked="checked" ';
$runoff = ' ';
}
} else {
if ($autorun) {
$runon = ' checked="checked" ';
$runoff = ' ';
} else {
$runoff = ' checked="checked" ';
$runon = ' ';
}
}
if (exists($settings->{'co-owners'})) {
if ($settings->{'co-owners'} eq '0') {
$coownersoff = ' checked="checked" ';
$coownerson = ' ';
} else {
$coownerson = ' checked="checked" ';
$coownersoff = ' ';
}
} else {
$coownersoff = ' checked="checked" ';
$coownerson = ' ';
}
if (exists($settings->{'sender_domain'})) {
$defdom = $settings->{'sender_domain'};
}
} else {
if ($autorun) {
$runon = ' checked="checked" ';
$runoff = ' ';
} else {
$runoff = ' checked="checked" ';
$runon = ' ';
}
}
my $domform = &Apache::loncommon::select_dom_form($defdom,'sender_domain',1);
my $notif_sender;
if (ref($settings) eq 'HASH') {
$notif_sender = $settings->{'sender_uname'};
}
my $datatable='<tr class="LC_odd_row">'.
'<td>'.&mt('Auto-enrollment active?').'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="autoenroll_run"'.
$runon.' value="1" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="autoenroll_run"'.
$runoff.' value="0" />'.&mt('No').'</label></span></td>'.
'</tr><tr>'.
'<td>'.&mt('Notification messages - sender').
'</td><td class="LC_right_item"><span class="LC_nobreak">'.
&mt('username').': '.
'<input type="text" name="sender_uname" value="'.
$notif_sender.'" size="10" /> '.&mt('domain').
': '.$domform.'</span></td></tr>'.
'<tr class="LC_odd_row">'.
'<td>'.&mt('Automatically assign co-ownership').'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="autoassign_coowners"'.
$coownerson.' value="1" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="autoassign_coowners"'.
$coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
'</tr>';
$$rowtotal += 3;
return $datatable;
}
sub print_autoupdate {
my ($position,$dom,$settings,$rowtotal) = @_;
my $datatable;
if ($position eq 'top') {
my $updateon = ' ';
my $updateoff = ' checked="checked" ';
my $classlistson = ' ';
my $classlistsoff = ' checked="checked" ';
if (ref($settings) eq 'HASH') {
if ($settings->{'run'} eq '1') {
$updateon = $updateoff;
$updateoff = ' ';
}
if ($settings->{'classlists'} eq '1') {
$classlistson = $classlistsoff;
$classlistsoff = ' ';
}
}
my %title = (
run => 'Auto-update active?',
classlists => 'Update information in classlists?',
);
$datatable = '<tr class="LC_odd_row">'.
'<td>'.&mt($title{'run'}).'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="autoupdate_run"'.
$updateon.' value="1" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="autoupdate_run"'.
$updateoff.'value="0" />'.&mt('No').'</label></span></td>'.
'</tr><tr>'.
'<td>'.&mt($title{'classlists'}).'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak">'.
'<label><input type="radio" name="classlists"'.
$classlistson.' value="1" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="classlists"'.
$classlistsoff.'value="0" />'.&mt('No').'</label></span></td>'.
'</tr>';
$$rowtotal += 2;
} elsif ($position eq 'middle') {
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
my $numinrow = 3;
my $locknamesettings;
$datatable .= &insttypes_row($settings,$types,$usertypes,
$dom,$numinrow,$othertitle,
'lockablenames');
$$rowtotal ++;
} else {
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
my @fields = ('lastname','firstname','middlename','generation',
'permanentemail','id');
my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
my $numrows = 0;
if (ref($types) eq 'ARRAY') {
if (@{$types} > 0) {
$datatable =
&usertype_update_row($settings,$usertypes,\%fieldtitles,
\@fields,$types,\$numrows);
$$rowtotal += @{$types};
}
}
$datatable .=
&usertype_update_row($settings,{'default' => $othertitle},
\%fieldtitles,\@fields,['default'],
\$numrows);
$$rowtotal ++;
}
return $datatable;
}
sub print_autocreate {
my ($dom,$settings,$rowtotal) = @_;
my (%createon,%createoff,%currhash);
my @types = ('xml','req');
if (ref($settings) eq 'HASH') {
foreach my $item (@types) {
$createoff{$item} = ' checked="checked" ';
$createon{$item} = ' ';
if (exists($settings->{$item})) {
if ($settings->{$item}) {
$createon{$item} = ' checked="checked" ';
$createoff{$item} = ' ';
}
}
}
if ($settings->{'xmldc'} ne '') {
$currhash{$settings->{'xmldc'}} = 1;
}
} else {
foreach my $item (@types) {
$createoff{$item} = ' checked="checked" ';
$createon{$item} = ' ';
}
}
$$rowtotal += 2;
my $numinrow = 2;
my $datatable='<tr class="LC_odd_row">'.
'<td>'.&mt('Create pending official courses from XML files').'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="autocreate_xml"'.
$createon{'xml'}.' value="1" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="autocreate_xml"'.
$createoff{'xml'}.' value="0" />'.&mt('No').'</label></span>'.
'</td></tr><tr>'.
'<td>'.&mt('Create pending requests for official courses (if validated)').'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="autocreate_req"'.
$createon{'req'}.' value="1" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="autocreate_req"'.
$createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';
my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
'autocreate_xmldc',%currhash);
if ($numdc > 1) {
$datatable .= '</td></tr><tr class="LC_odd_row"><td>'.
&mt('Course creation processed as: (choose Dom. Coord.)').
'</td><td class="LC_left_item">'.$dctable.'</td></tr>';
} else {
$datatable .= $dctable.'</td></tr>';
}
$$rowtotal += $rows;
return $datatable;
}
sub print_directorysrch {
my ($dom,$settings,$rowtotal) = @_;
my $srchon = ' ';
my $srchoff = ' checked="checked" ';
my ($exacton,$containson,$beginson);
my $localon = ' ';
my $localoff = ' checked="checked" ';
if (ref($settings) eq 'HASH') {
if ($settings->{'available'} eq '1') {
$srchon = $srchoff;
$srchoff = ' ';
}
if ($settings->{'localonly'} eq '1') {
$localon = $localoff;
$localoff = ' ';
}
if (ref($settings->{'searchtypes'}) eq 'ARRAY') {
foreach my $type (@{$settings->{'searchtypes'}}) {
if ($type eq 'exact') {
$exacton = ' checked="checked" ';
} elsif ($type eq 'contains') {
$containson = ' checked="checked" ';
} elsif ($type eq 'begins') {
$beginson = ' checked="checked" ';
}
}
} else {
if ($settings->{'searchtypes'} eq 'exact') {
$exacton = ' checked="checked" ';
} elsif ($settings->{'searchtypes'} eq 'contains') {
$containson = ' checked="checked" ';
} elsif ($settings->{'searchtypes'} eq 'specify') {
$exacton = ' checked="checked" ';
$containson = ' checked="checked" ';
}
}
}
my ($searchtitles,$titleorder) = &sorted_searchtitles();
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
my $numinrow = 4;
my $cansrchrow = 0;
my $datatable='<tr class="LC_odd_row">'.
'<td colspan="2"><span class ="LC_nobreak">'.&mt('Directory search available?').'</span></td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="dirsrch_available"'.
$srchon.' value="1" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="dirsrch_available"'.
$srchoff.' value="0" />'.&mt('No').'</label></span></td>'.
'</tr><tr>'.
'<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search?').'</span></td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="dirsrch_localonly"'.
$localoff.' value="0" />'.&mt('Yes').'</label> '.
'<label><input type="radio" name="dirsrch_localonly"'.
$localon.' value="1" />'.&mt('No').'</label></span></td>'.
'</tr>';
$$rowtotal += 2;
if (ref($usertypes) eq 'HASH') {
if (keys(%{$usertypes}) > 0) {
$datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
$numinrow,$othertitle,'cansearch');
$cansrchrow = 1;
}
}
if ($cansrchrow) {
$$rowtotal ++;
$datatable .= '<tr>';
} else {
$datatable .= '<tr class="LC_odd_row">';
}
$datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').
'</span></td><td class="LC_left_item" colspan="2"><table><tr>';
foreach my $title (@{$titleorder}) {
if (defined($searchtitles->{$title})) {
my $check = ' ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{'searchby'}) eq 'ARRAY') {
if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {
$check = ' checked="checked" ';
}
}
}
$datatable .= '<td class="LC_left_item">'.
'<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="searchby" '.
'value="'.$title.'"'.$check.'/>'.
$searchtitles->{$title}.'</label></span></td>';
}
}
$datatable .= '</tr></table></td></tr>';
$$rowtotal ++;
if ($cansrchrow) {
$datatable .= '<tr class="LC_odd_row">';
} else {
$datatable .= '<tr>';
}
$datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.
'<td class="LC_left_item" colspan="2">'.
'<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="searchtypes" '.
$exacton.' value="exact" />'.&mt('Exact match').
'</label> '.
'<label><input type="checkbox" name="searchtypes" '.
$beginson.' value="begins" />'.&mt('Begins with').
'</label> '.
'<label><input type="checkbox" name="searchtypes" '.
$containson.' value="contains" />'.&mt('Contains').
'</label></span></td></tr>';
$$rowtotal ++;
return $datatable;
}
sub print_contacts {
my ($dom,$settings,$rowtotal) = @_;
my $datatable;
my @contacts = ('adminemail','supportemail');
my (%checked,%to,%otheremails,%bccemails);
my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail',
'requestsmail','updatesmail','idconflictsmail');
foreach my $type (@mailings) {
$otheremails{$type} = '';
}
$bccemails{'helpdeskmail'} = '';
if (ref($settings) eq 'HASH') {
foreach my $item (@contacts) {
if (exists($settings->{$item})) {
$to{$item} = $settings->{$item};
}
}
foreach my $type (@mailings) {
if (exists($settings->{$type})) {
if (ref($settings->{$type}) eq 'HASH') {
foreach my $item (@contacts) {
if ($settings->{$type}{$item}) {
$checked{$type}{$item} = ' checked="checked" ';
}
}
$otheremails{$type} = $settings->{$type}{'others'};
if ($type eq 'helpdeskmail') {
$bccemails{$type} = $settings->{$type}{'bcc'};
}
}
} elsif ($type eq 'lonstatusmail') {
$checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
}
}
} else {
$to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
$to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
$checked{'errormail'}{'adminemail'} = ' checked="checked" ';
$checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';
$checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
$checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
$checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
$checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';
$checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';
}
my ($titles,$short_titles) = &contact_titles();
my $rownum = 0;
my $css_class;
foreach my $item (@contacts) {
$css_class = $rownum%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td><span class="LC_nobreak">'.$titles->{$item}.
'</span></td><td class="LC_right_item">'.
'<input type="text" name="'.$item.'" value="'.
$to{$item}.'" /></td></tr>';
$rownum ++;
}
foreach my $type (@mailings) {
$css_class = $rownum%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td><span class="LC_nobreak">'.
$titles->{$type}.': </span></td>'.
'<td class="LC_left_item">'.
'<span class="LC_nobreak">';
foreach my $item (@contacts) {
$datatable .= '<label>'.
'<input type="checkbox" name="'.$type.'"'.
$checked{$type}{$item}.
' value="'.$item.'" />'.$short_titles->{$item}.
'</label> ';
}
$datatable .= '</span><br />'.&mt('Others').': '.
'<input type="text" name="'.$type.'_others" '.
'value="'.$otheremails{$type}.'" />';
if ($type eq 'helpdeskmail') {
$datatable .= '<br />'.&mt('Bcc:').(' 'x6).
'<input type="text" name="'.$type.'_bcc" '.
'value="'.$bccemails{$type}.'" />';
}
$datatable .= '</td></tr>'."\n";
$rownum ++;
}
my %choices;
$choices{'reporterrors'} = &mt('E-mail error reports to [_1]',
&Apache::loncommon::modal_link('http://loncapa.org/core.html',
&mt('LON-CAPA core group - MSU'),600,500));
$choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',
&Apache::loncommon::modal_link('http://loncapa.org/core.html',
&mt('LON-CAPA core group - MSU'),600,500));
my @toggles = ('reporterrors','reportupdates');
my %defaultchecked = ('reporterrors' => 'on',
'reportupdates' => 'on');
(my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
\%choices,$rownum);
$datatable .= $reports;
$$rowtotal += $rownum;
return $datatable;
}
sub print_helpsettings {
my ($dom,$confname,$settings,$rowtotal) = @_;
my ($datatable,$itemcount);
$itemcount = 1;
my (%choices,%defaultchecked,@toggles);
$choices{'submitbugs'} = &mt('Display link to: [_1]?',
&Apache::loncommon::modal_link('http://bugs.loncapa.org',
&mt('LON-CAPA bug tracker'),600,500));
%defaultchecked = ('submitbugs' => 'on');
@toggles = ('submitbugs',);
($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
\%choices,$itemcount);
return $datatable;
}
sub radiobutton_prefs {
my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick,
$additional) = @_;
return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&
(ref($choices) eq 'HASH'));
my (%checkedon,%checkedoff,$datatable,$css_class);
foreach my $item (@{$toggles}) {
if ($defaultchecked->{$item} eq 'on') {
$checkedon{$item} = ' checked="checked" ';
$checkedoff{$item} = ' ';
} elsif ($defaultchecked->{$item} eq 'off') {
$checkedoff{$item} = ' checked="checked" ';
$checkedon{$item} = ' ';
}
}
if (ref($settings) eq 'HASH') {
foreach my $item (@{$toggles}) {
if ($settings->{$item} eq '1') {
$checkedon{$item} = ' checked="checked" ';
$checkedoff{$item} = ' ';
} elsif ($settings->{$item} eq '0') {
$checkedoff{$item} = ' checked="checked" ';
$checkedon{$item} = ' ';
}
}
}
if ($onclick) {
$onclick = ' onclick="'.$onclick.'"';
}
foreach my $item (@{$toggles}) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .=
'<tr'.$css_class.'><td valign="top">'.
'<span class="LC_nobreak">'.$choices->{$item}.
'</span></td>'.
'<td class="LC_right_item"><span class="LC_nobreak">'.
'<label><input type="radio" name="'.
$item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').
'</label> <label><input type="radio" name="'.$item.'" '.
$checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>'.
'</span>'.$additional.
'</td>'.
'</tr>';
$itemcount ++;
}
return ($datatable,$itemcount);
}
sub print_coursedefaults {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
my $itemcount = 1;
my %choices = &Apache::lonlocal::texthash (
canuse_pdfforms => 'Course/Community users can create/upload PDF forms',
uploadquota => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',
anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
coursecredits => 'Credits can be specified for courses',
);
my %staticdefaults = (
anonsurvey_threshold => 10,
uploadquota => 500,
);
if ($position eq 'top') {
%defaultchecked = ('canuse_pdfforms' => 'off');
@toggles = ('canuse_pdfforms');
($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
\%choices,$itemcount);
} else {
$css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
my ($currdefresponder,$def_official_credits,$def_unofficial_credits,$def_textbook_credits,
%curruploadquota);
my $currusecredits = 0;
my @types = ('official','unofficial','community','textbook');
if (ref($settings) eq 'HASH') {
$currdefresponder = $settings->{'anonsurvey_threshold'};
if (ref($settings->{'uploadquota'}) eq 'HASH') {
foreach my $type (keys(%{$settings->{'uploadquota'}})) {
$curruploadquota{$type} = $settings->{'uploadquota'}{$type};
}
}
if (ref($settings->{'coursecredits'}) eq 'HASH') {
$def_official_credits = $settings->{'coursecredits'}->{'official'};
$def_unofficial_credits = $settings->{'coursecredits'}->{'unofficial'};
$def_textbook_credits = $settings->{'coursecredits'}->{'textbook'};
if (($def_official_credits ne '') || ($def_unofficial_credits ne '') ||
($def_textbook_credits ne '')) {
$currusecredits = 1;
}
}
}
if (!$currdefresponder) {
$currdefresponder = $staticdefaults{'anonsurvey_threshold'};
} elsif ($currdefresponder < 1) {
$currdefresponder = 1;
}
foreach my $type (@types) {
if ($curruploadquota{$type} eq '') {
$curruploadquota{$type} = $staticdefaults{'uploadquota'};
}
}
$datatable .=
'<tr'.$css_class.'><td><span class="LC_nobreak">'.
$choices{'anonsurvey_threshold'}.
'</span></td>'.
'<td class="LC_right_item"><span class="LC_nobreak">'.
'<input type="text" name="anonsurvey_threshold"'.
' value="'.$currdefresponder.'" size="5" /></span>'.
'</td></tr>'."\n".
'<tr><td><span class="LC_nobreak">'.
$choices{'uploadquota'}.
'</span></td>'.
'<td align="right" class="LC_right_item">'.
'<table><tr>';
foreach my $type (@types) {
$datatable .= '<td align="center">'.&mt($type).'<br />'.
'<input type="text" name="uploadquota_'.$type.'"'.
' value="'.$curruploadquota{$type}.'" size="5" /></td>';
}
$datatable .= '</tr></table></td></tr>'."\n";
$itemcount += 2;
my $onclick = 'toggleCredits(this.form);';
my $display = 'none';
if ($currusecredits) {
$display = 'block';
}
my $additional = '<div id="credits" style="display: '.$display.'">'.
'<span class="LC_nobreak">'.
&mt('Default credits for official courses [_1]',
'<input type="text" name="official_credits" value="'.
$def_official_credits.'" size="3" />').
'</span><br />'.
'<span class="LC_nobreak">'.
&mt('Default credits for unofficial courses [_1]',
'<input type="text" name="unofficial_credits" value="'.
$def_unofficial_credits.'" size="3" />').
'</span><br />'.
'<span class="LC_nobreak">'.
&mt('Default credits for textbook courses [_1]',
'<input type="text" name="textbook_credits" value="'.
$def_textbook_credits.'" size="3" />').
'</span></div>'."\n";
%defaultchecked = ('coursecredits' => 'off');
@toggles = ('coursecredits');
my $current = {
'coursecredits' => $currusecredits,
};
(my $table,$itemcount) =
&radiobutton_prefs($current,\@toggles,\%defaultchecked,
\%choices,$itemcount,$onclick,$additional);
$datatable .= $table;
}
$$rowtotal += $itemcount;
return $datatable;
}
sub print_usersessions {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable,%checked,%choices);
my (%by_ip,%by_location,@intdoms);
&build_location_hashes(\@intdoms,\%by_ip,\%by_location);
my @alldoms = &Apache::lonnet::all_domains();
my %serverhomes = %Apache::lonnet::serverhomeIDs;
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %altids = &id_for_thisdom(%servers);
my $itemcount = 1;
if ($position eq 'top') {
if (keys(%serverhomes) > 1) {
my %spareid = ¤t_offloads_to($dom,$settings,\%servers);
$datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$rowtotal);
} else {
$datatable .= '<tr'.$css_class.'><td colspan="2">'.
&mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.');
}
} else {
if (keys(%by_location) == 0) {
$datatable .= '<tr'.$css_class.'><td colspan="2">'.
&mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.');
} else {
my %lt = &usersession_titles();
my $numinrow = 5;
my $prefix;
my @types;
if ($position eq 'bottom') {
$prefix = 'remote';
@types = ('version','excludedomain','includedomain');
} else {
$prefix = 'hosted';
@types = ('excludedomain','includedomain');
}
my (%current,%checkedon,%checkedoff);
my @lcversions = &Apache::lonnet::all_loncaparevs();
my @locations = sort(keys(%by_location));
foreach my $type (@types) {
$checkedon{$type} = '';
$checkedoff{$type} = ' checked="checked"';
}
if (ref($settings) eq 'HASH') {
if (ref($settings->{$prefix}) eq 'HASH') {
foreach my $key (keys(%{$settings->{$prefix}})) {
$current{$key} = $settings->{$prefix}{$key};
if ($key eq 'version') {
if ($current{$key} ne '') {
$checkedon{$key} = ' checked="checked"';
$checkedoff{$key} = '';
}
} elsif (ref($current{$key}) eq 'ARRAY') {
$checkedon{$key} = ' checked="checked"';
$checkedoff{$key} = '';
}
}
}
}
foreach my $type (@types) {
next if ($type ne 'version' && !@locations);
$css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
$datatable .= '<tr'.$css_class.'>
<td><span class="LC_nobreak">'.$lt{$type}.'</span><br />
<span class="LC_nobreak">
<label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>
<label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
if ($type eq 'version') {
my $selector = '<select name="'.$prefix.'_version">';
foreach my $version (@lcversions) {
my $selected = '';
if ($current{'version'} eq $version) {
$selected = ' selected="selected"';
}
$selector .= ' <option value="'.$version.'"'.
$selected.'>'.$version.'</option>';
}
$selector .= '</select> ';
$datatable .= &mt('remote server must be version: [_1] or later',$selector);
} else {
$datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
' />'.(' 'x2).
'<input type="button" value="'.&mt('uncheck all').'" '.
'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
"\n".
'</div><div><table>';
my $rem;
for (my $i=0; $i<@locations; $i++) {
my ($showloc,$value,$checkedtype);
if (ref($by_location{$locations[$i]}) eq 'ARRAY') {
my $ip = $by_location{$locations[$i]}->[0];
if (ref($by_ip{$ip}) eq 'ARRAY') {
$value = join(':',@{$by_ip{$ip}});
$showloc = join(', ',@{$by_ip{$ip}});
if (ref($current{$type}) eq 'ARRAY') {
foreach my $loc (@{$by_ip{$ip}}) {
if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
$checkedtype = ' checked="checked"';
last;
}
}
}
}
}
$rem = $i%($numinrow);
if ($rem == 0) {
if ($i > 0) {
$datatable .= '</tr>';
}
$datatable .= '<tr>';
}
$datatable .= '<td class="LC_left_item">'.
'<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$prefix.'_'.$type.
'" value="'.$value.'"'.$checkedtype.' />'.$showloc.
'</label></span></td>';
}
$rem = @locations%($numinrow);
my $colsleft = $numinrow - $rem;
if ($colsleft > 1 ) {
$datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
' </td>';
} elsif ($colsleft == 1) {
$datatable .= '<td class="LC_left_item"> </td>';
}
$datatable .= '</tr></table>';
}
$datatable .= '</td></tr>';
$itemcount ++;
}
}
}
$$rowtotal += $itemcount;
return $datatable;
}
sub build_location_hashes {
my ($intdoms,$by_ip,$by_location) = @_;
return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
(ref($by_location) eq 'HASH'));
my %iphost = &Apache::lonnet::get_iphost();
my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
if (ref($iphost{$primary_ip}) eq 'ARRAY') {
foreach my $id (@{$iphost{$primary_ip}}) {
my $intdom = &Apache::lonnet::internet_dom($id);
unless(grep(/^\Q$intdom\E$/,@{$intdoms})) {
push(@{$intdoms},$intdom);
}
}
}
foreach my $ip (keys(%iphost)) {
if (ref($iphost{$ip}) eq 'ARRAY') {
foreach my $id (@{$iphost{$ip}}) {
my $location = &Apache::lonnet::internet_dom($id);
if ($location) {
next if (grep(/^\Q$location\E$/,@{$intdoms}));
if (ref($by_ip->{$ip}) eq 'ARRAY') {
unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
push(@{$by_ip->{$ip}},$location);
}
} else {
$by_ip->{$ip} = [$location];
}
}
}
}
}
foreach my $ip (sort(keys(%{$by_ip}))) {
if (ref($by_ip->{$ip}) eq 'ARRAY') {
@{$by_ip->{$ip}} = sort(@{$by_ip->{$ip}});
my $first = $by_ip->{$ip}->[0];
if (ref($by_location->{$first}) eq 'ARRAY') {
unless (grep(/^\Q$ip\E$/,@{$by_location->{$first}})) {
push(@{$by_location->{$first}},$ip);
}
} else {
$by_location->{$first} = [$ip];
}
}
}
return;
}
sub current_offloads_to {
my ($dom,$settings,$servers) = @_;
my (%spareid,%otherdomconfigs);
if (ref($servers) eq 'HASH') {
foreach my $lonhost (sort(keys(%{$servers}))) {
my $gotspares;
if (ref($settings) eq 'HASH') {
if (ref($settings->{'spares'}) eq 'HASH') {
if (ref($settings->{'spares'}{$lonhost}) eq 'HASH') {
$spareid{$lonhost}{'primary'} = $settings->{'spares'}{$lonhost}{'primary'};
$spareid{$lonhost}{'default'} = $settings->{'spares'}{$lonhost}{'default'};
$gotspares = 1;
}
}
}
unless ($gotspares) {
my $gotspares;
my $serverhomeID =
&Apache::lonnet::get_server_homeID($servers->{$lonhost});
my $serverhomedom =
&Apache::lonnet::host_domain($serverhomeID);
if ($serverhomedom ne $dom) {
if (ref($otherdomconfigs{$serverhomedom} eq 'HASH')) {
if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') {
if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') {
$spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'};
$spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'};
$gotspares = 1;
}
}
} else {
$otherdomconfigs{$serverhomedom} =
&Apache::lonnet::get_dom('configuration',['usersessions'],$serverhomedom);
if (ref($otherdomconfigs{$serverhomedom}) eq 'HASH') {
if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') {
if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') {
if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{$lonhost}) eq 'HASH') {
$spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'};
$spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'};
$gotspares = 1;
}
}
}
}
}
}
}
unless ($gotspares) {
if ($lonhost eq $Apache::lonnet::perlvar{'lonHostID'}) {
$spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};
$spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};
} else {
my $server_hostname = &Apache::lonnet::hostname($lonhost);
my $server_homeID = &Apache::lonnet::get_server_homeID($server_hostname);
if ($server_homeID eq $Apache::lonnet::perlvar{'lonHostID'}) {
$spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};
$spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};
} else {
my %what = (
spareid => 1,
);
my ($result,$returnhash) =
&Apache::lonnet::get_remote_globals($lonhost,\%what);
if ($result eq 'ok') {
if (ref($returnhash) eq 'HASH') {
if (ref($returnhash->{'spareid'}) eq 'HASH') {
$spareid{$lonhost}{'primary'} = $returnhash->{'spareid'}->{'primary'};
$spareid{$lonhost}{'default'} = $returnhash->{'spareid'}->{'default'};
}
}
}
}
}
}
}
}
return %spareid;
}
sub spares_row {
my ($dom,$servers,$spareid,$serverhomes,$altids,$rowtotal) = @_;
my $css_class;
my $numinrow = 4;
my $itemcount = 1;
my $datatable;
my %typetitles = &sparestype_titles();
if ((ref($servers) eq 'HASH') && (ref($spareid) eq 'HASH') && (ref($altids) eq 'HASH')) {
foreach my $server (sort(keys(%{$servers}))) {
my $serverhome = &Apache::lonnet::get_server_homeID($servers->{$server});
my ($othercontrol,$serverdom);
if ($serverhome ne $server) {
$serverdom = &Apache::lonnet::host_domain($serverhome);
$othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
} else {
$serverdom = &Apache::lonnet::host_domain($server);
if ($serverdom ne $dom) {
$othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
}
}
next unless (ref($spareid->{$server}) eq 'HASH');
$css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
$datatable .= '<tr'.$css_class.'>
<td rowspan="2">
<span class="LC_nobreak">'.
&mt('[_1] when busy, offloads to:'
,'<b>'.$server.'</b>').
"\n";
my (%current,%canselect);
my @choices =
&possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
foreach my $type ('primary','default') {
if (ref($spareid->{$server}) eq 'HASH') {
if (ref($spareid->{$server}{$type}) eq 'ARRAY') {
my @spares = @{$spareid->{$server}{$type}};
if (@spares > 0) {
if ($othercontrol) {
$current{$type} = join(', ',@spares);
} else {
$current{$type} .= '<table>';
my $numspares = scalar(@spares);
for (my $i=0; $i<@spares; $i++) {
my $rem = $i%($numinrow);
if ($rem == 0) {
if ($i > 0) {
$current{$type} .= '</tr>';
}
$current{$type} .= '<tr>';
}
$current{$type} .= '<td><label><input type="checkbox" name="spare_'.$type.'_'.$server.'" id="spare_'.$type.'_'.$server.'_'.$i.'" checked="checked" value="'.$spareid->{$server}{$type}[$i].'" onclick="updateNewSpares(this.form,'."'$server'".');" /> '.
$spareid->{$server}{$type}[$i].
'</label></td>'."\n";
}
my $rem = @spares%($numinrow);
my $colsleft = $numinrow - $rem;
if ($colsleft > 1 ) {
$current{$type} .= '<td colspan="'.$colsleft.
'" class="LC_left_item">'.
' </td>';
} elsif ($colsleft == 1) {
$current{$type} .= '<td class="LC_left_item"> </td>'."\n";
}
$current{$type} .= '</tr></table>';
}
}
}
if ($current{$type} eq '') {
$current{$type} = &mt('None specified');
}
if ($othercontrol) {
if ($type eq 'primary') {
$canselect{$type} = $othercontrol;
}
} else {
$canselect{$type} =
&mt('Add new [_1]'.$type.'[_2]:','<i>','</i>').' '.
'<select name="newspare_'.$type.'_'.$server.'" '.
'id="newspare_'.$type.'_'.$server.'" onchange="checkNewSpares('."'$server','$type'".');">'."\n".
'<option value="" selected ="selected">'.&mt('Select').'</option>'."\n";
if (@choices > 0) {
foreach my $lonhost (@choices) {
$canselect{$type} .= '<option value="'.$lonhost.'">'.$lonhost.'</option>'."\n";
}
}
$canselect{$type} .= '</select>'."\n";
}
} else {
$current{$type} = &mt('Could not be determined');
if ($type eq 'primary') {
$canselect{$type} = $othercontrol;
}
}
if ($type eq 'default') {
$datatable .= '<tr'.$css_class.'>';
}
$datatable .= '<td><i>'.$typetitles{$type}.'</i></td>'."\n".
'<td>'.$current{$type}.'</td>'."\n".
'<td>'.$canselect{$type}.'</td></tr>'."\n";
}
$itemcount ++;
}
}
$$rowtotal += $itemcount;
return $datatable;
}
sub possible_newspares {
my ($server,$currspares,$serverhomes,$altids) = @_;
my $serverhostname = &Apache::lonnet::hostname($server);
my %excluded;
if ($serverhostname ne '') {
%excluded = (
$serverhostname => 1,
);
}
if (ref($currspares) eq 'HASH') {
foreach my $type (keys(%{$currspares})) {
if (ref($currspares->{$type}) eq 'ARRAY') {
if (@{$currspares->{$type}} > 0) {
foreach my $curr (@{$currspares->{$type}}) {
my $hostname = &Apache::lonnet::hostname($curr);
$excluded{$hostname} = 1;
}
}
}
}
}
my @choices;
if ((ref($serverhomes) eq 'HASH') && (ref($altids) eq 'HASH')) {
if (keys(%{$serverhomes}) > 1) {
foreach my $name (sort(keys(%{$serverhomes}))) {
unless ($excluded{$name}) {
if (exists($altids->{$serverhomes->{$name}})) {
push(@choices,$altids->{$serverhomes->{$name}});
} else {
push(@choices,$serverhomes->{$name});
}
}
}
}
}
return sort(@choices);
}
sub print_loadbalancing {
my ($dom,$settings,$rowtotal) = @_;
my $primary_id = &Apache::lonnet::domain($dom,'primary');
my $intdom = &Apache::lonnet::internet_dom($primary_id);
my $numinrow = 1;
my $datatable;
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my (%currbalancer,%currtargets,%currrules,%existing);
if (ref($settings) eq 'HASH') {
%existing = %{$settings};
}
if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
&get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
\%currtargets,\%currrules);
} else {
return;
}
my ($othertitle,$usertypes,$types) =
&Apache::loncommon::sorted_inst_types($dom);
my $rownum = 8;
if (ref($types) eq 'ARRAY') {
$rownum += scalar(@{$types});
}
my @css_class = ('LC_odd_row','LC_even_row');
my $balnum = 0;
my $islast;
my (@toshow,$disabledtext);
if (keys(%currbalancer) > 0) {
@toshow = sort(keys(%currbalancer));
if (scalar(@toshow) < scalar(keys(%servers)) + 1) {
push(@toshow,'');
}
} else {
@toshow = ('');
$disabledtext = &mt('No existing load balancer');
}
foreach my $lonhost (@toshow) {
if ($balnum == scalar(@toshow)-1) {
$islast = 1;
} else {
$islast = 0;
}
my $cssidx = $balnum%2;
my $targets_div_style = 'display: none';
my $disabled_div_style = 'display: block';
my $homedom_div_style = 'display: none';
$datatable .= '<tr class="'.$css_class[$cssidx].'">'.
'<td rowspan="'.$rownum.'" valign="top">'.
'<p>';
if ($lonhost eq '') {
$datatable .= '<span class="LC_nobreak">';
if (keys(%currbalancer) > 0) {
$datatable .= &mt('Add balancer:');
} else {
$datatable .= &mt('Enable balancer:');
}
$datatable .= ' '.
'<select name="loadbalancing_lonhost_'.$balnum.'"'.
' id="loadbalancing_lonhost_'.$balnum.'"'.
' onchange="toggleTargets('."'$balnum'".');">'."\n".
'<option value="" selected="selected">'.&mt('None').
'</option>'."\n";
foreach my $server (sort(keys(%servers))) {
next if ($currbalancer{$server});
$datatable .= '<option value="'.$server.'">'.$server.'</option>'."\n";
}
$datatable .=
'</select>'."\n".
'<input type="hidden" name="loadbalancing_prevlonhost_'.$balnum.'" id="loadbalancing_prevlonhost_'.$balnum.'" value="" /> </span>'."\n";
} else {
$datatable .= '<i>'.$lonhost.'</i><br /><span class="LC_nobreak">'.
'<label><input type="checkbox" name="loadbalancing_delete" value="'.$balnum.'" id="loadbalancing_delete_'.$balnum.'" onclick="javascript:balancerDeleteChange('."'$balnum'".');" /> '.
&mt('Stop balancing').'</label>'.
'<input type="hidden" name="loadbalancing_lonhost_'.$balnum.'" value="'.$lonhost.'" id="loadbalancing_lonhost_'.$balnum.'" /></span>';
$targets_div_style = 'display: block';
$disabled_div_style = 'display: none';
if ($dom eq &Apache::lonnet::host_domain($lonhost)) {
$homedom_div_style = 'display: block';
}
}
$datatable .= '</p></td><td rowspan="'.$rownum.'" valign="top">'.
'<div id="loadbalancing_disabled_'.$balnum.'" style="'.
$disabled_div_style.'">'.$disabledtext.'</div>'."\n".
'<div id="loadbalancing_targets_'.$balnum.'" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';
my ($numspares,@spares) = &count_servers($lonhost,%servers);
my @sparestypes = ('primary','default');
my %typetitles = &sparestype_titles();
foreach my $sparetype (@sparestypes) {
my $targettable;
for (my $i=0; $i<$numspares; $i++) {
my $checked;
if (ref($currtargets{$lonhost}) eq 'HASH') {
if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {
if (grep(/^\Q$spares[$i]\E$/,@{$currtargets{$lonhost}{$sparetype}})) {
$checked = ' checked="checked"';
}
}
}
my ($chkboxval,$disabled);
if (($lonhost ne '') && (exists($servers{$lonhost}))) {
$chkboxval = $spares[$i];
}
if (exists($currbalancer{$spares[$i]})) {
$disabled = ' disabled="disabled"';
}
$targettable .=
'<td><label><input type="checkbox" name="loadbalancing_target_'.$balnum.'_'.$sparetype.'"'.
$checked.$disabled.' value="'.$chkboxval.'" id="loadbalancing_target_'.$balnum.'_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$balnum','$sparetype'".');" /><span id="loadbalancing_targettxt_'.$balnum.'_'.$sparetype.'_'.$i.'"> '.$chkboxval.
'</span></label></td>';
my $rem = $i%($numinrow);
if ($rem == 0) {
if (($i > 0) && ($i < $numspares-1)) {
$targettable .= '</tr>';
}
if ($i < $numspares-1) {
$targettable .= '<tr>';
}
}
}
if ($targettable ne '') {
my $rem = $numspares%($numinrow);
my $colsleft = $numinrow - $rem;
if ($colsleft > 1 ) {
$targettable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
' </td>';
} elsif ($colsleft == 1) {
$targettable .= '<td class="LC_left_item"> </td>';
}
$datatable .= '<i>'.$typetitles{$sparetype}.'</i><br />'.
'<table><tr>'.$targettable.'</tr></table><br />';
}
}
$datatable .= '</div></td></tr>'.
&loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
$othertitle,$usertypes,$types,\%servers,
\%currbalancer,$lonhost,
$targets_div_style,$homedom_div_style,
$css_class[$cssidx],$balnum,$islast);
$$rowtotal += $rownum;
$balnum ++;
}
$datatable .= '<input type="hidden" name="loadbalancing_total" id="loadbalancing_total" value="'.$balnum.'" />';
return $datatable;
}
sub get_loadbalancers_config {
my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_;
return unless ((ref($servers) eq 'HASH') &&
(ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&
(ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH'));
if (keys(%{$existing}) > 0) {
my $oldlonhost;
foreach my $key (sort(keys(%{$existing}))) {
if ($key eq 'lonhost') {
$oldlonhost = $existing->{'lonhost'};
$currbalancer->{$oldlonhost} = 1;
} elsif ($key eq 'targets') {
if ($oldlonhost) {
$currtargets->{$oldlonhost} = $existing->{'targets'};
}
} elsif ($key eq 'rules') {
if ($oldlonhost) {
$currrules->{$oldlonhost} = $existing->{'rules'};
}
} elsif (ref($existing->{$key}) eq 'HASH') {
$currbalancer->{$key} = 1;
$currtargets->{$key} = $existing->{$key}{'targets'};
$currrules->{$key} = $existing->{$key}{'rules'};
}
}
} else {
my ($balancerref,$targetsref) =
&Apache::lonnet::get_lonbalancer_config($servers);
if ((ref($balancerref) eq 'HASH') && (ref($targetsref) eq 'HASH')) {
foreach my $server (sort(keys(%{$balancerref}))) {
$currbalancer->{$server} = 1;
$currtargets->{$server} = $targetsref->{$server};
}
}
}
return;
}
sub loadbalancing_rules {
my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,
$currbalancer,$lonhost,$targets_div_style,$homedom_div_style,
$css_class,$balnum,$islast) = @_;
my $output;
my $num = 0;
my ($alltypes,$othertypes,$titles) =
&loadbalancing_titles($dom,$intdom,$usertypes,$types);
if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
foreach my $type (@{$alltypes}) {
$num ++;
my $current;
if (ref($currrules) eq 'HASH') {
$current = $currrules->{$type};
}
if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) {
if ($dom ne &Apache::lonnet::host_domain($lonhost)) {
$current = '';
}
}
$output .= &loadbalance_rule_row($type,$titles->{$type},$current,
$servers,$currbalancer,$lonhost,$dom,
$targets_div_style,$homedom_div_style,
$css_class,$balnum,$num,$islast);
}
}
return $output;
}
sub loadbalancing_titles {
my ($dom,$intdom,$usertypes,$types) = @_;
my %othertypes = (
'_LC_adv' => &mt('Advanced users from [_1]',$dom),
'_LC_author' => &mt('Users from [_1] with author role',$dom),
'_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),
'_LC_external' => &mt('Users not from [_1]',$intdom),
'_LC_ipchangesso' => &mt('SSO users from [_1], with IP mismatch',$dom),
'_LC_ipchange' => &mt('Non-SSO users with IP mismatch'),
);
my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange');
if (ref($types) eq 'ARRAY') {
unshift(@alltypes,@{$types},'default');
}
my %titles;
foreach my $type (@alltypes) {
if ($type =~ /^_LC_/) {
$titles{$type} = $othertypes{$type};
} elsif ($type eq 'default') {
$titles{$type} = &mt('All users from [_1]',$dom);
if (ref($types) eq 'ARRAY') {
if (@{$types} > 0) {
$titles{$type} = &mt('Other users from [_1]',$dom);
}
}
} elsif (ref($usertypes) eq 'HASH') {
$titles{$type} = $usertypes->{$type};
}
}
return (\@alltypes,\%othertypes,\%titles);
}
sub loadbalance_rule_row {
my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom,
$targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_;
my @rulenames;
my %ruletitles = &offloadtype_text();
if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) {
@rulenames = ('balancer','offloadedto');
} else {
@rulenames = ('default','homeserver');
if ($type eq '_LC_external') {
push(@rulenames,'externalbalancer');
} else {
push(@rulenames,'specific');
}
push(@rulenames,'none');
}
my $style = $targets_div_style;
if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) {
$style = $homedom_div_style;
}
my $space;
if ($islast && $num == 1) {
$space = '<div display="inline-block"> </div>';
}
my $output =
'<tr class="'.$css_class.'" id="balanceruletr_'.$balnum.'_'.$num.'"><td valign="top">'.$space.
'<div id="balanceruletitle_'.$balnum.'_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".
'<td valaign="top">'.$space.
'<div id="balancerule_'.$balnum.'_'.$type.'" style="'.$style.'">'."\n";
for (my $i=0; $i<@rulenames; $i++) {
my $rule = $rulenames[$i];
my ($checked,$extra);
if ($rulenames[$i] eq 'default') {
$rule = '';
}
if ($rulenames[$i] eq 'specific') {
if (ref($servers) eq 'HASH') {
my $default;
if (($current ne '') && (exists($servers->{$current}))) {
$checked = ' checked="checked"';
}
unless ($checked) {
$default = ' selected="selected"';
}
$extra =
': <select name="loadbalancing_singleserver_'.$balnum.'_'.$type.
'" id="loadbalancing_singleserver_'.$balnum.'_'.$type.
'" onchange="singleServerToggle('."'$balnum','$type'".')">'."\n".
'<option value=""'.$default.'></option>'."\n";
foreach my $server (sort(keys(%{$servers}))) {
if (ref($currbalancer) eq 'HASH') {
next if (exists($currbalancer->{$server}));
}
my $selected;
if ($server eq $current) {
$selected = ' selected="selected"';
}
$extra .= '<option value="'.$server.'"'.$selected.'>'.$server.'</option>';
}
$extra .= '</select>';
}
} elsif ($rule eq $current) {
$checked = ' checked="checked"';
}
$output .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="loadbalancing_rules_'.$balnum.'_'.$type.
'" id="loadbalancing_rules_'.$balnum.'_'.$type.'_'.$i.'" value="'.
$rule.'" onclick="balanceruleChange('."this.form,'$balnum','$type'".
')"'.$checked.' /> '.$ruletitles{$rulenames[$i]}.
'</label>'.$extra.'</span><br />'."\n";
}
$output .= '</div></td></tr>'."\n";
return $output;
}
sub offloadtype_text {
my %ruletitles = &Apache::lonlocal::texthash (
'default' => 'Offloads to default destinations',
'homeserver' => "Offloads to user's home server",
'externalbalancer' => "Offloads to Load Balancer in user's domain",
'specific' => 'Offloads to specific server',
'none' => 'No offload',
'balancer' => 'Session hosted on Load Balancer, after re-authentication',
'offloadedto' => 'Session hosted on offload server, after re-authentication',
);
return %ruletitles;
}
sub sparestype_titles {
my %typestitles = &Apache::lonlocal::texthash (
'primary' => 'primary',
'default' => 'default',
);
return %typestitles;
}
sub contact_titles {
my %titles = &Apache::lonlocal::texthash (
'supportemail' => 'Support E-mail address',
'adminemail' => 'Default Server Admin E-mail address',
'errormail' => 'Error reports to be e-mailed to',
'packagesmail' => 'Package update alerts to be e-mailed to',
'helpdeskmail' => 'Helpdesk requests to be e-mailed to',
'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',
'requestsmail' => 'E-mail from course requests requiring approval',
'updatesmail' => 'E-mail from nightly check of LON-CAPA module integrity/updates',
'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
);
my %short_titles = &Apache::lonlocal::texthash (
adminemail => 'Admin E-mail address',
supportemail => 'Support E-mail',
);
return (\%titles,\%short_titles);
}
sub tool_titles {
my %titles = &Apache::lonlocal::texthash (
aboutme => 'Personal web page',
blog => 'Blog',
webdav => 'WebDAV',
portfolio => 'Portfolio',
official => 'Official courses (with institutional codes)',
unofficial => 'Unofficial courses',
community => 'Communities',
textbook => 'Textbook courses',
);
return %titles;
}
sub courserequest_titles {
my %titles = &Apache::lonlocal::texthash (
official => 'Official',
unofficial => 'Unofficial',
community => 'Communities',
textbook => 'Textbook',
norequest => 'Not allowed',
approval => 'Approval by Dom. Coord.',
validate => 'With validation',
autolimit => 'Numerical limit',
unlimited => '(blank for unlimited)',
);
return %titles;
}
sub authorrequest_titles {
my %titles = &Apache::lonlocal::texthash (
norequest => 'Not allowed',
approval => 'Approval by Dom. Coord.',
automatic => 'Automatic approval',
);
return %titles;
}
sub courserequest_conditions {
my %conditions = &Apache::lonlocal::texthash (
approval => '(Processing of request subject to approval by Domain Coordinator).',
validate => '(Processing of request subject to institutional validation).',
);
return %conditions;
}
sub print_usercreation {
my ($position,$dom,$settings,$rowtotal) = @_;
my $numinrow = 4;
my $datatable;
if ($position eq 'top') {
$$rowtotal ++;
my $rowcount = 0;
my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username');
if (ref($rules) eq 'HASH') {
if (keys(%{$rules}) > 0) {
$datatable .= &user_formats_row('username',$settings,$rules,
$ruleorder,$numinrow,$rowcount);
$$rowtotal ++;
$rowcount ++;
}
}
my ($idrules,$idruleorder) = &Apache::lonnet::inst_userrules($dom,'id');
if (ref($idrules) eq 'HASH') {
if (keys(%{$idrules}) > 0) {
$datatable .= &user_formats_row('id',$settings,$idrules,
$idruleorder,$numinrow,$rowcount);
$$rowtotal ++;
$rowcount ++;
}
}
if ($rowcount == 0) {
$datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';
$$rowtotal ++;
$rowcount ++;
}
} elsif ($position eq 'middle') {
my @creators = ('author','course','requestcrs');
my ($rules,$ruleorder) =
&Apache::lonnet::inst_userrules($dom,'username');
my %lt = &usercreation_types();
my %checked;
if (ref($settings) eq 'HASH') {
if (ref($settings->{'cancreate'}) eq 'HASH') {
foreach my $item (@creators) {
$checked{$item} = $settings->{'cancreate'}{$item};
}
} elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {
foreach my $item (@creators) {
if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {
$checked{$item} = 'none';
}
}
}
}
my $rownum = 0;
foreach my $item (@creators) {
$rownum ++;
if ($checked{$item} eq '') {
$checked{$item} = 'any';
}
my $css_class;
if ($rownum%2) {
$css_class = '';
} else {
$css_class = ' class="LC_odd_row" ';
}
$datatable .= '<tr'.$css_class.'>'.
'<td><span class="LC_nobreak">'.$lt{$item}.
'</span></td><td align="right">';
my @options = ('any');
if (ref($rules) eq 'HASH') {
if (keys(%{$rules}) > 0) {
push(@options,('official','unofficial'));
}
}
push(@options,'none');
foreach my $option (@options) {
my $type = 'radio';
my $check = ' ';
if ($checked{$item} eq $option) {
$check = ' checked="checked" ';
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="'.$type.'" name="can_createuser_'.
$item.'" value="'.$option.'"'.$check.'/> '.
$lt{$option}.'</label> </span>';
}
$datatable .= '</td></tr>';
}
} else {
my @contexts = ('author','course','domain');
my @authtypes = ('int','krb4','krb5','loc');
my %checked;
if (ref($settings) eq 'HASH') {
if (ref($settings->{'authtypes'}) eq 'HASH') {
foreach my $item (@contexts) {
if (ref($settings->{'authtypes'}{$item}) eq 'HASH') {
foreach my $auth (@authtypes) {
if ($settings->{'authtypes'}{$item}{$auth}) {
$checked{$item}{$auth} = ' checked="checked" ';
}
}
}
}
}
} else {
foreach my $item (@contexts) {
foreach my $auth (@authtypes) {
$checked{$item}{$auth} = ' checked="checked" ';
}
}
}
my %title = &context_names();
my %authname = &authtype_names();
my $rownum = 0;
my $css_class;
foreach my $item (@contexts) {
if ($rownum%2) {
$css_class = '';
} else {
$css_class = ' class="LC_odd_row" ';
}
$datatable .= '<tr'.$css_class.'>'.
'<td>'.$title{$item}.
'</td><td class="LC_left_item">'.
'<span class="LC_nobreak">';
foreach my $auth (@authtypes) {
$datatable .= '<label>'.
'<input type="checkbox" name="'.$item.'_auth" '.
$checked{$item}{$auth}.' value="'.$auth.'" />'.
$authname{$auth}.'</label> ';
}
$datatable .= '</span></td></tr>';
$rownum ++;
}
$$rowtotal += $rownum;
}
return $datatable;
}
sub print_selfcreation {
my ($position,$dom,$settings,$rowtotal) = @_;
my (@selfcreate,$createsettings,$datatable);
if (ref($settings) eq 'HASH') {
if (ref($settings->{'cancreate'}) eq 'HASH') {
$createsettings = $settings->{'cancreate'};
if (ref($settings->{'cancreate'}{'selfcreate'}) eq 'ARRAY') {
@selfcreate = @{$settings->{'cancreate'}{'selfcreate'}};
} elsif ($settings->{'cancreate'}{'selfcreate'} ne '') {
if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {
@selfcreate = ('email','login','sso');
} elsif ($settings->{'cancreate'}{'selfcreate'} ne 'none') {
@selfcreate = ($settings->{'cancreate'}{'selfcreate'});
}
}
}
}
my %radiohash;
my $numinrow = 4;
map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;
if ($position eq 'top') {
my %choices = &Apache::lonlocal::texthash (
cancreate_login => 'Institutional Login',
cancreate_sso => 'Institutional Single Sign On',
);
my @toggles = sort(keys(%choices));
my %defaultchecked = (
'cancreate_login' => 'off',
'cancreate_sso' => 'off',
);
my ($onclick,$itemcount);
($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
\%choices,$itemcount,$onclick);
$$rowtotal += $itemcount;
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
if (ref($usertypes) eq 'HASH') {
if (keys(%{$usertypes}) > 0) {
$datatable .= &insttypes_row($createsettings,$types,$usertypes,
$dom,$numinrow,$othertitle,
'statustocreate',$$rowtotal);
$$rowtotal ++;
}
}
} elsif ($position eq 'middle') {
my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
$usertypes->{'default'} = $othertitle;
if (ref($types) eq 'ARRAY') {
push(@{$types},'default');
$usertypes->{'default'} = $othertitle;
foreach my $status (@{$types}) {
$datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
$numinrow,$$rowtotal,$usertypes);
$$rowtotal ++;
}
}
} else {
my $css_class = $$rowtotal%2?' class="LC_odd_row"':'';
my %choices =
&Apache::lonlocal::texthash(
email => 'Approved automatically',
emailapproval => 'Queued for approval by DC',
off => 'Not enabled',
);
$datatable .= '<tr'.$css_class.'>'.
'<td>'.&mt('E-mail address as username').
'</td><td class="LC_left_item">'.
'<span class="LC_nobreak">';
foreach my $option ('email','emailapproval','off') {
my $checked;
if ($option eq 'email') {
if ($radiohash{'cancreate_email'}) {
$checked = 'checked="checked"';
}
} elsif ($option eq 'emailapproval') {
if ($radiohash{'cancreate_emailapproval'}) {
$checked = 'checked="checked"';
}
} else {
if ((!$radiohash{'cancreate_email'}) && (!$radiohash{'cancreate_emailapproval'})) {
$checked = 'checked="checked"';
}
}
$datatable .= '<label>'.
'<input type="radio" name="cancreate_email" '.
$checked.' value="'.$option.'" />'.
$choices{$option}.'</label> ';
}
$$rowtotal ++;
$datatable .= '</span></td></tr>'.
&print_requestmail($dom,'selfcreation',$createsettings,$rowtotal);
$$rowtotal ++;
my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
$numinrow = 1;
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
$usertypes->{'default'} = $othertitle;
if (ref($types) eq 'ARRAY') {
push(@{$types},'default');
$usertypes->{'default'} = $othertitle;
foreach my $status (@{$types}) {
$datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
$numinrow,$$rowtotal,$usertypes,$infofields,$infotitles);
$$rowtotal ++;
}
}
my ($emailrules,$emailruleorder) =
&Apache::lonnet::inst_userrules($dom,'email');
if (ref($emailrules) eq 'HASH') {
if (keys(%{$emailrules}) > 0) {
$datatable .= &user_formats_row('email',$settings,$emailrules,
$emailruleorder,$numinrow,$$rowtotal);
$$rowtotal ++;
}
}
$datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal);
}
return $datatable;
}
sub captcha_choice {
my ($context,$settings,$itemcount) = @_;
my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext);
my %lt = &captcha_phrases();
$keyentry = 'hidden';
if ($context eq 'cancreate') {
$rowname = &mt('CAPTCHA validation');
} elsif ($context eq 'login') {
$rowname = &mt('"Contact helpdesk" CAPTCHA validation');
}
if (ref($settings) eq 'HASH') {
if ($settings->{'captcha'}) {
$checked{$settings->{'captcha'}} = ' checked="checked"';
} else {
$checked{'original'} = ' checked="checked"';
}
if ($settings->{'captcha'} eq 'recaptcha') {
$pubtext = $lt{'pub'};
$privtext = $lt{'priv'};
$keyentry = 'text';
}
if (ref($settings->{'recaptchakeys'}) eq 'HASH') {
$currpub = $settings->{'recaptchakeys'}{'public'};
$currpriv = $settings->{'recaptchakeys'}{'private'};
}
} else {
$checked{'original'} = ' checked="checked"';
}
my $css_class = $itemcount%2?' class="LC_odd_row"':'';
my $output = '<tr'.$css_class.'>'.
'<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="2">'."\n".
'<table><tr><td>'."\n";
foreach my $option ('original','recaptcha','notused') {
$output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.
$option.'" '.$checked{$option}.' onchange="javascript:updateCaptcha('."this,'$context'".');" />'.
$lt{$option}.'</label></span>';
unless ($option eq 'notused') {
$output .= (' 'x2)."\n";
}
}
#
# Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit:
# https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple
# servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu)
# specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.
#
$output .= '</td></tr>'."\n".
'<tr><td>'."\n".
'<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span> '."\n".
'<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.
$currpub.'" size="40" /></span><br />'."\n".
'<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span> '."\n".
'<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.
$currpriv.'" size="40" /></span></td></tr></table>'."\n".
'</td></tr>';
return $output;
}
sub user_formats_row {
my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_;
my $output;
my %text = (
'username' => 'new usernames',
'id' => 'IDs',
'email' => 'self-created accounts (e-mail)',
);
my $css_class = $rowcount%2?' class="LC_odd_row"':'';
$output = '<tr '.$css_class.'>'.
'<td><span class="LC_nobreak">';
if ($type eq 'email') {
$output .= &mt("Formats disallowed for $text{$type}: ");
} else {
$output .= &mt("Format rules to check for $text{$type}: ");
}
$output .= '</span></td>'.
'<td class="LC_left_item" colspan="2"><table>';
my $rem;
if (ref($ruleorder) eq 'ARRAY') {
for (my $i=0; $i<@{$ruleorder}; $i++) {
if (ref($rules->{$ruleorder->[$i]}) eq 'HASH') {
my $rem = $i%($numinrow);
if ($rem == 0) {
if ($i > 0) {
$output .= '</tr>';
}
$output .= '<tr>';
}
my $check = ' ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{$type.'_rule'}) eq 'ARRAY') {
if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}})) {
$check = ' checked="checked" ';
}
}
}
$output .= '<td class="LC_left_item">'.
'<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$type.'_rule" '.
'value="'.$ruleorder->[$i].'"'.$check.'/>'.
$rules->{$ruleorder->[$i]}{'name'}.'</label></span></td>';
}
}
$rem = @{$ruleorder}%($numinrow);
}
my $colsleft = $numinrow - $rem;
if ($colsleft > 1 ) {
$output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
' </td>';
} elsif ($colsleft == 1) {
$output .= '<td class="LC_left_item"> </td>';
}
$output .= '</tr></table></td></tr>';
return $output;
}
sub usercreation_types {
my %lt = &Apache::lonlocal::texthash (
author => 'When adding a co-author',
course => 'When adding a user to a course',
requestcrs => 'When requesting a course',
any => 'Any',
official => 'Institutional only ',
unofficial => 'Non-institutional only',
none => 'None',
);
return %lt;
}
sub selfcreation_types {
my %lt = &Apache::lonlocal::texthash (
selfcreate => 'User creates own account',
any => 'Any',
official => 'Institutional only ',
unofficial => 'Non-institutional only',
email => 'E-mail address',
login => 'Institutional Login',
sso => 'SSO',
);
}
sub authtype_names {
my %lt = &Apache::lonlocal::texthash(
int => 'Internal',
krb4 => 'Kerberos 4',
krb5 => 'Kerberos 5',
loc => 'Local',
);
return %lt;
}
sub context_names {
my %context_title = &Apache::lonlocal::texthash(
author => 'Creating users when an Author',
course => 'Creating users when in a course',
domain => 'Creating users when a Domain Coordinator',
);
return %context_title;
}
sub print_usermodification {
my ($position,$dom,$settings,$rowtotal) = @_;
my $numinrow = 4;
my ($context,$datatable,$rowcount);
if ($position eq 'top') {
$rowcount = 0;
$context = 'author';
foreach my $role ('ca','aa') {
$datatable .= &modifiable_userdata_row($context,$role,$settings,
$numinrow,$rowcount);
$$rowtotal ++;
$rowcount ++;
}
} elsif ($position eq 'middle') {
$context = 'course';
$rowcount = 0;
foreach my $role ('st','ep','ta','in','cr') {
$datatable .= &modifiable_userdata_row($context,$role,$settings,
$numinrow,$rowcount);
$$rowtotal ++;
$rowcount ++;
}
}
return $datatable;
}
sub print_defaults {
my ($dom,$settings,$rowtotal) = @_;
my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
'datelocale_def','portal_def');
my %defaults;
if (ref($settings) eq 'HASH') {
%defaults = %{$settings};
} else {
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
foreach my $item (@items) {
$defaults{$item} = $domdefaults{$item};
}
}
my $titles = &defaults_titles($dom);
my $rownum = 0;
my ($datatable,$css_class);
foreach my $item (@items) {
if ($rownum%2) {
$css_class = '';
} else {
$css_class = ' class="LC_odd_row" ';
}
$datatable .= '<tr'.$css_class.'>'.
'<td><span class="LC_nobreak">'.$titles->{$item}.
'</span></td><td class="LC_right_item">';
if ($item eq 'auth_def') {
my @authtypes = ('internal','krb4','krb5','localauth');
my %shortauth = (
internal => 'int',
krb4 => 'krb4',
krb5 => 'krb5',
localauth => 'loc'
);
my %authnames = &authtype_names();
foreach my $auth (@authtypes) {
my $checked = ' ';
if ($defaults{$item} eq $auth) {
$checked = ' checked="checked" ';
}
$datatable .= '<label><input type="radio" name="'.$item.
'" value="'.$auth.'"'.$checked.'/>'.
$authnames{$shortauth{$auth}}.'</label> ';
}
} elsif ($item eq 'timezone_def') {
my $includeempty = 1;
$datatable .= &Apache::loncommon::select_timezone($item,$defaults{$item},undef,$includeempty);
} elsif ($item eq 'datelocale_def') {
my $includeempty = 1;
$datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);
} elsif ($item eq 'lang_def') {
my %langchoices = &get_languages_hash();
$langchoices{''} = 'No language preference';
%langchoices = &Apache::lonlocal::texthash(%langchoices);
$datatable .= &Apache::loncommon::select_form($defaults{$item},$item,
\%langchoices);
} else {
my $size;
if ($item eq 'portal_def') {
$size = ' size="25"';
}
$datatable .= '<input type="text" name="'.$item.'" value="'.
$defaults{$item}.'"'.$size.' />';
}
$datatable .= '</td></tr>';
$rownum ++;
}
$$rowtotal += $rownum;
return $datatable;
}
sub get_languages_hash {
my %langchoices;
foreach my $id (&Apache::loncommon::languageids()) {
my $code = &Apache::loncommon::supportedlanguagecode($id);
if ($code ne '') {
$langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id);
}
}
return %langchoices;
}
sub defaults_titles {
my ($dom) = @_;
my %titles = &Apache::lonlocal::texthash (
'auth_def' => 'Default authentication type',
'auth_arg_def' => 'Default authentication argument',
'lang_def' => 'Default language',
'timezone_def' => 'Default timezone',
'datelocale_def' => 'Default locale for dates',
'portal_def' => 'Portal/Default URL',
);
if ($dom) {
my $uprimary_id = &Apache::lonnet::domain($dom,'primary');
my $uint_dom = &Apache::lonnet::internet_dom($uprimary_id);
my $protocol = $Apache::lonnet::protocol{$uprimary_id};
$protocol = 'http' if ($protocol ne 'https');
if ($uint_dom) {
$titles{'portal_def'} .= ' '.&mt('(for example: [_1])',$protocol.'://loncapa.'.
$uint_dom);
}
}
return (\%titles);
}
sub print_scantronformat {
my ($r,$dom,$confname,$settings,$rowtotal) = @_;
my $itemcount = 1;
my ($datatable,$css_class,$scantronurl,$is_custom,%error,%scantronurls,
%confhash);
my $switchserver = &check_switchserver($dom,$confname);
my %lt = &Apache::lonlocal::texthash (
default => 'Default bubblesheet format file error',
custom => 'Custom bubblesheet format file error',
);
my %scantronfiles = (
default => 'default.tab',
custom => 'custom.tab',
);
foreach my $key (keys(%scantronfiles)) {
$scantronurls{$key} = '/res/'.$dom.'/'.$confname.'/scantron/'
.$scantronfiles{$key};
}
my @defaultinfo = &Apache::lonnet::stat_file($scantronurls{'default'});
if ((!@defaultinfo) || ($defaultinfo[0] eq 'no_such_dir')) {
if (!$switchserver) {
my $servadm = $r->dir_config('lonAdmEMail');
my ($configuserok,$author_ok) = &config_check($dom,$confname,$servadm);
if ($configuserok eq 'ok') {
if ($author_ok eq 'ok') {
my %legacyfile = (
default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',
custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',
);
my %md5chk;
foreach my $type (keys(%legacyfile)) {
($md5chk{$type}) = split(/ /,`md5sum $legacyfile{$type}`);
chomp($md5chk{$type});
}
if ($md5chk{'default'} ne $md5chk{'custom'}) {
foreach my $type (keys(%legacyfile)) {
($scantronurls{$type},my $error) =
&legacy_scantronformat($r,$dom,$confname,
$type,$legacyfile{$type},
$scantronurls{$type},
$scantronfiles{$type});
if ($error ne '') {
$error{$type} = $error;
}
}
if (keys(%error) == 0) {
$is_custom = 1;
$confhash{'scantron'}{'scantronformat'} =
$scantronurls{'custom'};
my $putresult =
&Apache::lonnet::put_dom('configuration',
\%confhash,$dom);
if ($putresult ne 'ok') {
$error{'custom'} =
'<span class="LC_error">'.
&mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
}
}
} else {
($scantronurls{'default'},my $error) =
&legacy_scantronformat($r,$dom,$confname,
'default',$legacyfile{'default'},
$scantronurls{'default'},
$scantronfiles{'default'});
if ($error eq '') {
$confhash{'scantron'}{'scantronformat'} = '';
my $putresult =
&Apache::lonnet::put_dom('configuration',
\%confhash,$dom);
if ($putresult ne 'ok') {
$error{'default'} =
'<span class="LC_error">'.
&mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
}
} else {
$error{'default'} = $error;
}
}
}
}
} else {
$error{'default'} = &mt("Unable to copy default bubblesheet formatfile to domain's RES space: [_1]",$switchserver);
}
}
if (ref($settings) eq 'HASH') {
if ($settings->{'scantronformat'} eq "/res/$dom/$confname/scantron/custom.tab") {
my @info = &Apache::lonnet::stat_file($settings->{'scantronformat'});
if ((!@info) || ($info[0] eq 'no_such_dir')) {
$scantronurl = '';
} else {
$scantronurl = $settings->{'scantronformat'};
}
$is_custom = 1;
} else {
$scantronurl = $scantronurls{'default'};
}
} else {
if ($is_custom) {
$scantronurl = $scantronurls{'custom'};
} else {
$scantronurl = $scantronurls{'default'};
}
}
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>';
if (!$is_custom) {
$datatable .= '<td>'.&mt('Default in use:').'<br />'.
'<span class="LC_nobreak">';
if ($scantronurl) {
$datatable .= &Apache::loncommon::modal_link($scantronurl,&mt('Default bubblesheet format file'),600,500,
undef,undef,undef,undef,'background-color:#ffffff');
} else {
$datatable = &mt('File unavailable for display');
}
$datatable .= '</span></td>';
if (keys(%error) == 0) {
$datatable .= '<td valign="bottom">';
if (!$switchserver) {
$datatable .= &mt('Upload:').'<br />';
}
} else {
my $errorstr;
foreach my $key (sort(keys(%error))) {
$errorstr .= $lt{$key}.': '.$error{$key}.'<br />';
}
$datatable .= '<td>'.$errorstr;
}
} else {
if (keys(%error) > 0) {
my $errorstr;
foreach my $key (sort(keys(%error))) {
$errorstr .= $lt{$key}.': '.$error{$key}.'<br />';
}
$datatable .= '<td>'.$errorstr.'</td><td> ';
} elsif ($scantronurl) {
my $link = &Apache::loncommon::modal_link($scantronurl,&mt('Custom bubblesheet format file'),600,500,
undef,undef,undef,undef,'background-color:#ffffff');
$datatable .= '<td><span class="LC_nobreak">'.
$link.
'<label><input type="checkbox" name="scantronformat_del"'.
' value="1" />'.&mt('Delete?').'</label></span></td>'.
'<td><span class="LC_nobreak"> '.
&mt('Replace:').'</span><br />';
}
}
if (keys(%error) == 0) {
if ($switchserver) {
$datatable .= &mt('Upload to library server: [_1]',$switchserver);
} else {
$datatable .='<span class="LC_nobreak"> '.
'<input type="file" name="scantronformat" /></span>';
}
}
$datatable .= '</td></tr>';
$$rowtotal ++;
return $datatable;
}
sub legacy_scantronformat {
my ($r,$dom,$confname,$file,$legacyfile,$newurl,$newfile) = @_;
my ($url,$error);
my @statinfo = &Apache::lonnet::stat_file($newurl);
if ((!@statinfo) || ($statinfo[0] eq 'no_such_dir')) {
(my $result,$url) =
&publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron',
'','',$newfile);
if ($result ne 'ok') {
$error = &mt("An error occurred publishing the [_1] bubblesheet format file in RES space. Error was: [_2].",$newfile,$result);
}
}
return ($url,$error);
}
sub print_coursecategories {
my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
my $datatable;
if ($position eq 'top') {
my $toggle_cats_crs = ' ';
my $toggle_cats_dom = ' checked="checked" ';
my $can_cat_crs = ' ';
my $can_cat_dom = ' checked="checked" ';
my $toggle_catscomm_comm = ' ';
my $toggle_catscomm_dom = ' checked="checked" ';
my $can_catcomm_comm = ' ';
my $can_catcomm_dom = ' checked="checked" ';
if (ref($settings) eq 'HASH') {
if ($settings->{'togglecats'} eq 'crs') {
$toggle_cats_crs = $toggle_cats_dom;
$toggle_cats_dom = ' ';
}
if ($settings->{'categorize'} eq 'crs') {
$can_cat_crs = $can_cat_dom;
$can_cat_dom = ' ';
}
if ($settings->{'togglecatscomm'} eq 'comm') {
$toggle_catscomm_comm = $toggle_catscomm_dom;
$toggle_catscomm_dom = ' ';
}
if ($settings->{'categorizecomm'} eq 'comm') {
$can_catcomm_comm = $can_catcomm_dom;
$can_catcomm_dom = ' ';
}
}
my %title = &Apache::lonlocal::texthash (
togglecats => 'Show/Hide a course in catalog',
togglecatscomm => 'Show/Hide a community in catalog',
categorize => 'Assign a category to a course',
categorizecomm => 'Assign a category to a community',
);
my %level = &Apache::lonlocal::texthash (
dom => 'Set in Domain',
crs => 'Set in Course',
comm => 'Set in Community',
);
$datatable = '<tr class="LC_odd_row">'.
'<td>'.$title{'togglecats'}.'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="togglecats"'.
$toggle_cats_dom.' value="dom" />'.$level{'dom'}.'</label> '.
'<label><input type="radio" name="togglecats"'.
$toggle_cats_crs.' value="crs" />'.$level{'crs'}.'</label></span></td>'.
'</tr><tr>'.
'<td>'.$title{'categorize'}.'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak">'.
'<label><input type="radio" name="categorize"'.
$can_cat_dom.' value="dom" />'.$level{'dom'}.'</label> '.
'<label><input type="radio" name="categorize"'.
$can_cat_crs.'value="crs" />'.$level{'crs'}.'</label></span></td>'.
'</tr><tr class="LC_odd_row">'.
'<td>'.$title{'togglecatscomm'}.'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak"><label>'.
'<input type="radio" name="togglecatscomm"'.
$toggle_catscomm_dom.' value="dom" />'.$level{'dom'}.'</label> '.
'<label><input type="radio" name="togglecatscomm"'.
$toggle_catscomm_comm.' value="comm" />'.$level{'comm'}.'</label></span></td>'.
'</tr><tr>'.
'<td>'.$title{'categorizecomm'}.'</td>'.
'<td class="LC_right_item"><span class="LC_nobreak">'.
'<label><input type="radio" name="categorizecomm"'.
$can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label> '.
'<label><input type="radio" name="categorizecomm"'.
$can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.
'</tr>';
$$rowtotal += 4;
} else {
my $css_class;
my $itemcount = 1;
my $cathash;
if (ref($settings) eq 'HASH') {
$cathash = $settings->{'cats'};
}
if (ref($cathash) eq 'HASH') {
my (@cats,@trails,%allitems,%idx,@jsarray);
&Apache::loncommon::extract_categories($cathash,\@cats,\@trails,
\%allitems,\%idx,\@jsarray);
my $maxdepth = scalar(@cats);
my $colattrib = '';
if ($maxdepth > 2) {
$colattrib = ' colspan="2" ';
}
my @path;
if (@cats > 0) {
if (ref($cats[0]) eq 'ARRAY') {
my $numtop = @{$cats[0]};
my $maxnum = $numtop;
my %default_names = (
instcode => &mt('Official courses'),
communities => &mt('Communities'),
);
if ((!grep(/^instcode$/,@{$cats[0]})) ||
($cathash->{'instcode::0'} eq '') ||
(!grep(/^communities$/,@{$cats[0]})) ||
($cathash->{'communities::0'} eq '')) {
$maxnum ++;
}
my $lastidx;
for (my $i=0; $i<$numtop; $i++) {
my $parent = $cats[0][$i];
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $item = &escape($parent).'::0';
my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$item','$idx{$item}'".');"';
$lastidx = $idx{$item};
$datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
.'<select name="'.$item.'"'.$chgstr.'>';
for (my $k=0; $k<=$maxnum; $k++) {
my $vpos = $k+1;
my $selstr;
if ($k == $i) {
$selstr = ' selected="selected" ';
}
$datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
}
$datatable .= '</select></span></td><td>';
if ($parent eq 'instcode' || $parent eq 'communities') {
$datatable .= '<span class="LC_nobreak">'
.$default_names{$parent}.'</span>';
if ($parent eq 'instcode') {
$datatable .= '<br /><span class="LC_nobreak">('
.&mt('with institutional codes')
.')</span></td><td'.$colattrib.'>';
} else {
$datatable .= '<table><tr><td>';
}
$datatable .= '<span class="LC_nobreak">'
.'<label><input type="radio" name="'
.$parent.'" value="1" checked="checked" />'
.&mt('Display').'</label>';
if ($parent eq 'instcode') {
$datatable .= ' ';
} else {
$datatable .= '</span></td></tr><tr><td>'
.'<span class="LC_nobreak">';
}
$datatable .= '<label><input type="radio" name="'
.$parent.'" value="0" />'
.&mt('Do not display').'</label></span>';
if ($parent eq 'communities') {
$datatable .= '</td></tr></table>';
}
$datatable .= '</td>';
} else {
$datatable .= $parent
.' <span class="LC_nobreak"><label>'
.'<input type="checkbox" name="deletecategory" '
.'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';
}
my $depth = 1;
push(@path,$parent);
$datatable .= &build_category_rows($itemcount,\@cats,$depth,$parent,\@path,\%idx);
pop(@path);
$datatable .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';
$itemcount ++;
}
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','$lastidx'".');"';
$datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak"><select name="addcategory_pos"'.$chgstr.'>';
for (my $k=0; $k<=$maxnum; $k++) {
my $vpos = $k+1;
my $selstr;
if ($k == $numtop) {
$selstr = ' selected="selected" ';
}
$datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
}
$datatable .= '</select></span></td><td colspan="2">'.&mt('Add category:').' '
.'<input type="text" size="20" name="addcategory_name" value="" /></td>'
.'</tr>'."\n";
$itemcount ++;
foreach my $default ('instcode','communities') {
if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';
$datatable .= '<tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr><tr '.$css_class.'><td>'.
'<span class="LC_nobreak"><select name="'.$default.'_pos"'.$chgstr.'>';
for (my $k=0; $k<=$maxnum; $k++) {
my $vpos = $k+1;
my $selstr;
if ($k == $maxnum) {
$selstr = ' selected="selected" ';
}
$datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
}
$datatable .= '</select></span></td>'.
'<td><span class="LC_nobreak">'.
$default_names{$default}.'</span>';
if ($default eq 'instcode') {
$datatable .= '<br /><span class="LC_nobreak">('
.&mt('with institutional codes').')</span>';
}
$datatable .= '</td>'
.'<td><span class="LC_nobreak"><label><input type="radio" name="'.$default.'" value="1" />'
.&mt('Display').'</label> '
.'<label><input type="radio" name="'.$default.'" value="0" checked="checked"/>'
.&mt('Do not display').'</label></span></td></tr>';
}
}
}
} else {
$datatable .= &initialize_categories($itemcount);
}
} else {
$datatable .= '<td class="LC_right_item">'.$hdritem->{'header'}->[0]->{'col2'}.'</td>'
.&initialize_categories($itemcount);
}
$$rowtotal += $itemcount;
}
return $datatable;
}
sub print_serverstatuses {
my ($dom,$settings,$rowtotal) = @_;
my $datatable;
my @pages = &serverstatus_pages();
my (%namedaccess,%machineaccess);
foreach my $type (@pages) {
$namedaccess{$type} = '';
$machineaccess{$type}= '';
}
if (ref($settings) eq 'HASH') {
foreach my $type (@pages) {
if (exists($settings->{$type})) {
if (ref($settings->{$type}) eq 'HASH') {
foreach my $key (keys(%{$settings->{$type}})) {
if ($key eq 'namedusers') {
$namedaccess{$type} = $settings->{$type}->{$key};
} elsif ($key eq 'machines') {
$machineaccess{$type} = $settings->{$type}->{$key};
}
}
}
}
}
}
my $titles= &LONCAPA::lonauthcgi::serverstatus_titles();
my $rownum = 0;
my $css_class;
foreach my $type (@pages) {
$rownum ++;
$css_class = $rownum%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'>'.
'<td><span class="LC_nobreak">'.
$titles->{$type}.'</span></td>'.
'<td class="LC_left_item">'.
'<input type="text" name="'.$type.'_namedusers" '.
'value="'.$namedaccess{$type}.'" size="30" /></td>'.
'<td class="LC_right_item">'.
'<span class="LC_nobreak">'.
'<input type="text" name="'.$type.'_machines" '.
'value="'.$machineaccess{$type}.'" size="10" />'.
'</td></tr>'."\n";
}
$$rowtotal += $rownum;
return $datatable;
}
sub serverstatus_pages {
return ('userstatus','lonstatus','loncron','server-status','codeversions',
'checksums','clusterstatus','metadata_keywords','metadata_harvest',
'takeoffline','takeonline','showenv','toggledebug','ping','domconf',
'uniquecodes','diskusage');
}
sub coursecategories_javascript {
my ($settings) = @_;
my ($output,$jstext,$cathash);
if (ref($settings) eq 'HASH') {
$cathash = $settings->{'cats'};
}
if (ref($cathash) eq 'HASH') {
my (@cats,@jsarray,%idx);
&Apache::loncommon::gather_categories($cathash,\@cats,\%idx,\@jsarray);
if (@jsarray > 0) {
$jstext = ' var categories = Array('.scalar(@jsarray).');'."\n";
for (my $i=0; $i<@jsarray; $i++) {
if (ref($jsarray[$i]) eq 'ARRAY') {
my $catstr = join('","',@{$jsarray[$i]});
$jstext .= ' categories['.$i.'] = Array("'.$catstr.'");'."\n";
}
}
}
} else {
$jstext = ' var categories = Array(1);'."\n".
' categories[0] = Array("instcode_pos");'."\n";
}
my $instcode_reserved = &mt('The name: "instcode" is a reserved category');
my $communities_reserved = &mt('The name: "communities" is a reserved category');
my $choose_again = '\\n'.&mt('Please use a different name for the new top level category');
$output = <<"ENDSCRIPT";
<script type="text/javascript">
// <![CDATA[
function reorderCats(form,parent,item,idx) {
var changedVal;
$jstext
var newpos = 'addcategory_pos';
var current = new Array;
if (parent == '') {
var has_instcode = 0;
var maxtop = categories[idx].length;
for (var j=0; j<maxtop; j++) {
if (categories[idx][j] == 'instcode::0') {
has_instcode == 1;
}
}
if (has_instcode == 0) {
categories[idx][maxtop] = 'instcode_pos';
}
} else {
newpos += '_'+parent;
}
var maxh = 1 + categories[idx].length;
var current = new Array;
var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
if (item == newpos) {
changedVal = newitemVal;
} else {
changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
current[newitemVal] = newpos;
}
for (var i=0; i<categories[idx].length; i++) {
var elementName = categories[idx][i];
if (elementName != item) {
if (form.elements[elementName]) {
var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
current[currVal] = elementName;
}
}
}
var oldVal;
for (var j=0; j<maxh; j++) {
if (current[j] == undefined) {
oldVal = j;
}
}
if (oldVal < changedVal) {
for (var k=oldVal+1; k<=changedVal ; k++) {
var elementName = current[k];
form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
}
} else {
for (var k=changedVal; k<oldVal; k++) {
var elementName = current[k];
form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
}
}
return;
}
function categoryCheck(form) {
if (form.elements['addcategory_name'].value == 'instcode') {
alert('$instcode_reserved\\n$choose_again');
return false;
}
if (form.elements['addcategory_name'].value == 'communities') {
alert('$communities_reserved\\n$choose_again');
return false;
}
return true;
}
// ]]>
</script>
ENDSCRIPT
return $output;
}
sub initialize_categories {
my ($itemcount) = @_;
my ($datatable,$css_class,$chgstr);
my %default_names = (
instcode => 'Official courses (with institutional codes)',
communities => 'Communities',
);
my $select0 = ' selected="selected"';
my $select1 = '';
foreach my $default ('instcode','communities') {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';
if ($default eq 'communities') {
$select1 = $select0;
$select0 = '';
}
$datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
.'<select name="'.$default.'_pos">'
.'<option value="0"'.$select0.'>1</option>'
.'<option value="1"'.$select1.'>2</option>'
.'<option value="2">3</option></select> '
.$default_names{$default}
.'</span></td><td><span class="LC_nobreak">'
.'<label><input type="radio" name="'.$default.'" value="1" checked="checked" />'
.&mt('Display').'</label> <label>'
.'<input type="radio" name="'.$default.'" value="0" />'.&mt('Do not display')
.'</label></span></td></tr>';
$itemcount ++;
}
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','0'".');"';
$datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
.'<select name="addcategory_pos"'.$chgstr.'>'
.'<option value="0">1</option>'
.'<option value="1">2</option>'
.'<option value="2" selected="selected">3</option></select> '
.&mt('Add category').'</td><td>'.&mt('Name:')
.' <input type="text" size="20" name="addcategory_name" value="" /></td></tr>';
return $datatable;
}
sub build_category_rows {
my ($itemcount,$cats,$depth,$parent,$path,$idx) = @_;
my ($text,$name,$item,$chgstr);
if (ref($cats) eq 'ARRAY') {
my $maxdepth = scalar(@{$cats});
if (ref($cats->[$depth]) eq 'HASH') {
if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
my $numchildren = @{$cats->[$depth]{$parent}};
my $css_class = $itemcount%2?' class="LC_odd_row"':'';
$text .= '<td><table class="LC_data_table">';
my ($idxnum,$parent_name,$parent_item);
my $higher = $depth - 1;
if ($higher == 0) {
$parent_name = &escape($parent).'::'.$higher;
} else {
if (ref($path) eq 'ARRAY') {
$parent_name = &escape($parent).':'.&escape($path->[-2]).':'.$higher;
}
}
$parent_item = 'addcategory_pos_'.$parent_name;
for (my $j=0; $j<=$numchildren; $j++) {
if ($j < $numchildren) {
$name = $cats->[$depth]{$parent}[$j];
$item = &escape($name).':'.&escape($parent).':'.$depth;
$idxnum = $idx->{$item};
} else {
$name = $parent_name;
$item = $parent_item;
}
$chgstr = ' onchange="javascript:reorderCats(this.form,'."'$parent_name','$item','$idxnum'".');"';
$text .= '<tr '.$css_class.'><td><span class="LC_nobreak"><select name="'.$item.'"'.$chgstr.'>';
for (my $i=0; $i<=$numchildren; $i++) {
my $vpos = $i+1;
my $selstr;
if ($j == $i) {
$selstr = ' selected="selected" ';
}
$text .= '<option value="'.$i.'"'.$selstr.'>'.$vpos.'</option>';
}
$text .= '</select> ';
if ($j < $numchildren) {
my $deeper = $depth+1;
$text .= $name.' '
.'<label><input type="checkbox" name="deletecategory" value="'
.$item.'" />'.&mt('Delete').'</label></span></td><td>';
if(ref($path) eq 'ARRAY') {
push(@{$path},$name);
$text .= &build_category_rows($itemcount,$cats,$deeper,$name,$path,$idx);
pop(@{$path});
}
} else {
$text .= &mt('Add subcategory:').' </span><input type="textbox" size="20" name="addcategory_name_';
if ($j == $numchildren) {
$text .= $name;
} else {
$text .= $item;
}
$text .= '" value="" />';
}
$text .= '</td></tr>';
}
$text .= '</table></td>';
} else {
my $higher = $depth-1;
if ($higher == 0) {
$name = &escape($parent).'::'.$higher;
} else {
if (ref($path) eq 'ARRAY') {
$name = &escape($parent).':'.&escape($path->[-2]).':'.$higher;
}
}
my $colspan;
if ($parent ne 'instcode') {
$colspan = $maxdepth - $depth - 1;
$text .= '<td colspan="'.$colspan.'">'.&mt('Add subcategory:').'<input type="textbox" size="20" name="subcat_'.$name.'" value="" /></td>';
}
}
}
}
return $text;
}
sub modifiable_userdata_row {
my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref) = @_;
my ($role,$rolename,$statustype);
$role = $item;
if ($context eq 'cancreate') {
if ($item =~ /^emailusername_(.+)$/) {
$statustype = $1;
$role = 'emailusername';
if (ref($usertypes) eq 'HASH') {
if ($usertypes->{$statustype}) {
$rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});
} else {
$rolename = &mt('Data provided by user');
}
}
}
} elsif ($context eq 'selfcreate') {
if (ref($usertypes) eq 'HASH') {
$rolename = $usertypes->{$role};
} else {
$rolename = $role;
}
} else {
if ($role eq 'cr') {
$rolename = &mt('Custom role');
} else {
$rolename = &Apache::lonnet::plaintext($role);
}
}
my (@fields,%fieldtitles);
if (ref($fieldsref) eq 'ARRAY') {
@fields = @{$fieldsref};
} else {
@fields = ('lastname','firstname','middlename','generation',
'permanentemail','id');
}
if ((ref($titlesref) eq 'HASH')) {
%fieldtitles = %{$titlesref};
} else {
%fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
}
my $output;
my $css_class = $rowcount%2?' class="LC_odd_row"':'';
$output = '<tr '.$css_class.'>'.
'<td><span class="LC_nobreak">'.$rolename.'</span></td>'.
'<td class="LC_left_item" colspan="2"><table>';
my $rem;
my %checks;
if (ref($settings) eq 'HASH') {
if (ref($settings->{$context}) eq 'HASH') {
if (ref($settings->{$context}->{$role}) eq 'HASH') {
my $hashref = $settings->{$context}->{$role};
if ($role eq 'emailusername') {
if ($statustype) {
if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
$hashref = $settings->{$context}->{$role}->{$statustype};
if (ref($hashref) eq 'HASH') {
foreach my $field (@fields) {
if ($hashref->{$field}) {
$checks{$field} = $hashref->{$field};
}
}
}
}
}
} else {
if (ref($hashref) eq 'HASH') {
foreach my $field (@fields) {
if ($hashref->{$field}) {
$checks{$field} = ' checked="checked" ';
}
}
}
}
}
}
}
for (my $i=0; $i<@fields; $i++) {
my $rem = $i%($numinrow);
if ($rem == 0) {
if ($i > 0) {
$output .= '</tr>';
}
$output .= '<tr>';
}
my $check = ' ';
unless ($role eq 'emailusername') {
if (exists($checks{$fields[$i]})) {
$check = $checks{$fields[$i]}
} else {
if ($role eq 'st') {
if (ref($settings) ne 'HASH') {
$check = ' checked="checked" ';
}
}
}
}
$output .= '<td class="LC_left_item">'.
'<span class="LC_nobreak">';
if ($role eq 'emailusername') {
unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {
$checks{$fields[$i]} = 'omit';
}
foreach my $option ('required','optional','omit') {
my $checked='';
if ($checks{$fields[$i]} eq $option) {
$checked='checked="checked" ';
}
$output .= '<label>'.
'<input type="radio" name="canmodify_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.
&mt($option).'</label>'.(' ' x2);
}
$output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';
} else {
$output .= '<label>'.
'<input type="checkbox" name="canmodify_'.$role.'" '.
'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.
'</label>';
}
$output .= '</span></td>';
$rem = @fields%($numinrow);
}
my $colsleft = $numinrow - $rem;
if ($colsleft > 1 ) {
$output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
' </td>';
} elsif ($colsleft == 1) {
$output .= '<td class="LC_left_item"> </td>';
}
$output .= '</tr></table></td></tr>';
return $output;
}
sub insttypes_row {
my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rownum) = @_;
my %lt = &Apache::lonlocal::texthash (
cansearch => 'Users allowed to search',
statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
lockablenames => 'User preference to lock name',
);
my $showdom;
if ($context eq 'cansearch') {
$showdom = ' ('.$dom.')';
}
my $class = 'LC_left_item';
if ($context eq 'statustocreate') {
$class = 'LC_right_item';
}
my $css_class = ' class="LC_odd_row"';
if ($rownum ne '') {
$css_class = ($rownum%2? ' class="LC_odd_row"':'');
}
my $output = '<tr'.$css_class.'>'.
'<td>'.$lt{$context}.$showdom.
'</td><td class="'.$class.'" colspan="2"><table>';
my $rem;
if (ref($types) eq 'ARRAY') {
for (my $i=0; $i<@{$types}; $i++) {
if (defined($usertypes->{$types->[$i]})) {
my $rem = $i%($numinrow);
if ($rem == 0) {
if ($i > 0) {
$output .= '</tr>';
}
$output .= '<tr>';
}
my $check = ' ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{$context}) eq 'ARRAY') {
if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {
$check = ' checked="checked" ';
}
} elsif ($context eq 'statustocreate') {
$check = ' checked="checked" ';
}
}
$output .= '<td class="LC_left_item">'.
'<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$context.'" '.
'value="'.$types->[$i].'"'.$check.'/>'.
$usertypes->{$types->[$i]}.'</label></span></td>';
}
}
$rem = @{$types}%($numinrow);
}
my $colsleft = $numinrow - $rem;
if (($rem == 0) && (@{$types} > 0)) {
$output .= '<tr>';
}
if ($colsleft > 1) {
$output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
} else {
$output .= '<td class="LC_left_item">';
}
my $defcheck = ' ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{$context}) eq 'ARRAY') {
if (grep(/^default$/,@{$settings->{$context}})) {
$defcheck = ' checked="checked" ';
}
} elsif ($context eq 'statustocreate') {
$defcheck = ' checked="checked" ';
}
}
$output .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$context.'" '.
'value="default"'.$defcheck.'/>'.
$othertitle.'</label></span></td>'.
'</tr></table></td></tr>';
return $output;
}
sub sorted_searchtitles {
my %searchtitles = &Apache::lonlocal::texthash(
'uname' => 'username',
'lastname' => 'last name',
'lastfirst' => 'last name, first name',
);
my @titleorder = ('uname','lastname','lastfirst');
return (\%searchtitles,\@titleorder);
}
sub sorted_searchtypes {
my %srchtypes_desc = (
exact => 'is exact match',
contains => 'contains ..',
begins => 'begins with ..',
);
my @srchtypeorder = ('exact','begins','contains');
return (\%srchtypes_desc,\@srchtypeorder);
}
sub usertype_update_row {
my ($settings,$usertypes,$fieldtitles,$fields,$types,$rownums) = @_;
my $datatable;
my $numinrow = 4;
foreach my $type (@{$types}) {
if (defined($usertypes->{$type})) {
$$rownums ++;
my $css_class = $$rownums%2?' class="LC_odd_row"':'';
$datatable .= '<tr'.$css_class.'><td>'.$usertypes->{$type}.
'</td><td class="LC_left_item"><table>';
for (my $i=0; $i<@{$fields}; $i++) {
my $rem = $i%($numinrow);
if ($rem == 0) {
if ($i > 0) {
$datatable .= '</tr>';
}
$datatable .= '<tr>';
}
my $check = ' ';
if (ref($settings) eq 'HASH') {
if (ref($settings->{'fields'}) eq 'HASH') {
if (ref($settings->{'fields'}{$type}) eq 'ARRAY') {
if (grep(/^\Q$fields->[$i]\E$/,@{$settings->{'fields'}{$type}})) {
$check = ' checked="checked" ';
}
}
}
}
if ($i == @{$fields}-1) {
my $colsleft = $numinrow - $rem;
if ($colsleft > 1) {
$datatable .= '<td colspan="'.$colsleft.'">';
} else {
$datatable .= '<td>';
}
} else {
$datatable .= '<td>';
}
$datatable .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="updateable_'.$type.
'_'.$fields->[$i].'" value="1"'.$check.'/>'.
$fieldtitles->{$fields->[$i]}.'</label></span></td>';
}
$datatable .= '</tr></table></td></tr>';
}
}
return $datatable;
}
sub modify_login {
my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl,
%curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon);
%title = ( coursecatalog => 'Display course catalog',
adminmail => 'Display administrator E-mail address',
helpdesk => 'Display "Contact Helpdesk" link',
newuser => 'Link for visitors to create a user account',
loginheader => 'Log-in box header');
@offon = ('off','on');
if (ref($domconfig{login}) eq 'HASH') {
if (ref($domconfig{login}{loginvia}) eq 'HASH') {
foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) {
$curr_loginvia{$lonhost} = $domconfig{login}{loginvia}{$lonhost};
}
}
}
($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],
\%domconfig,\%loginhash);
my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
foreach my $item (@toggles) {
$loginhash{login}{$item} = $env{'form.'.$item};
}
$loginhash{login}{loginheader} = $env{'form.loginheader'};
if (ref($colchanges{'login'}) eq 'HASH') {
$colchgtext = &display_colorchgs($dom,\%colchanges,['login'],
\%loginhash);
}
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my @loginvia_attribs = ('serverpath','custompath','exempt');
if (keys(%servers) > 1) {
foreach my $lonhost (keys(%servers)) {
next if ($env{'form.'.$lonhost.'_server'} eq $lonhost);
if (ref($curr_loginvia{$lonhost}) eq 'HASH') {
if ($env{'form.'.$lonhost.'_server'} eq $curr_loginvia{$lonhost}{'server'}) {
$loginhash{login}{loginvia}{$lonhost}{'server'} = $curr_loginvia{$lonhost}{'server'};
} elsif ($curr_loginvia{$lonhost}{'server'} ne '') {
if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
$loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
$changes{'loginvia'}{$lonhost} = 1;
} else {
$loginhash{login}{loginvia}{$lonhost}{'server'} = '';
$changes{'loginvia'}{$lonhost} = 1;
}
} else {
if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
$loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
$changes{'loginvia'}{$lonhost} = 1;
}
}
if ($loginhash{login}{loginvia}{$lonhost}{'server'} eq '') {
foreach my $item (@loginvia_attribs) {
$loginhash{login}{loginvia}{$lonhost}{$item} = '';
}
} else {
foreach my $item (@loginvia_attribs) {
my $new = $env{'form.'.$lonhost.'_'.$item};
if (($item eq 'serverpath') && ($new eq 'custom')) {
$env{'form.'.$lonhost.'_custompath'} =~ s/\s+//g;
if ($env{'form.'.$lonhost.'_custompath'} eq '') {
$new = '/';
}
}
if (($item eq 'custompath') &&
($env{'form.'.$lonhost.'_serverpath'} ne 'custom')) {
$new = '';
}
if ($new ne $curr_loginvia{$lonhost}{$item}) {
$changes{'loginvia'}{$lonhost} = 1;
}
if ($item eq 'exempt') {
$new =~ s/^\s+//;
$new =~ s/\s+$//;
my @poss_ips = split(/\s*[,:]\s*/,$new);
my @okips;
foreach my $ip (@poss_ips) {
if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
if (($1 <= 255) && ($2 <= 255) && ($3 <= 255) && ($4 <= 255)) {
push(@okips,$ip);
}
}
}
if (@okips > 0) {
$new = join(',',@okips);
} else {
$new = '';
}
}
$loginhash{login}{loginvia}{$lonhost}{$item} = $new;
}
}
} else {
if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
$loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
$changes{'loginvia'}{$lonhost} = 1;
foreach my $item (@loginvia_attribs) {
my $new = $env{'form.'.$lonhost.'_'.$item};
if (($item eq 'serverpath') && ($new eq 'custom')) {
if ($env{'form.'.$lonhost.'_custompath'} eq '') {
$new = '/';
}
}
if (($item eq 'custompath') &&
($env{'form.'.$lonhost.'_serverpath'} ne 'custom')) {
$new = '';
}
$loginhash{login}{loginvia}{$lonhost}{$item} = $new;
}
}
}
}
}
my $servadm = $r->dir_config('lonAdmEMail');
my %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());
if (ref($domconfig{'login'}) eq 'HASH') {
if (ref($domconfig{'login'}{'helpurl'}) eq 'HASH') {
foreach my $lang (sort(keys(%{$domconfig{'login'}{'helpurl'}}))) {
if ($lang eq 'nolang') {
push(@currlangs,$lang);
} elsif (defined($langchoices{$lang})) {
push(@currlangs,$lang);
} else {
next;
}
}
}
}
my @delurls = &Apache::loncommon::get_env_multiple('form.loginhelpurl_del');
if (@currlangs > 0) {
foreach my $lang (@currlangs) {
if (grep(/^\Q$lang\E$/,@delurls)) {
$changes{'helpurl'}{$lang} = 1;
} elsif ($env{'form.loginhelpurl_'.$lang.'.filename'}) {
$changes{'helpurl'}{$lang} = 1;
$newfile{$lang} = $env{'form.loginhelpurl_'.$lang.'.filename'};
push(@newlangs,$lang);
} else {
$loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
}
}
}
unless (grep(/^nolang$/,@currlangs)) {
if ($env{'form.loginhelpurl_nolang.filename'}) {
$changes{'helpurl'}{'nolang'} = 1;
$newfile{'nolang'} = $env{'form.loginhelpurl_nolang.filename'};
push(@newlangs,'nolang');
}
}
if ($env{'form.loginhelpurl_add_lang'}) {
if ((defined($langchoices{$env{'form.loginhelpurl_add_lang'}})) &&
($env{'form.loginhelpurl_add_file.filename'})) {
$newfile{$env{'form.loginhelpurl_add_lang'}} = $env{'form.loginhelpurl_add_file.filename'};
$addedfile = $env{'form.loginhelpurl_add_lang'};
}
}
if ((@newlangs > 0) || ($addedfile)) {
my $error;
my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
if ($configuserok eq 'ok') {
if ($switchserver) {
$error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver);
} elsif ($author_ok eq 'ok') {
my @allnew = @newlangs;
if ($addedfile ne '') {
push(@allnew,$addedfile);
}
foreach my $lang (@allnew) {
my $formelem = 'loginhelpurl_'.$lang;
if ($lang eq $env{'form.loginhelpurl_add_lang'}) {
$formelem = 'loginhelpurl_add_file';
}
(my $result,$newurl{$lang}) = &publishlogo($r,'upload',$formelem,$dom,$confname,
"help/$lang",'','',$newfile{$lang});
if ($result eq 'ok') {
$loginhash{'login'}{'helpurl'}{$lang} = $newurl{$lang};
$changes{'helpurl'}{$lang} = 1;
} else {
my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$newfile{$lang},$result);
$errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
if ((grep(/^\Q$lang\E$/,@currlangs)) &&
(!grep(/^\Q$lang\E$/,@delurls))) {
$loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
}
}
}
} else {
$error = &mt("Upload of custom log-in help file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2]. Error was: [_3].",$confname,$dom,$author_ok);
}
} else {
$error = &mt("Upload of custom log-in help file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2]. Error was: [_3].",$confname,$dom,$configuserok);
}
if ($error) {
&Apache::lonnet::logthis($error);
$errors .= '<li><span class="LC_error">'.$error.'</span></li>';
}
}
&process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});
my $defaulthelpfile = '/adm/loginproblems.html';
my $defaulttext = &mt('Default in use');
my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,
$dom);
if ($putresult eq 'ok') {
my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
my %defaultchecked = (
'coursecatalog' => 'on',
'helpdesk' => 'on',
'adminmail' => 'off',
'newuser' => 'off',
);
if (ref($domconfig{'login'}) eq 'HASH') {
foreach my $item (@toggles) {
if ($defaultchecked{$item} eq 'on') {
if (($domconfig{'login'}{$item} eq '0') &&
($env{'form.'.$item} eq '1')) {
$changes{$item} = 1;
} elsif (($domconfig{'login'}{$item} eq '' ||
$domconfig{'login'}{$item} eq '1') &&
($env{'form.'.$item} eq '0')) {
$changes{$item} = 1;
}
} elsif ($defaultchecked{$item} eq 'off') {
if (($domconfig{'login'}{$item} eq '1') &&
($env{'form.'.$item} eq '0')) {
$changes{$item} = 1;
} elsif (($domconfig{'login'}{$item} eq '' ||
$domconfig{'login'}{$item} eq '0') &&
($env{'form.'.$item} eq '1')) {
$changes{$item} = 1;
}
}
}
}
if (keys(%changes) > 0 || $colchgtext) {
&Apache::loncommon::devalidate_domconfig_cache($dom);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domainconfig'} = 1;
}
$resulttext = &mt('Changes made:').'<ul>';
foreach my $item (sort(keys(%changes))) {
if ($item eq 'loginvia') {
if (ref($changes{$item}) eq 'HASH') {
$resulttext .= '<li>'.&mt('Log-in page availability:').'<ul>';
foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
if (defined($servers{$loginhash{login}{loginvia}{$lonhost}{'server'}})) {
if (ref($loginhash{login}{loginvia}{$lonhost}) eq 'HASH') {
my $protocol = $Apache::lonnet::protocol{$env{'form.'.$lonhost.'_server'}};
$protocol = 'http' if ($protocol ne 'https');
my $target = $protocol.'://'.$servers{$env{'form.'.$lonhost.'_server'}};
if ($loginhash{login}{loginvia}{$lonhost}{'serverpath'} eq 'custom') {
$target .= $loginhash{login}{loginvia}{$lonhost}{'custompath'};
} else {
$target .= $loginhash{login}{loginvia}{$lonhost}{'serverpath'};
}
$resulttext .= '<li>'.&mt('Server: [_1] log-in page redirects to [_2].',$servers{$lonhost},'<a href="'.$target.'">'.$target.'</a>');
if ($loginhash{login}{loginvia}{$lonhost}{'exempt'} ne '') {
$resulttext .= ' '.&mt('No redirection for clients from following IPs:').' '.$loginhash{login}{loginvia}{$lonhost}{'exempt'};
}
$resulttext .= '</li>';
} else {
$resulttext .= '<li>'.&mt('Server: [_1] has standard log-in page.',$lonhost).'</li>';
}
} else {
$resulttext .= '<li>'.&mt('Server: [_1] has standard log-in page.',$servers{$lonhost}).'</li>';
}
}
$resulttext .= '</ul></li>';
}
} elsif ($item eq 'helpurl') {
if (ref($changes{$item}) eq 'HASH') {
foreach my $lang (sort(keys(%{$changes{$item}}))) {
if (grep(/^\Q$lang\E$/,@delurls)) {
my ($chg,$link);
$link = &Apache::loncommon::modal_link($defaulthelpfile,$defaulttext,600,500);
if ($lang eq 'nolang') {
$chg = &mt('custom log-in help file removed for no preferred language; [_1]',$link);
} else {
$chg = &mt('custom log-in help file removed for specific language: [_1]; [_2]',$langchoices{$lang},$link);
}
$resulttext .= '<li>'.$chg.'</li>';
} else {
my $chg;
if ($lang eq 'nolang') {
$chg = &mt('custom log-in help file for no preferred language');
} else {
$chg = &mt('custom log-in help file for specific language: [_1]',$langchoices{$lang});
}
$resulttext .= '<li>'.&Apache::loncommon::modal_link(
$loginhash{'login'}{'helpurl'}{$lang}.
'?inhibitmenu=yes',$chg,600,500).
'</li>';
}
}
}
} elsif ($item eq 'captcha') {
if (ref($loginhash{'login'}) eq 'HASH') {
my $chgtxt;
if ($loginhash{'login'}{$item} eq 'notused') {
$chgtxt .= &mt('No CAPTCHA validation in use for helpdesk form.');
} else {
my %captchas = &captcha_phrases();
if ($captchas{$loginhash{'login'}{$item}}) {
$chgtxt .= &mt("Validation for helpdesk form set to $captchas{$loginhash{'login'}{$item}}.");
} else {
$chgtxt .= &mt('Validation for helpdesk form set to unknown type.');
}
}
$resulttext .= '<li>'.$chgtxt.'</li>';
}
} elsif ($item eq 'recaptchakeys') {
if (ref($loginhash{'login'}) eq 'HASH') {
my ($privkey,$pubkey);
if (ref($loginhash{'login'}{$item}) eq 'HASH') {
$pubkey = $loginhash{'login'}{$item}{'public'};
$privkey = $loginhash{'login'}{$item}{'private'};
}
my $chgtxt .= &mt('ReCAPTCHA keys changes').'<ul>';
if (!$pubkey) {
$chgtxt .= '<li>'.&mt('Public key deleted').'</li>';
} else {
$chgtxt .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';
}
if (!$privkey) {
$chgtxt .= '<li>'.&mt('Private key deleted').'</li>';
} else {
$chgtxt .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';
}
$chgtxt .= '</ul>';
$resulttext .= '<li>'.$chgtxt.'</li>';
}
} else {
$resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';
}
}
$resulttext .= $colchgtext.'</ul>';
} else {
$resulttext = &mt('No changes made to log-in page settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
if ($errors) {
$resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
$errors.'</ul>';
}
return $resulttext;
}
sub color_font_choices {
my %choices =
&Apache::lonlocal::texthash (
img => "Header",
bgs => "Background colors",
links => "Link colors",
images => "Images",
font => "Font color",
fontmenu => "Font menu",
pgbg => "Page",
tabbg => "Header",
sidebg => "Border",
link => "Link",
alink => "Active link",
vlink => "Visited link",
);
return %choices;
}
sub modify_rolecolors {
my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_;
my ($resulttext,%rolehash);
$rolehash{'rolecolors'} = {};
if (ref($domconfig{'rolecolors'}) ne 'HASH') {
if ($domconfig{'rolecolors'} eq '') {
$domconfig{'rolecolors'} = {};
}
}
my ($errors,%changes) = &modify_colors($r,$dom,$confname,$roles,
$domconfig{'rolecolors'},$rolehash{'rolecolors'});
my $putresult = &Apache::lonnet::put_dom('configuration',\%rolehash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
&Apache::loncommon::devalidate_domconfig_cache($dom);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domainconfig'} = 1;
}
$resulttext = &display_colorchgs($dom,\%changes,$roles,
$rolehash{'rolecolors'});
} else {
$resulttext = &mt('No changes made to default color schemes');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
if ($errors) {
$resulttext .= &mt('The following errors occurred: ').'<ul>'.
$errors.'</ul>';
}
return $resulttext;
}
sub modify_colors {
my ($r,$dom,$confname,$roles,$domconfig,$confhash) = @_;
my (%changes,%choices);
my @bgs;
my @links = ('link','alink','vlink');
my @logintext;
my @images;
my $servadm = $r->dir_config('lonAdmEMail');
my $errors;
my %defaults;
foreach my $role (@{$roles}) {
if ($role eq 'login') {
%choices = &login_choices();
@logintext = ('textcol','bgcol');
} else {
%choices = &color_font_choices();
}
if ($role eq 'login') {
@images = ('img','logo','domlogo','login');
@bgs = ('pgbg','mainbg','sidebg');
} else {
@images = ('img');
@bgs = ('pgbg','tabbg','sidebg');
}
my %defaults = &role_defaults($role,\@bgs,\@links,\@images,\@logintext);
unless ($env{'form.'.$role.'_font'} eq $defaults{'font'}) {
$confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};
}
if ($role eq 'login') {
foreach my $item (@logintext) {
unless ($env{'form.'.$role.'_'.$item} eq $defaults{'logintext'}{$item}) {
$confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
}
}
} else {
unless($env{'form.'.$role.'_fontmenu'} eq $defaults{'fontmenu'}) {
$confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};
}
}
foreach my $item (@bgs) {
unless ($env{'form.'.$role.'_'.$item} eq $defaults{'bgs'}{$item} ) {
$confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
}
}
foreach my $item (@links) {
unless ($env{'form.'.$role.'_'.$item} eq $defaults{'links'}{$item}) {
$confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
}
}
my ($configuserok,$author_ok,$switchserver) =
&config_check($dom,$confname,$servadm);
my ($width,$height) = &thumb_dimensions();
if (ref($domconfig->{$role}) ne 'HASH') {
$domconfig->{$role} = {};
}
foreach my $img (@images) {
if (($role eq 'login') && (($img eq 'img') || ($img eq 'logo'))) {
if (defined($env{'form.login_showlogo_'.$img})) {
$confhash->{$role}{'showlogo'}{$img} = 1;
} else {
$confhash->{$role}{'showlogo'}{$img} = 0;
}
}
if ( ! $env{'form.'.$role.'_'.$img.'.filename'}
&& !defined($domconfig->{$role}{$img})
&& !$env{'form.'.$role.'_del_'.$img}
&& $env{'form.'.$role.'_import_'.$img}) {
# import the old configured image from the .tab setting
# if they haven't provided a new one
$domconfig->{$role}{$img} =
$env{'form.'.$role.'_import_'.$img};
}
if ($env{'form.'.$role.'_'.$img.'.filename'} ne '') {
my $error;
if ($configuserok eq 'ok') {
if ($switchserver) {
$error = &mt("Upload of [_1] image for $role page(s) is not permitted to this server: [_2]",$choices{$img},$switchserver);
} else {
if ($author_ok eq 'ok') {
my ($result,$logourl) =
&publishlogo($r,'upload',$role.'_'.$img,
$dom,$confname,$img,$width,$height);
if ($result eq 'ok') {
$confhash->{$role}{$img} = $logourl;
$changes{$role}{'images'}{$img} = 1;
} else {
$error = &mt("Upload of [_1] image for $role page(s) failed because an error occurred publishing the file in RES space. Error was: [_2].",$choices{img},$result);
}
} else {
$error = &mt("Upload of [_1] image for $role page(s) failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$author_ok);
}
}
} else {
$error = &mt("Upload of [_1] image for $role page(s) failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$configuserok);
}
if ($error) {
&Apache::lonnet::logthis($error);
$errors .= '<li><span class="LC_error">'.$error.'</span></li>';
}
} elsif ($domconfig->{$role}{$img} ne '') {
if ($domconfig->{$role}{$img} !~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) {
my $error;
if ($configuserok eq 'ok') {
# is confname an author?
if ($switchserver eq '') {
if ($author_ok eq 'ok') {
my ($result,$logourl) =
&publishlogo($r,'copy',$domconfig->{$role}{$img},
$dom,$confname,$img,$width,$height);
if ($result eq 'ok') {
$confhash->{$role}{$img} = $logourl;
$changes{$role}{'images'}{$img} = 1;
}
}
}
}
}
}
}
if (ref($domconfig) eq 'HASH') {
if (ref($domconfig->{$role}) eq 'HASH') {
foreach my $img (@images) {
if ($domconfig->{$role}{$img} ne '') {
if ($env{'form.'.$role.'_del_'.$img}) {
$confhash->{$role}{$img} = '';
$changes{$role}{'images'}{$img} = 1;
} else {
if ($confhash->{$role}{$img} eq '') {
$confhash->{$role}{$img} = $domconfig->{$role}{$img};
}
}
} else {
if ($env{'form.'.$role.'_del_'.$img}) {
$confhash->{$role}{$img} = '';
$changes{$role}{'images'}{$img} = 1;
}
}
if (($role eq 'login') && (($img eq 'logo') || ($img eq 'img'))) {
if (ref($domconfig->{'login'}{'showlogo'}) eq 'HASH') {
if ($confhash->{$role}{'showlogo'}{$img} ne
$domconfig->{$role}{'showlogo'}{$img}) {
$changes{$role}{'showlogo'}{$img} = 1;
}
} else {
if ($confhash->{$role}{'showlogo'}{$img} == 0) {
$changes{$role}{'showlogo'}{$img} = 1;
}
}
}
}
if ($domconfig->{$role}{'font'} ne '') {
if ($confhash->{$role}{'font'} ne $domconfig->{$role}{'font'}) {
$changes{$role}{'font'} = 1;
}
} else {
if ($confhash->{$role}{'font'}) {
$changes{$role}{'font'} = 1;
}
}
if ($role ne 'login') {
if ($domconfig->{$role}{'fontmenu'} ne '') {
if ($confhash->{$role}{'fontmenu'} ne $domconfig->{$role}{'fontmenu'}) {
$changes{$role}{'fontmenu'} = 1;
}
} else {
if ($confhash->{$role}{'fontmenu'}) {
$changes{$role}{'fontmenu'} = 1;
}
}
}
foreach my $item (@bgs) {
if ($domconfig->{$role}{$item} ne '') {
if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
$changes{$role}{'bgs'}{$item} = 1;
}
} else {
if ($confhash->{$role}{$item}) {
$changes{$role}{'bgs'}{$item} = 1;
}
}
}
foreach my $item (@links) {
if ($domconfig->{$role}{$item} ne '') {
if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
$changes{$role}{'links'}{$item} = 1;
}
} else {
if ($confhash->{$role}{$item}) {
$changes{$role}{'links'}{$item} = 1;
}
}
}
foreach my $item (@logintext) {
if ($domconfig->{$role}{$item} ne '') {
if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
$changes{$role}{'logintext'}{$item} = 1;
}
} else {
if ($confhash->{$role}{$item}) {
$changes{$role}{'logintext'}{$item} = 1;
}
}
}
} else {
&default_change_checker($role,\@images,\@links,\@bgs,
\@logintext,$confhash,\%changes);
}
} else {
&default_change_checker($role,\@images,\@links,\@bgs,
\@logintext,$confhash,\%changes);
}
}
return ($errors,%changes);
}
sub config_check {
my ($dom,$confname,$servadm) = @_;
my ($configuserok,$author_ok,$switchserver,%currroles);
my $uhome = &Apache::lonnet::homeserver($confname,$dom,1);
($configuserok,%currroles) = &check_configuser($uhome,$dom,
$confname,$servadm);
if ($configuserok eq 'ok') {
$switchserver = &check_switchserver($dom,$confname);
if ($switchserver eq '') {
$author_ok = &check_authorstatus($dom,$confname,%currroles);
}
}
return ($configuserok,$author_ok,$switchserver);
}
sub default_change_checker {
my ($role,$images,$links,$bgs,$logintext,$confhash,$changes) = @_;
foreach my $item (@{$links}) {
if ($confhash->{$role}{$item}) {
$changes->{$role}{'links'}{$item} = 1;
}
}
foreach my $item (@{$bgs}) {
if ($confhash->{$role}{$item}) {
$changes->{$role}{'bgs'}{$item} = 1;
}
}
foreach my $item (@{$logintext}) {
if ($confhash->{$role}{$item}) {
$changes->{$role}{'logintext'}{$item} = 1;
}
}
foreach my $img (@{$images}) {
if ($env{'form.'.$role.'_del_'.$img}) {
$confhash->{$role}{$img} = '';
$changes->{$role}{'images'}{$img} = 1;
}
if ($role eq 'login') {
if ($confhash->{$role}{'showlogo'}{$img} == 0) {
$changes->{$role}{'showlogo'}{$img} = 1;
}
}
}
if ($confhash->{$role}{'font'}) {
$changes->{$role}{'font'} = 1;
}
}
sub display_colorchgs {
my ($dom,$changes,$roles,$confhash) = @_;
my (%choices,$resulttext);
if (!grep(/^login$/,@{$roles})) {
$resulttext = &mt('Changes made:').'<br />';
}
foreach my $role (@{$roles}) {
if ($role eq 'login') {
%choices = &login_choices();
} else {
%choices = &color_font_choices();
}
if (ref($changes->{$role}) eq 'HASH') {
if ($role ne 'login') {
$resulttext .= '<h4>'.&mt($role).'</h4>';
}
foreach my $key (sort(keys(%{$changes->{$role}}))) {
if ($role ne 'login') {
$resulttext .= '<ul>';
}
if (ref($changes->{$role}{$key}) eq 'HASH') {
if ($role ne 'login') {
$resulttext .= '<li>'.&mt($choices{$key}).':<ul>';
}
foreach my $item (sort(keys(%{$changes->{$role}{$key}}))) {
if (($role eq 'login') && ($key eq 'showlogo')) {
if ($confhash->{$role}{$key}{$item}) {
$resulttext .= '<li>'.&mt("$choices{$item} set to be displayed").'</li>';
} else {
$resulttext .= '<li>'.&mt("$choices{$item} set to not be displayed").'</li>';
}
} elsif ($confhash->{$role}{$item} eq '') {
$resulttext .= '<li>'.&mt("$choices{$item} set to default").'</li>';
} else {
my $newitem = $confhash->{$role}{$item};
if ($key eq 'images') {
$newitem = '<img src="'.$confhash->{$role}{$item}.'" alt="'.$choices{$item}.'" valign="bottom" />';
}
$resulttext .= '<li>'.&mt("$choices{$item} set to [_1]",$newitem).'</li>';
}
}
if ($role ne 'login') {
$resulttext .= '</ul></li>';
}
} else {
if ($confhash->{$role}{$key} eq '') {
$resulttext .= '<li>'.&mt("$choices{$key} set to default").'</li>';
} else {
$resulttext .= '<li>'.&mt("$choices{$key} set to [_1]",$confhash->{$role}{$key}).'</li>';
}
}
if ($role ne 'login') {
$resulttext .= '</ul>';
}
}
}
}
return $resulttext;
}
sub thumb_dimensions {
return ('200','50');
}
sub check_dimensions {
my ($inputfile) = @_;
my ($fullwidth,$fullheight);
if ($inputfile =~ m|^[/\w.\-]+$|) {
if (open(PIPE,"identify $inputfile 2>&1 |")) {
my $imageinfo = <PIPE>;
if (!close(PIPE)) {
&Apache::lonnet::logthis("Failed to close PIPE opened to retrieve image information for $inputfile");
}
chomp($imageinfo);
my ($fullsize) =
($imageinfo =~ /^\Q$inputfile\E\s+\w+\s+(\d+x\d+)/);
if ($fullsize) {
($fullwidth,$fullheight) = split(/x/,$fullsize);
}
}
}
return ($fullwidth,$fullheight);
}
sub check_configuser {
my ($uhome,$dom,$confname,$servadm) = @_;
my ($configuserok,%currroles);
if ($uhome eq 'no_host') {
srand( time() ^ ($$ + ($$ << 15)) ); # Seed rand.
my $configpass = &LONCAPA::Enrollment::create_password();
$configuserok =
&Apache::lonnet::modifyuser($dom,$confname,'','internal',
$configpass,'','','','','',undef,$servadm);
} else {
$configuserok = 'ok';
%currroles =
&Apache::lonnet::get_my_roles($confname,$dom,'userroles');
}
return ($configuserok,%currroles);
}
sub check_authorstatus {
my ($dom,$confname,%currroles) = @_;
my $author_ok;
if (!$currroles{':'.$dom.':au'}) {
my $start = time;
my $end = 0;
$author_ok =
&Apache::lonnet::assignrole($dom,$confname,'/'.$dom.'/',
'au',$end,$start,'','','domconfig');
} else {
$author_ok = 'ok';
}
return $author_ok;
}
sub publishlogo {
my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_;
my ($output,$fname,$logourl);
if ($action eq 'upload') {
$fname=$env{'form.'.$formname.'.filename'};
chop($env{'form.'.$formname});
} else {
($fname) = ($formname =~ /([^\/]+)$/);
}
if ($savefileas ne '') {
$fname = $savefileas;
}
$fname=&Apache::lonnet::clean_filename($fname);
# See if there is anything left
unless ($fname) { return ('error: no uploaded file'); }
$fname="$subdir/$fname";
my $docroot=$r->dir_config('lonDocRoot');
my $filepath="$docroot/priv";
my $relpath = "$dom/$confname";
my ($fnamepath,$file,$fetchthumb);
$file=$fname;
if ($fname=~m|/|) {
($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);
}
my @parts=split(/\//,"$filepath/$relpath/$fnamepath");
my $count;
for ($count=5;$count<=$#parts;$count++) {
$filepath.="/$parts[$count]";
if ((-e $filepath)!=1) {
mkdir($filepath,02770);
}
}
# Check for bad extension and disallow upload
if ($file=~/\.(\w+)$/ &&
(&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
$output =
&mt('Invalid file extension ([_1]) - reserved for internal use.',$1);
} elsif ($file=~/\.(\w+)$/ &&
!defined(&Apache::loncommon::fileembstyle($1))) {
$output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);
} elsif ($file=~/\.(\d+)\.(\w+)$/) {
$output = &mt('Filename not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);
} elsif (-d "$filepath/$file") {
$output = &mt('Filename is a directory name - rename the file and re-upload');
} else {
my $source = $filepath.'/'.$file;
my $logfile;
if (!open($logfile,">>$source".'.log')) {
return (&mt('No write permission to Authoring Space'));
}
print $logfile
"\n================= Publish ".localtime()." ================\n".
$env{'user.name'}.':'.$env{'user.domain'}."\n";
# Save the file
if (!open(FH,'>'.$source)) {
&Apache::lonnet::logthis('Failed to create '.$source);
return (&mt('Failed to create file'));
}
if ($action eq 'upload') {
if (!print FH ($env{'form.'.$formname})) {
&Apache::lonnet::logthis('Failed to write to '.$source);
return (&mt('Failed to write file'));
}
} else {
my $original = &Apache::lonnet::filelocation('',$formname);
if(!copy($original,$source)) {
&Apache::lonnet::logthis('Failed to copy '.$original.' to '.$source);
return (&mt('Failed to write file'));
}
}
close(FH);
chmod(0660, $source); # Permissions to rw-rw---.
my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath;
my $copyfile=$targetdir.'/'.$file;
my @parts=split(/\//,$targetdir);
my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";
for (my $count=5;$count<=$#parts;$count++) {
$path.="/$parts[$count]";
if (!-e $path) {
print $logfile "\nCreating directory ".$path;
mkdir($path,02770);
}
}
my $versionresult;
if (-e $copyfile) {
$versionresult = &logo_versioning($targetdir,$file,$logfile);
} else {
$versionresult = 'ok';
}
if ($versionresult eq 'ok') {
if (copy($source,$copyfile)) {
print $logfile "\nCopied original source to ".$copyfile."\n";
$output = 'ok';
$logourl = '/res/'.$dom.'/'.$confname.'/'.$fname;
push(@{$modified_urls},[$copyfile,$source]);
my $metaoutput =
&write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile);
unless ($registered_cleanup) {
my $handlers = $r->get_handlers('PerlCleanupHandler');
$r->set_handlers('PerlCleanupHandler' => [\¬ifysubscribed,@{$handlers}]);
$registered_cleanup=1;
}
} else {
print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";
$output = &mt('Failed to copy file to RES space').", $!";
}
if (($thumbwidth =~ /^\d+$/) && ($thumbheight =~ /^\d+$/)) {
my $inputfile = $filepath.'/'.$file;
my $outfile = $filepath.'/'.'tn-'.$file;
my ($fullwidth,$fullheight) = &check_dimensions($inputfile);
if ($fullwidth ne '' && $fullheight ne '') {
if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) {
my $thumbsize = $thumbwidth.'x'.$thumbheight;
system("convert -sample $thumbsize $inputfile $outfile");
chmod(0660, $filepath.'/tn-'.$file);
if (-e $outfile) {
my $copyfile=$targetdir.'/tn-'.$file;
if (copy($outfile,$copyfile)) {
print $logfile "\nCopied source to ".$copyfile."\n";
my $thumb_metaoutput =
&write_metadata($dom,$confname,$formname,
$targetdir,'tn-'.$file,$logfile);
push(@{$modified_urls},[$copyfile,$outfile]);
unless ($registered_cleanup) {
my $handlers = $r->get_handlers('PerlCleanupHandler');
$r->set_handlers('PerlCleanupHandler' => [\¬ifysubscribed,@{$handlers}]);
$registered_cleanup=1;
}
} else {
print $logfile "\nUnable to write ".$copyfile.
':'.$!."\n";
}
}
}
}
}
} else {
$output = $versionresult;
}
}
return ($output,$logourl);
}
sub logo_versioning {
my ($targetdir,$file,$logfile) = @_;
my $target = $targetdir.'/'.$file;
my ($maxversion,$fn,$extn,$output);
$maxversion = 0;
if ($file =~ /^(.+)\.(\w+)$/) {
$fn=$1;
$extn=$2;
}
opendir(DIR,$targetdir);
while (my $filename=readdir(DIR)) {
if ($filename=~/\Q$fn\E\.(\d+)\.\Q$extn\E$/) {
$maxversion=($1>$maxversion)?$1:$maxversion;
}
}
$maxversion++;
print $logfile "\nCreating old version ".$maxversion."\n";
my $copyfile=$targetdir.'/'.$fn.'.'.$maxversion.'.'.$extn;
if (copy($target,$copyfile)) {
print $logfile "Copied old target to ".$copyfile."\n";
$copyfile=$copyfile.'.meta';
if (copy($target.'.meta',$copyfile)) {
print $logfile "Copied old target metadata to ".$copyfile."\n";
$output = 'ok';
} else {
print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n";
$output = &mt('Failed to copy old meta').", $!, ";
}
} else {
print $logfile "Unable to write ".$copyfile.':'.$!."\n";
$output = &mt('Failed to copy old target').", $!, ";
}
return $output;
}
sub write_metadata {
my ($dom,$confname,$formname,$targetdir,$file,$logfile) = @_;
my (%metadatafields,%metadatakeys,$output);
$metadatafields{'title'}=$formname;
$metadatafields{'creationdate'}=time;
$metadatafields{'lastrevisiondate'}=time;
$metadatafields{'copyright'}='public';
$metadatafields{'modifyinguser'}=$env{'user.name'}.':'.
$env{'user.domain'};
$metadatafields{'authorspace'}=$confname.':'.$dom;
$metadatafields{'domain'}=$dom;
{
print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;
my $mfh;
if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {
foreach (sort(keys(%metadatafields))) {
unless ($_=~/\./) {
my $unikey=$_;
$unikey=~/^([A-Za-z]+)/;
my $tag=$1;
$tag=~tr/A-Z/a-z/;
print $mfh "\n\<$tag";
foreach (split(/\,/,$metadatakeys{$unikey})) {
my $value=$metadatafields{$unikey.'.'.$_};
$value=~s/\"/\'\'/g;
print $mfh ' '.$_.'="'.$value.'"';
}
print $mfh '>'.
&HTML::Entities::encode($metadatafields{$unikey},'<>&"')
.'</'.$tag.'>';
}
}
$output = 'ok';
print $logfile "\nWrote metadata";
close($mfh);
} else {
print $logfile "\nFailed to open metadata file";
$output = &mt('Could not write metadata');
}
}
return $output;
}
sub notifysubscribed {
foreach my $targetsource (@{$modified_urls}){
next unless (ref($targetsource) eq 'ARRAY');
my ($target,$source)=@{$targetsource};
if ($source ne '') {
if (open(my $logfh,'>>'.$source.'.log')) {
print $logfh "\nCleanup phase: Notifications\n";
my @subscribed=&subscribed_hosts($target);
foreach my $subhost (@subscribed) {
print $logfh "\nNotifying host ".$subhost.':';
my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
print $logfh $reply;
}
my @subscribedmeta=&subscribed_hosts("$target.meta");
foreach my $subhost (@subscribedmeta) {
print $logfh "\nNotifying host for metadata only ".$subhost.':';
my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
$subhost);
print $logfh $reply;
}
print $logfh "\n============ Done ============\n";
close($logfh);
}
}
}
return OK;
}
sub subscribed_hosts {
my ($target) = @_;
my @subscribed;
if (open(my $fh,"<$target.subscription")) {
while (my $subline=<$fh>) {
if ($subline =~ /^($match_lonid):/) {
my $host = $1;
if ($host ne $Apache::lonnet::perlvar{'lonHostID'}) {
unless (grep(/^\Q$host\E$/,@subscribed)) {
push(@subscribed,$host);
}
}
}
}
}
return @subscribed;
}
sub check_switchserver {
my ($dom,$confname) = @_;
my ($allowed,$switchserver);
my $home = &Apache::lonnet::homeserver($confname,$dom);
if ($home eq 'no_host') {
$home = &Apache::lonnet::domain($dom,'primary');
}
my @ids=&Apache::lonnet::current_machine_ids();
foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
if (!$allowed) {
$switchserver='<a href="/adm/switchserver?otherserver='.$home.'&role=dc./'.$dom.'/&destinationurl=/adm/domainprefs">'.&mt('Switch Server').'</a>';
}
return $switchserver;
}
sub modify_quotas {
my ($r,$dom,$action,$lastactref,%domconfig) = @_;
my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,
%limithash,$toolregexp,%conditions,$resulttext,%changes,$confname,$configuserok,
$author_ok,$switchserver,$errors);
if ($action eq 'quotas') {
$context = 'tools';
} else {
$context = $action;
}
if ($context eq 'requestcourses') {
@usertools = ('official','unofficial','community','textbook');
@options =('norequest','approval','validate','autolimit');
%validations = &Apache::lonnet::auto_courserequest_checks($dom);
%titles = &courserequest_titles();
$toolregexp = join('|',@usertools);
%conditions = &courserequest_conditions();
$confname = $dom.'-domainconfig';
my $servadm = $r->dir_config('lonAdmEMail');
($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
} elsif ($context eq 'requestauthor') {
@usertools = ('author');
%titles = &authorrequest_titles();
} else {
@usertools = ('aboutme','blog','webdav','portfolio');
%titles = &tool_titles();
}
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
foreach my $key (keys(%env)) {
if ($context eq 'requestcourses') {
if ($key =~ /^form\.crsreq_($toolregexp)_(.+)$/) {
my $item = $1;
my $type = $2;
if ($type =~ /^limit_(.+)/) {
$limithash{$item}{$1} = $env{$key};
} else {
$confhash{$item}{$type} = $env{$key};
}
}
} elsif ($context eq 'requestauthor') {
if ($key =~ /^\Qform.authorreq_\E(.+)$/) {
$confhash{$1} = $env{$key};
}
} else {
if ($key =~ /^form\.quota_(.+)$/) {
$confhash{'defaultquota'}{$1} = $env{$key};
} elsif ($key =~ /^form\.authorquota_(.+)$/) {
$confhash{'authorquota'}{$1} = $env{$key};
} elsif ($key =~ /^form\.\Q$context\E_(.+)$/) {
@{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);
}
}
}
if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
@approvalnotify = sort(@approvalnotify);
$confhash{'notify'}{'approval'} = join(',',@approvalnotify);
my @crstypes = ('official','unofficial','community','textbook');
my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
foreach my $type (@hasuniquecode) {
if (grep(/^\Q$type\E$/,@crstypes)) {
$confhash{'uniquecode'}{$type} = 1;
}
}
my ($newbook,@allpos);
if ($context eq 'requestcourses') {
if ($env{'form.addbook'}) {
if (($env{'form.addbook_cnum'} =~ /^$match_courseid$/) &&
($env{'form.addbook_cdom'} =~ /^$match_domain$/)) {
if (&Apache::lonnet::homeserver($env{'form.addbook_cnum'},
$env{'form.addbook_cdom'}) eq 'no_host') {
$errors .= '<li><span class="LC_error">'.&mt('Invalid LON-CAPA course for textbook').
'</span></li>';
} else {
$newbook = $env{'form.addbook_cdom'}.'_'.$env{'form.addbook_cnum'};
my $position = $env{'form.addbook_pos'};
$position =~ s/\D+//g;
if ($position ne '') {
$allpos[$position] = $newbook;
}
}
} else {
$errors .= '<li><span class="LC_error">'.&mt('Invalid LON-CAPA course for textbook').
'</span></li>';
}
}
}
if (ref($domconfig{$action}) eq 'HASH') {
if (ref($domconfig{$action}{'notify'}) eq 'HASH') {
if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {
$changes{'notify'}{'approval'} = 1;
}
} else {
if ($confhash{'notify'}{'approval'}) {
$changes{'notify'}{'approval'} = 1;
}
}
if (ref($domconfig{$action}{'uniquecode'}) eq 'HASH') {
if (ref($confhash{'uniquecode'}) eq 'HASH') {
foreach my $crstype (keys(%{$domconfig{$action}{'uniquecode'}})) {
unless ($confhash{'uniquecode'}{$crstype}) {
$changes{'uniquecode'} = 1;
}
}
unless ($changes{'uniquecode'}) {
foreach my $crstype (keys(%{$confhash{'uniquecode'}})) {
unless ($domconfig{$action}{'uniquecode'}{$crstype}) {
$changes{'uniquecode'} = 1;
}
}
}
} else {
$changes{'uniquecode'} = 1;
}
} elsif (ref($confhash{'uniquecode'}) eq 'HASH') {
$changes{'uniquecode'} = 1;
}
if ($context eq 'requestcourses') {
if (ref($domconfig{$action}{'textbooks'}) eq 'HASH') {
my %deletions;
my @todelete = &Apache::loncommon::get_env_multiple('form.book_del');
if (@todelete) {
map { $deletions{$_} = 1; } @todelete;
}
my %imgdeletions;
my @todeleteimages = &Apache::loncommon::get_env_multiple('form.book_image_del');
if (@todeleteimages) {
map { $imgdeletions{$_} = 1; } @todeleteimages;
}
my $maxnum = $env{'form.book_maxnum'};
for (my $i=0; $i<=$maxnum; $i++) {
my $key = $env{'form.book_id_'.$i};
if (ref($domconfig{$action}{'textbooks'}{$key}) eq 'HASH') {
if ($deletions{$key}) {
if ($domconfig{$action}{'textbooks'}{$key}{'image'}) {
#FIXME need to obsolete item in RES space
}
next;
} else {
my $newpos = $env{'form.'.$key};
$newpos =~ s/\D+//g;
foreach my $item ('subject','title','author') {
$confhash{'textbooks'}{$key}{$item} = $env{'form.book_'.$item.'_'.$i};
if ($domconfig{$action}{'textbooks'}{$key}{$item} ne $confhash{'textbooks'}{$key}{$item}) {
$changes{'textbooks'}{$key} = 1;
}
}
$allpos[$newpos] = $key;
}
if ($imgdeletions{$key}) {
$changes{'textbooks'}{$key} = 1;
#FIXME need to obsolete item in RES space
} elsif ($env{'form.book_image_'.$i.'.filename'}) {
my ($cdom,$cnum) = split(/_/,$key);
my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,'book_image_'.$i,
$cdom,$cnum,$configuserok,
$switchserver,$author_ok);
if ($imgurl) {
$confhash{'textbooks'}{$key}{'image'} = $imgurl;
$changes{'textbooks'}{$key} = 1;
}
if ($error) {
&Apache::lonnet::logthis($error);
$errors .= '<li><span class="LC_error">'.$error.'</span></li>';
}
} elsif ($domconfig{$action}{'textbooks'}{$key}{'image'}) {
$confhash{'textbooks'}{$key}{'image'} =
$domconfig{$action}{'textbooks'}{$key}{'image'};
}
}
}
}
}
} else {
if ($confhash{'notify'}{'approval'}) {
$changes{'notify'}{'approval'} = 1;
}
if (ref($confhash{'uniquecode'} eq 'HASH')) {
$changes{'uniquecode'} = 1;
}
}
if ($context eq 'requestcourses') {
if ($newbook) {
$changes{'textbooks'}{$newbook} = 1;
foreach my $item ('subject','title','author') {
$env{'form.addbook_'.$item} =~ s/(`)/'/g;
if ($env{'form.addbook_'.$item}) {
$confhash{'textbooks'}{$newbook}{$item} = $env{'form.addbook_'.$item};
}
}
if ($env{'form.addbook_image.filename'} ne '') {
my ($cdom,$cnum) = split(/_/,$newbook);
my ($imageurl,$error) =
&process_textbook_image($r,$dom,$confname,'addbook_image',$cdom,$cnum,$configuserok,
$switchserver,$author_ok);
if ($imageurl) {
$confhash{'textbooks'}{$newbook}{'image'} = $imageurl;
}
if ($error) {
&Apache::lonnet::logthis($error);
$errors .= '<li><span class="LC_error">'.$error.'</span></li>';
}
}
}
if (@allpos > 0) {
my $idx = 0;
foreach my $item (@allpos) {
if ($item ne '') {
$confhash{'textbooks'}{$item}{'order'} = $idx;
if (ref($domconfig{$action}) eq 'HASH') {
if (ref($domconfig{$action}{'textbooks'}) eq 'HASH') {
if (ref($domconfig{$action}{'textbooks'}{$item}) eq 'HASH') {
if ($domconfig{$action}{'textbooks'}{$item}{'order'} ne $idx) {
$changes{'textbooks'}{$item} = 1;
}
}
}
}
$idx ++;
}
}
}
}
} else {
$confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};
$confhash{'authorquota'}{'default'} = $env{'form.authorquota'};
}
foreach my $item (@usertools) {
foreach my $type (@{$types},'default','_LC_adv') {
my $unset;
if ($context eq 'requestcourses') {
$unset = '0';
if ($type eq '_LC_adv') {
$unset = '';
}
if ($confhash{$item}{$type} eq 'autolimit') {
$confhash{$item}{$type} .= '=';
unless ($limithash{$item}{$type} =~ /\D/) {
$confhash{$item}{$type} .= $limithash{$item}{$type};
}
}
} elsif ($context eq 'requestauthor') {
$unset = '0';
if ($type eq '_LC_adv') {
$unset = '';
}
} else {
if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {
$confhash{$item}{$type} = 1;
} else {
$confhash{$item}{$type} = 0;
}
}
if (ref($domconfig{$action}) eq 'HASH') {
if ($action eq 'requestauthor') {
if ($domconfig{$action}{$type} ne $confhash{$type}) {
$changes{$type} = 1;
}
} elsif (ref($domconfig{$action}{$item}) eq 'HASH') {
if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {
$changes{$item}{$type} = 1;
}
} else {
if ($context eq 'requestcourses') {
if ($confhash{$item}{$type} ne $unset) {
$changes{$item}{$type} = 1;
}
} else {
if (!$confhash{$item}{$type}) {
$changes{$item}{$type} = 1;
}
}
}
} else {
if ($context eq 'requestcourses') {
if ($confhash{$item}{$type} ne $unset) {
$changes{$item}{$type} = 1;
}
} elsif ($context eq 'requestauthor') {
if ($confhash{$type} ne $unset) {
$changes{$type} = 1;
}
} else {
if (!$confhash{$item}{$type}) {
$changes{$item}{$type} = 1;
}
}
}
}
}
unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
if (ref($domconfig{'quotas'}) eq 'HASH') {
if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {
if (exists($confhash{'defaultquota'}{$key})) {
if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{'defaultquota'}{$key}) {
$changes{'defaultquota'}{$key} = 1;
}
} else {
$confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{'defaultquota'}{$key};
}
}
} else {
foreach my $key (keys(%{$domconfig{'quotas'}})) {
if (exists($confhash{'defaultquota'}{$key})) {
if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{$key}) {
$changes{'defaultquota'}{$key} = 1;
}
} else {
$confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{$key};
}
}
}
if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'quotas'}{'authorquota'}})) {
if (exists($confhash{'authorquota'}{$key})) {
if ($confhash{'authorquota'}{$key} ne $domconfig{'quotas'}{'authorquota'}{$key}) {
$changes{'authorquota'}{$key} = 1;
}
} else {
$confhash{'authorquota'}{$key} = $domconfig{'quotas'}{'authorquota'}{$key};
}
}
}
}
if (ref($confhash{'defaultquota'}) eq 'HASH') {
foreach my $key (keys(%{$confhash{'defaultquota'}})) {
if (ref($domconfig{'quotas'}) eq 'HASH') {
if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
if (!exists($domconfig{'quotas'}{'defaultquota'}{$key})) {
$changes{'defaultquota'}{$key} = 1;
}
} else {
if (!exists($domconfig{'quotas'}{$key})) {
$changes{'defaultquota'}{$key} = 1;
}
}
} else {
$changes{'defaultquota'}{$key} = 1;
}
}
}
if (ref($confhash{'authorquota'}) eq 'HASH') {
foreach my $key (keys(%{$confhash{'authorquota'}})) {
if (ref($domconfig{'quotas'}) eq 'HASH') {
if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
if (!exists($domconfig{'quotas'}{'authorquota'}{$key})) {
$changes{'authorquota'}{$key} = 1;
}
} else {
$changes{'authorquota'}{$key} = 1;
}
} else {
$changes{'authorquota'}{$key} = 1;
}
}
}
}
if ($context eq 'requestauthor') {
$domdefaults{'requestauthor'} = \%confhash;
} else {
foreach my $key (keys(%confhash)) {
unless (($context eq 'requestcourses') && ($key eq 'textbooks')) {
$domdefaults{$key} = $confhash{$key};
}
}
}
my %quotahash = (
$action => { %confhash }
);
my $putresult = &Apache::lonnet::put_dom('configuration',\%quotahash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
my $cachetime = 24*60*60;
&Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domdefaults'} = 1;
}
$resulttext = &mt('Changes made:').'<ul>';
unless (($context eq 'requestcourses') ||
($context eq 'requestauthor')) {
if (ref($changes{'defaultquota'}) eq 'HASH') {
$resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';
foreach my $type (@{$types},'default') {
if (defined($changes{'defaultquota'}{$type})) {
my $typetitle = $usertypes->{$type};
if ($type eq 'default') {
$typetitle = $othertitle;
}
$resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';
}
}
$resulttext .= '</ul></li>';
}
if (ref($changes{'authorquota'}) eq 'HASH') {
$resulttext .= '<li>'.&mt('Authoring Space default quotas').'<ul>';
foreach my $type (@{$types},'default') {
if (defined($changes{'authorquota'}{$type})) {
my $typetitle = $usertypes->{$type};
if ($type eq 'default') {
$typetitle = $othertitle;
}
$resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'authorquota'}{$type}).'</li>';
}
}
$resulttext .= '</ul></li>';
}
}
my %newenv;
foreach my $item (@usertools) {
my (%haschgs,%inconf);
if ($context eq 'requestauthor') {
%haschgs = %changes;
%inconf = %confhash;
} else {
if (ref($changes{$item}) eq 'HASH') {
%haschgs = %{$changes{$item}};
}
if (ref($confhash{$item}) eq 'HASH') {
%inconf = %{$confhash{$item}};
}
}
if (keys(%haschgs) > 0) {
my $newacc =
&Apache::lonnet::usertools_access($env{'user.name'},
$env{'user.domain'},
$item,'reload',$context);
if (($context eq 'requestcourses') ||
($context eq 'requestauthor')) {
if ($env{'environment.canrequest.'.$item} ne $newacc) {
$newenv{'environment.canrequest.'.$item} = $newacc;
}
} else {
if ($env{'environment.availabletools.'.$item} ne $newacc) {
$newenv{'environment.availabletools.'.$item} = $newacc;
}
}
unless ($context eq 'requestauthor') {
$resulttext .= '<li>'.$titles{$item}.'<ul>';
}
foreach my $type (@{$types},'default','_LC_adv') {
if ($haschgs{$type}) {
my $typetitle = $usertypes->{$type};
if ($type eq 'default') {
$typetitle = $othertitle;
} elsif ($type eq '_LC_adv') {
$typetitle = 'LON-CAPA Advanced Users';
}
if ($inconf{$type}) {
if ($context eq 'requestcourses') {
my $cond;
if ($inconf{$type} =~ /^autolimit=(\d*)$/) {
if ($1 eq '') {
$cond = &mt('(Automatic processing of any request).');
} else {
$cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);
}
} else {
$cond = $conditions{$inconf{$type}};
}
$resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';
} elsif ($context eq 'requestauthor') {
$resulttext .= '<li>'.&mt('Set to "[_1]" for "[_2]".',
$titles{$inconf{$type}},$typetitle);
} else {
$resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';
}
} else {
if ($type eq '_LC_adv') {
if ($inconf{$type} eq '0') {
$resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
} else {
$resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';
}
} else {
$resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
}
}
}
}
unless ($context eq 'requestauthor') {
$resulttext .= '</ul></li>';
}
}
}
if (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
if (ref($changes{'notify'}) eq 'HASH') {
if ($changes{'notify'}{'approval'}) {
if (ref($confhash{'notify'}) eq 'HASH') {
if ($confhash{'notify'}{'approval'}) {
$resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';
} else {
$resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of requests requiring approval.').'</li>';
}
}
}
}
}
if ($action eq 'requestcourses') {
my @offon = ('off','on');
if ($changes{'uniquecode'}) {
if (ref($confhash{'uniquecode'}) eq 'HASH') {
my $codestr = join(' ',map{ &mt($_); } sort(keys(%{$confhash{'uniquecode'}})));
$resulttext .= '<li>'.
&mt('Generation of six character code as course identifier for distribution to students set to on for: [_1].','<b>'.$codestr.'</b>').
'</li>';
} else {
$resulttext .= '<li>'.&mt('Generation of six character code as course identifier for distribution to students set to off.').
'</li>';
}
}
if (ref($changes{'textbooks'}) eq 'HASH') {
$resulttext .= '<li>'.&mt('Available textbooks updated').'<ul>';
foreach my $key (sort(keys(%{$changes{'textbooks'}}))) {
my %coursehash = &Apache::lonnet::coursedescription($key);
my $coursetitle = $coursehash{'description'};
my $position = $confhash{'textbooks'}{$key}{'order'} + 1;
$resulttext .= '<li>';
foreach my $item ('subject','title','author') {
my $name = $item.':';
$name =~ s/^(\w)/\U$1/;
$resulttext .= &mt($name).' '.$confhash{'textbooks'}{$key}{$item}.'<br />';
}
$resulttext .= ' '.&mt('Order: [_1]',$position).'<br />';
if ($confhash{'textbooks'}{$key}{'image'}) {
$resulttext .= ' '.&mt('Image: [_1]',
'<img src="'.$confhash{'textbooks'}{$key}{'image'}.'"'.
' alt="Textbook cover" />').'<br />';
}
$resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'</li>';
}
$resulttext .= '</ul></li>';
}
}
$resulttext .= '</ul>';
if (keys(%newenv)) {
&Apache::lonnet::appenv(\%newenv);
}
} else {
if ($context eq 'requestcourses') {
$resulttext = &mt('No changes made to rights to request creation of courses.');
} elsif ($context eq 'requestauthor') {
$resulttext = &mt('No changes made to rights to request author space.');
} else {
$resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');
}
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
if ($errors) {
$resulttext .= '<p>'.&mt('The following errors occurred when modifying Textbook settings.').
'<ul>'.$errors.'</ul></p>';
}
return $resulttext;
}
sub process_textbook_image {
my ($r,$dom,$confname,$caller,$cdom,$cnum,$configuserok,$switchserver,$author_ok) = @_;
my $filename = $env{'form.'.$caller.'.filename'};
my ($error,$url);
my ($width,$height) = (50,50);
if ($configuserok eq 'ok') {
if ($switchserver) {
$error = &mt('Upload of textbook image is not permitted to this server: [_1]',
$switchserver);
} elsif ($author_ok eq 'ok') {
my ($result,$imageurl) =
&publishlogo($r,'upload',$caller,$dom,$confname,
"textbooks/$dom/$cnum/cover",$width,$height);
if ($result eq 'ok') {
$url = $imageurl;
} else {
$error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
}
} else {
$error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$author_ok);
}
} else {
$error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$configuserok);
}
return ($url,$error);
}
sub modify_autoenroll {
my ($dom,$lastactref,%domconfig) = @_;
my ($resulttext,%changes);
my %currautoenroll;
if (ref($domconfig{'autoenroll'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'autoenroll'}})) {
$currautoenroll{$key} = $domconfig{'autoenroll'}{$key};
}
}
my $autorun = &Apache::lonnet::auto_run(undef,$dom),
my %title = ( run => 'Auto-enrollment active',
sender => 'Sender for notification messages',
coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)');
my @offon = ('off','on');
my $sender_uname = $env{'form.sender_uname'};
my $sender_domain = $env{'form.sender_domain'};
if ($sender_domain eq '') {
$sender_uname = '';
} elsif ($sender_uname eq '') {
$sender_domain = '';
}
my $coowners = $env{'form.autoassign_coowners'};
my %autoenrollhash = (
autoenroll => { 'run' => $env{'form.autoenroll_run'},
'sender_uname' => $sender_uname,
'sender_domain' => $sender_domain,
'co-owners' => $coowners,
}
);
my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
$dom);
if ($putresult eq 'ok') {
if (exists($currautoenroll{'run'})) {
if ($currautoenroll{'run'} ne $env{'form.autoenroll_run'}) {
$changes{'run'} = 1;
}
} elsif ($autorun) {
if ($env{'form.autoenroll_run'} ne '1') {
$changes{'run'} = 1;
}
}
if ($currautoenroll{'sender_uname'} ne $sender_uname) {
$changes{'sender'} = 1;
}
if ($currautoenroll{'sender_domain'} ne $sender_domain) {
$changes{'sender'} = 1;
}
if ($currautoenroll{'co-owners'} ne '') {
if ($currautoenroll{'co-owners'} ne $coowners) {
$changes{'coowners'} = 1;
}
} elsif ($coowners) {
$changes{'coowners'} = 1;
}
if (keys(%changes) > 0) {
$resulttext = &mt('Changes made:').'<ul>';
if ($changes{'run'}) {
$resulttext .= '<li>'.&mt("$title{'run'} set to $offon[$env{'form.autoenroll_run'}]").'</li>';
}
if ($changes{'sender'}) {
if ($sender_uname eq '' || $sender_domain eq '') {
$resulttext .= '<li>'.&mt("$title{'sender'} set to default (course owner).").'</li>';
} else {
$resulttext .= '<li>'.&mt("$title{'sender'} set to [_1]",$sender_uname.':'.$sender_domain).'</li>';
}
}
if ($changes{'coowners'}) {
$resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';
&Apache::loncommon::devalidate_domconfig_cache($dom);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domainconfig'} = 1;
}
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to auto-enrollment settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
return $resulttext;
}
sub modify_autoupdate {
my ($dom,%domconfig) = @_;
my ($resulttext,%currautoupdate,%fields,%changes);
if (ref($domconfig{'autoupdate'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'autoupdate'}})) {
$currautoupdate{$key} = $domconfig{'autoupdate'}{$key};
}
}
my @offon = ('off','on');
my %title = &Apache::lonlocal::texthash (
run => 'Auto-update:',
classlists => 'Updates to user information in classlists?'
);
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
my %fieldtitles = &Apache::lonlocal::texthash (
id => 'Student/Employee ID',
permanentemail => 'E-mail address',
lastname => 'Last Name',
firstname => 'First Name',
middlename => 'Middle Name',
generation => 'Generation',
);
$othertitle = &mt('All users');
if (keys(%{$usertypes}) > 0) {
$othertitle = &mt('Other users');
}
foreach my $key (keys(%env)) {
if ($key =~ /^form\.updateable_(.+)_([^_]+)$/) {
my ($usertype,$item) = ($1,$2);
if (grep(/^\Q$item\E$/,keys(%fieldtitles))) {
if ($usertype eq 'default') {
push(@{$fields{$1}},$2);
} elsif (ref($types) eq 'ARRAY') {
if (grep(/^\Q$usertype\E$/,@{$types})) {
push(@{$fields{$1}},$2);
}
}
}
}
}
my @lockablenames = &Apache::loncommon::get_env_multiple('form.lockablenames');
@lockablenames = sort(@lockablenames);
if (ref($currautoupdate{'lockablenames'}) eq 'ARRAY') {
my @changed = &Apache::loncommon::compare_arrays($currautoupdate{'lockablenames'},\@lockablenames);
if (@changed) {
$changes{'lockablenames'} = 1;
}
} else {
if (@lockablenames) {
$changes{'lockablenames'} = 1;
}
}
my %updatehash = (
autoupdate => { run => $env{'form.autoupdate_run'},
classlists => $env{'form.classlists'},
fields => {%fields},
lockablenames => \@lockablenames,
}
);
foreach my $key (keys(%currautoupdate)) {
if (($key eq 'run') || ($key eq 'classlists')) {
if (exists($updatehash{autoupdate}{$key})) {
if ($currautoupdate{$key} ne $updatehash{autoupdate}{$key}) {
$changes{$key} = 1;
}
}
} elsif ($key eq 'fields') {
if (ref($currautoupdate{$key}) eq 'HASH') {
foreach my $item (@{$types},'default') {
if (ref($currautoupdate{$key}{$item}) eq 'ARRAY') {
my $change = 0;
foreach my $type (@{$currautoupdate{$key}{$item}}) {
if (!exists($fields{$item})) {
$change = 1;
last;
} elsif (ref($fields{$item}) eq 'ARRAY') {
if (!grep(/^\Q$type\E$/,@{$fields{$item}})) {
$change = 1;
last;
}
}
}
if ($change) {
push(@{$changes{$key}},$item);
}
}
}
}
} elsif ($key eq 'lockablenames') {
if (ref($currautoupdate{$key}) eq 'ARRAY') {
my @changed = &Apache::loncommon::compare_arrays($currautoupdate{'lockablenames'},\@lockablenames);
if (@changed) {
$changes{'lockablenames'} = 1;
}
} else {
if (@lockablenames) {
$changes{'lockablenames'} = 1;
}
}
}
}
unless (grep(/^\Qlockablenames\E$/,keys(%currautoupdate))) {
if (@lockablenames) {
$changes{'lockablenames'} = 1;
}
}
foreach my $item (@{$types},'default') {
if (defined($fields{$item})) {
if (ref($currautoupdate{'fields'}) eq 'HASH') {
if (ref($currautoupdate{'fields'}{$item}) eq 'ARRAY') {
my $change = 0;
if (ref($fields{$item}) eq 'ARRAY') {
foreach my $type (@{$fields{$item}}) {
if (!grep(/^\Q$type\E$/,@{$currautoupdate{'fields'}{$item}})) {
$change = 1;
last;
}
}
}
if ($change) {
push(@{$changes{'fields'}},$item);
}
} else {
push(@{$changes{'fields'}},$item);
}
} else {
push(@{$changes{'fields'}},$item);
}
}
}
my $putresult = &Apache::lonnet::put_dom('configuration',\%updatehash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
$resulttext = &mt('Changes made:').'<ul>';
foreach my $key (sort(keys(%changes))) {
if ($key eq 'lockablenames') {
$resulttext .= '<li>';
if (@lockablenames) {
$usertypes->{'default'} = $othertitle;
$resulttext .= &mt("User preference to disable replacement of user's name with institutional data (by auto-update), available for the following affiliations:").' '.
join(', ', map { $usertypes->{$_}; } @lockablenames).'</li>';
} else {
$resulttext .= &mt("User preference to disable replacement of user's name with institutional data (by auto-update) is unavailable.");
}
$resulttext .= '</li>';
} elsif (ref($changes{$key}) eq 'ARRAY') {
foreach my $item (@{$changes{$key}}) {
my @newvalues;
foreach my $type (@{$fields{$item}}) {
push(@newvalues,$fieldtitles{$type});
}
my $newvaluestr;
if (@newvalues > 0) {
$newvaluestr = join(', ',@newvalues);
} else {
$newvaluestr = &mt('none');
}
if ($item eq 'default') {
$resulttext .= '<li>'.&mt("Updates for '[_1]' set to: '[_2]'",$othertitle,$newvaluestr).'</li>';
} else {
$resulttext .= '<li>'.&mt("Updates for '[_1]' set to: '[_2]'",$usertypes->{$item},$newvaluestr).'</li>';
}
}
} else {
my $newvalue;
if ($key eq 'run') {
$newvalue = $offon[$env{'form.autoupdate_run'}];
} else {
$newvalue = $offon[$env{'form.'.$key}];
}
$resulttext .= '<li>'.&mt("[_1] set to $newvalue",$title{$key}).'</li>';
}
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to autoupdates');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
return $resulttext;
}
sub modify_autocreate {
my ($dom,%domconfig) = @_;
my ($resulttext,%changes,%currautocreate,%newvals,%autocreatehash);
if (ref($domconfig{'autocreate'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'autocreate'}})) {
$currautocreate{$key} = $domconfig{'autocreate'}{$key};
}
}
my %title= ( xml => 'Auto-creation of courses in XML course description files',
req => 'Auto-creation of validated requests for official courses',
xmldc => 'Identity of course creator of courses from XML files',
);
my @types = ('xml','req');
foreach my $item (@types) {
$newvals{$item} = $env{'form.autocreate_'.$item};
$newvals{$item} =~ s/\D//g;
$newvals{$item} = 0 if ($newvals{$item} eq '');
}
$newvals{'xmldc'} = $env{'form.autocreate_xmldc'};
my %domcoords = &get_active_dcs($dom);
unless (exists($domcoords{$newvals{'xmldc'}})) {
$newvals{'xmldc'} = '';
}
%autocreatehash = (
autocreate => { xml => $newvals{'xml'},
req => $newvals{'req'},
}
);
if ($newvals{'xmldc'} ne '') {
$autocreatehash{'autocreate'}{'xmldc'} = $newvals{'xmldc'};
}
my $putresult = &Apache::lonnet::put_dom('configuration',\%autocreatehash,
$dom);
if ($putresult eq 'ok') {
my @items = @types;
if ($newvals{'xml'}) {
push(@items,'xmldc');
}
foreach my $item (@items) {
if (exists($currautocreate{$item})) {
if ($currautocreate{$item} ne $newvals{$item}) {
$changes{$item} = 1;
}
} elsif ($newvals{$item}) {
$changes{$item} = 1;
}
}
if (keys(%changes) > 0) {
my @offon = ('off','on');
$resulttext = &mt('Changes made:').'<ul>';
foreach my $item (@types) {
if ($changes{$item}) {
my $newtxt = $offon[$newvals{$item}];
$resulttext .= '<li>'.
&mt("$title{$item} set to [_1]$newtxt [_2]",
'<b>','</b>').
'</li>';
}
}
if ($changes{'xmldc'}) {
my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});
my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);
$resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]",'<b>'.$newtxt.'</b>').'</li>';
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to auto-creation settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
return $resulttext;
}
sub modify_directorysrch {
my ($dom,%domconfig) = @_;
my ($resulttext,%changes);
my %currdirsrch;
if (ref($domconfig{'directorysrch'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'directorysrch'}})) {
$currdirsrch{$key} = $domconfig{'directorysrch'}{$key};
}
}
my %title = ( available => 'Directory search available',
localonly => 'Other domains can search',
searchby => 'Search types',
searchtypes => 'Search latitude');
my @offon = ('off','on');
my @otherdoms = ('Yes','No');
my @searchtypes = &Apache::loncommon::get_env_multiple('form.searchtypes');
my @cansearch = &Apache::loncommon::get_env_multiple('form.cansearch');
my @searchby = &Apache::loncommon::get_env_multiple('form.searchby');
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
if (keys(%{$usertypes}) == 0) {
@cansearch = ('default');
} else {
if (ref($currdirsrch{'cansearch'}) eq 'ARRAY') {
foreach my $type (@{$currdirsrch{'cansearch'}}) {
if (!grep(/^\Q$type\E$/,@cansearch)) {
push(@{$changes{'cansearch'}},$type);
}
}
foreach my $type (@cansearch) {
if (!grep(/^\Q$type\E$/,@{$currdirsrch{'cansearch'}})) {
push(@{$changes{'cansearch'}},$type);
}
}
} else {
push(@{$changes{'cansearch'}},@cansearch);
}
}
if (ref($currdirsrch{'searchby'}) eq 'ARRAY') {
foreach my $by (@{$currdirsrch{'searchby'}}) {
if (!grep(/^\Q$by\E$/,@searchby)) {
push(@{$changes{'searchby'}},$by);
}
}
foreach my $by (@searchby) {
if (!grep(/^\Q$by\E$/,@{$currdirsrch{'searchby'}})) {
push(@{$changes{'searchby'}},$by);
}
}
} else {
push(@{$changes{'searchby'}},@searchby);
}
if (ref($currdirsrch{'searchtypes'}) eq 'ARRAY') {
foreach my $type (@{$currdirsrch{'searchtypes'}}) {
if (!grep(/^\Q$type\E$/,@searchtypes)) {
push(@{$changes{'searchtypes'}},$type);
}
}
foreach my $type (@searchtypes) {
if (!grep(/^\Q$type\E$/,@{$currdirsrch{'searchtypes'}})) {
push(@{$changes{'searchtypes'}},$type);
}
}
} else {
if (exists($currdirsrch{'searchtypes'})) {
foreach my $type (@searchtypes) {
if ($type ne $currdirsrch{'searchtypes'}) {
push(@{$changes{'searchtypes'}},$type);
}
}
if (!grep(/^\Q$currdirsrch{'searchtypes'}\E/,@searchtypes)) {
push(@{$changes{'searchtypes'}},$currdirsrch{'searchtypes'});
}
} else {
push(@{$changes{'searchtypes'}},@searchtypes);
}
}
my %dirsrch_hash = (
directorysrch => { available => $env{'form.dirsrch_available'},
cansearch => \@cansearch,
localonly => $env{'form.dirsrch_localonly'},
searchby => \@searchby,
searchtypes => \@searchtypes,
}
);
my $putresult = &Apache::lonnet::put_dom('configuration',\%dirsrch_hash,
$dom);
if ($putresult eq 'ok') {
if (exists($currdirsrch{'available'})) {
if ($currdirsrch{'available'} ne $env{'form.dirsrch_available'}) {
$changes{'available'} = 1;
}
} else {
if ($env{'form.dirsrch_available'} eq '1') {
$changes{'available'} = 1;
}
}
if (exists($currdirsrch{'localonly'})) {
if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_localonly'}) {
$changes{'localonly'} = 1;
}
} else {
if ($env{'form.dirsrch_localonly'} eq '1') {
$changes{'localonly'} = 1;
}
}
if (keys(%changes) > 0) {
$resulttext = &mt('Changes made:').'<ul>';
if ($changes{'available'}) {
$resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';
}
if ($changes{'localonly'}) {
$resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_localonly'}]").'</li>';
}
if (ref($changes{'cansearch'}) eq 'ARRAY') {
my $chgtext;
if (ref($usertypes) eq 'HASH') {
if (keys(%{$usertypes}) > 0) {
foreach my $type (@{$types}) {
if (grep(/^\Q$type\E$/,@cansearch)) {
$chgtext .= $usertypes->{$type}.'; ';
}
}
if (grep(/^default$/,@cansearch)) {
$chgtext .= $othertitle;
} else {
$chgtext =~ s/\; $//;
}
$resulttext .=
'<li>'.
&mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]",
'<span class="LC_cusr_emph">'.$dom.'</span>',$chgtext).
'</li>';
}
}
}
if (ref($changes{'searchby'}) eq 'ARRAY') {
my ($searchtitles,$titleorder) = &sorted_searchtitles();
my $chgtext;
foreach my $type (@{$titleorder}) {
if (grep(/^\Q$type\E$/,@searchby)) {
if (defined($searchtitles->{$type})) {
$chgtext .= $searchtitles->{$type}.'; ';
}
}
}
$chgtext =~ s/\; $//;
$resulttext .= '<li>'.&mt("$title{'searchby'} set to: [_1]",$chgtext).'</li>';
}
if (ref($changes{'searchtypes'}) eq 'ARRAY') {
my ($srchtypes_desc,$srchtypeorder) = &sorted_searchtypes();
my $chgtext;
foreach my $type (@{$srchtypeorder}) {
if (grep(/^\Q$type\E$/,@searchtypes)) {
if (defined($srchtypes_desc->{$type})) {
$chgtext .= $srchtypes_desc->{$type}.'; ';
}
}
}
$chgtext =~ s/\; $//;
$resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to institution directory search settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
return $resulttext;
}
sub modify_contacts {
my ($dom,$lastactref,%domconfig) = @_;
my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);
if (ref($domconfig{'contacts'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'contacts'}})) {
$currsetting{$key} = $domconfig{'contacts'}{$key};
}
}
my (%others,%to,%bcc);
my @contacts = ('supportemail','adminemail');
my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail',
'requestsmail','updatesmail','idconflictsmail');
my @toggles = ('reporterrors','reportupdates');
foreach my $type (@mailings) {
@{$newsetting{$type}} =
&Apache::loncommon::get_env_multiple('form.'.$type);
foreach my $item (@contacts) {
if (grep(/^\Q$item\E$/,@{$newsetting{$type}})) {
$contacts_hash{contacts}{$type}{$item} = 1;
} else {
$contacts_hash{contacts}{$type}{$item} = 0;
}
}
$others{$type} = $env{'form.'.$type.'_others'};
$contacts_hash{contacts}{$type}{'others'} = $others{$type};
if ($type eq 'helpdeskmail') {
$bcc{$type} = $env{'form.'.$type.'_bcc'};
$contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};
}
}
foreach my $item (@contacts) {
$to{$item} = $env{'form.'.$item};
$contacts_hash{'contacts'}{$item} = $to{$item};
}
foreach my $item (@toggles) {
if ($env{'form.'.$item} =~ /^(0|1)$/) {
$contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
}
}
if (keys(%currsetting) > 0) {
foreach my $item (@contacts) {
if ($to{$item} ne $currsetting{$item}) {
$changes{$item} = 1;
}
}
foreach my $type (@mailings) {
foreach my $item (@contacts) {
if (ref($currsetting{$type}) eq 'HASH') {
if ($currsetting{$type}{$item} ne $contacts_hash{contacts}{$type}{$item}) {
push(@{$changes{$type}},$item);
}
} else {
push(@{$changes{$type}},@{$newsetting{$type}});
}
}
if ($others{$type} ne $currsetting{$type}{'others'}) {
push(@{$changes{$type}},'others');
}
if ($type eq 'helpdeskmail') {
if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {
push(@{$changes{$type}},'bcc');
}
}
}
} else {
my %default;
$default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
$default{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
$default{'errormail'} = 'adminemail';
$default{'packagesmail'} = 'adminemail';
$default{'helpdeskmail'} = 'supportemail';
$default{'lonstatusmail'} = 'adminemail';
$default{'requestsmail'} = 'adminemail';
$default{'updatesmail'} = 'adminemail';
foreach my $item (@contacts) {
if ($to{$item} ne $default{$item}) {
$changes{$item} = 1;
}
}
foreach my $type (@mailings) {
if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {
push(@{$changes{$type}},@{$newsetting{$type}});
}
if ($others{$type} ne '') {
push(@{$changes{$type}},'others');
}
if ($type eq 'helpdeskmail') {
if ($bcc{$type} ne '') {
push(@{$changes{$type}},'bcc');
}
}
}
}
foreach my $item (@toggles) {
if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) {
$changes{$item} = 1;
} elsif ((!$env{'form.'.$item}) &&
(($currsetting{$item} eq '') || ($currsetting{$item} == 1))) {
$changes{$item} = 1;
}
}
my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
&Apache::loncommon::devalidate_domconfig_cache($dom);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domainconfig'} = 1;
}
my ($titles,$short_titles) = &contact_titles();
$resulttext = &mt('Changes made:').'<ul>';
foreach my $item (@contacts) {
if ($changes{$item}) {
$resulttext .= '<li>'.$titles->{$item}.
&mt(' set to: ').
'<span class="LC_cusr_emph">'.
$to{$item}.'</span></li>';
}
}
foreach my $type (@mailings) {
if (ref($changes{$type}) eq 'ARRAY') {
$resulttext .= '<li>'.$titles->{$type}.': ';
my @text;
foreach my $item (@{$newsetting{$type}}) {
push(@text,$short_titles->{$item});
}
if ($others{$type} ne '') {
push(@text,$others{$type});
}
$resulttext .= '<span class="LC_cusr_emph">'.
join(', ',@text).'</span>';
if ($type eq 'helpdeskmail') {
if ($bcc{$type} ne '') {
$resulttext .= ' '.&mt('with Bcc to').': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
}
}
$resulttext .= '</li>';
}
}
my @offon = ('off','on');
if ($changes{'reporterrors'}) {
$resulttext .= '<li>'.
&mt('E-mail error reports to [_1] set to "'.
$offon[$env{'form.reporterrors'}].'".',
&Apache::loncommon::modal_link('http://loncapa.org/core.html',
&mt('LON-CAPA core group - MSU'),600,500)).
'</li>';
}
if ($changes{'reportupdates'}) {
$resulttext .= '<li>'.
&mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.
$offon[$env{'form.reportupdates'}].'".',
&Apache::loncommon::modal_link('http://loncapa.org/core.html',
&mt('LON-CAPA core group - MSU'),600,500)).
'</li>';
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to contact information');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1].',$putresult).'</span>';
}
return $resulttext;
}
sub modify_usercreation {
my ($dom,%domconfig) = @_;
my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
my $warningmsg;
if (ref($domconfig{'usercreation'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'usercreation'}})) {
if ($key eq 'cancreate') {
if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
($item eq 'captcha') || ($item eq 'recaptchakeys')) {
$save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
} else {
$curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
}
}
}
} elsif ($key eq 'email_rule') {
$save_usercreate{$key} = $domconfig{'usercreation'}{$key};
} else {
$curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
}
}
}
my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');
my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');
my @contexts = ('author','course','requestcrs');
foreach my $item(@contexts) {
$cancreate{$item} = $env{'form.can_createuser_'.$item};
}
if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
foreach my $item (@contexts) {
if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {
push(@{$changes{'cancreate'}},$item);
}
}
} elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {
foreach my $item (@contexts) {
if (!grep(/^\Q$item\E$/,@{$curr_usercreation{'cancreate'}})) {
if ($cancreate{$item} ne 'any') {
push(@{$changes{'cancreate'}},$item);
}
} else {
if ($cancreate{$item} ne 'none') {
push(@{$changes{'cancreate'}},$item);
}
}
}
} else {
foreach my $item (@contexts) {
push(@{$changes{'cancreate'}},$item);
}
}
if (ref($curr_usercreation{'username_rule'}) eq 'ARRAY') {
foreach my $type (@{$curr_usercreation{'username_rule'}}) {
if (!grep(/^\Q$type\E$/,@username_rule)) {
push(@{$changes{'username_rule'}},$type);
}
}
foreach my $type (@username_rule) {
if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'username_rule'}})) {
push(@{$changes{'username_rule'}},$type);
}
}
} else {
push(@{$changes{'username_rule'}},@username_rule);
}
if (ref($curr_usercreation{'id_rule'}) eq 'ARRAY') {
foreach my $type (@{$curr_usercreation{'id_rule'}}) {
if (!grep(/^\Q$type\E$/,@id_rule)) {
push(@{$changes{'id_rule'}},$type);
}
}
foreach my $type (@id_rule) {
if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'id_rule'}})) {
push(@{$changes{'id_rule'}},$type);
}
}
} else {
push(@{$changes{'id_rule'}},@id_rule);
}
my @authen_contexts = ('author','course','domain');
my @authtypes = ('int','krb4','krb5','loc');
my %authhash;
foreach my $item (@authen_contexts) {
my @authallowed = &Apache::loncommon::get_env_multiple('form.'.$item.'_auth');
foreach my $auth (@authtypes) {
if (grep(/^\Q$auth\E$/,@authallowed)) {
$authhash{$item}{$auth} = 1;
} else {
$authhash{$item}{$auth} = 0;
}
}
}
if (ref($curr_usercreation{'authtypes'}) eq 'HASH') {
foreach my $item (@authen_contexts) {
if (ref($curr_usercreation{'authtypes'}{$item}) eq 'HASH') {
foreach my $auth (@authtypes) {
if ($authhash{$item}{$auth} ne $curr_usercreation{'authtypes'}{$item}{$auth}) {
push(@{$changes{'authtypes'}},$item);
last;
}
}
}
}
} else {
foreach my $item (@authen_contexts) {
push(@{$changes{'authtypes'}},$item);
}
}
$save_usercreate{'cancreate'}{'course'} = $cancreate{'course'};
$save_usercreate{'cancreate'}{'author'} = $cancreate{'author'};
$save_usercreate{'cancreate'}{'requestcrs'} = $cancreate{'requestcrs'};
$save_usercreate{'id_rule'} = \@id_rule;
$save_usercreate{'username_rule'} = \@username_rule,
$save_usercreate{'authtypes'} = \%authhash;
my %usercreation_hash = (
usercreation => \%save_usercreate,
);
my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
$resulttext = &mt('Changes made:').'<ul>';
if (ref($changes{'cancreate'}) eq 'ARRAY') {
my %lt = &usercreation_types();
foreach my $type (@{$changes{'cancreate'}}) {
my $chgtext = $lt{$type}.', ';
if ($cancreate{$type} eq 'none') {
$chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');
} elsif ($cancreate{$type} eq 'any') {
$chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');
} elsif ($cancreate{$type} eq 'official') {
$chgtext .= &mt('creation of new users is only permitted for institutional usernames.');
} elsif ($cancreate{$type} eq 'unofficial') {
$chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');
}
$resulttext .= '<li>'.$chgtext.'</li>';
}
}
if (ref($changes{'username_rule'}) eq 'ARRAY') {
my ($rules,$ruleorder) =
&Apache::lonnet::inst_userrules($dom,'username');
my $chgtext = '<ul>';
foreach my $type (@username_rule) {
if (ref($rules->{$type}) eq 'HASH') {
$chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';
}
}
$chgtext .= '</ul>';
if (@username_rule > 0) {
$resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';
} else {
$resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>';
}
}
if (ref($changes{'id_rule'}) eq 'ARRAY') {
my ($idrules,$idruleorder) =
&Apache::lonnet::inst_userrules($dom,'id');
my $chgtext = '<ul>';
foreach my $type (@id_rule) {
if (ref($idrules->{$type}) eq 'HASH') {
$chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';
}
}
$chgtext .= '</ul>';
if (@id_rule > 0) {
$resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';
} else {
$resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';
}
}
my %authname = &authtype_names();
my %context_title = &context_names();
if (ref($changes{'authtypes'}) eq 'ARRAY') {
my $chgtext = '<ul>';
foreach my $type (@{$changes{'authtypes'}}) {
my @allowed;
$chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');
foreach my $auth (@authtypes) {
if ($authhash{$type}{$auth}) {
push(@allowed,$authname{$auth});
}
}
if (@allowed > 0) {
$chgtext .= join(', ',@allowed).'</li>';
} else {
$chgtext .= &mt('none').'</li>';
}
}
$chgtext .= '</ul>';
$resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;
$resulttext .= '</li>';
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to user creation settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
if ($warningmsg ne '') {
$resulttext .= '<br /><span class="LC_warning">'.$warningmsg.'</span><br />';
}
return $resulttext;
}
sub modify_selfcreation {
my ($dom,%domconfig) = @_;
my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%changes,%cancreate);
my (%save_usercreate,%save_usermodify);
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
if (ref($types) eq 'ARRAY') {
$usertypes->{'default'} = $othertitle;
push(@{$types},'default');
}
#
# Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.
#
if (ref($domconfig{'usercreation'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'usercreation'}})) {
if ($key eq 'cancreate') {
if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
($item eq 'captcha') || ($item eq 'recaptchakeys') ||
($item eq 'emailusername') || ($item eq 'notify')) {
$curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
} else {
$save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
}
}
}
} elsif ($key eq 'email_rule') {
$curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
} else {
$save_usercreate{$key} = $domconfig{'usercreation'}{$key};
}
}
}
#
# Retrieve current domain configuration for self-creation of usernames from $domconfig{'usermodification'}.
#
if (ref($domconfig{'usermodification'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'usermodification'}})) {
if ($key eq 'selfcreate') {
$curr_usermodify{$key} = $domconfig{'usermodification'}{$key};
} else {
$save_usermodify{$key} = $domconfig{'usermodification'}{$key};
}
}
}
my @contexts = ('selfcreate');
@{$cancreate{'selfcreate'}} = ();
%{$cancreate{'emailusername'}} = ();
@{$cancreate{'statustocreate'}} = ();
my %selfcreatetypes = (
sso => 'users authenticated by institutional single sign on',
login => 'users authenticated by institutional log-in',
email => 'users who provide a valid e-mail address for use as username (automatic creation)',
emailapproval => 'users who provide a valid e-mail address for use as username (queued for Domain Coordinator review)',
);
#
# Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts
# is permitted.
#
foreach my $item ('login','sso','email') {
if ($item eq 'email') {
if ($env{'form.cancreate_email'} eq 'email') {
push(@{$cancreate{'selfcreate'}},'email');
} elsif ($env{'form.cancreate_email'} eq 'emailapproval') {
push(@{$cancreate{'selfcreate'}},'emailapproval');
}
} else {
if ($env{'form.cancreate_'.$item}) {
push(@{$cancreate{'selfcreate'}},$item);
}
}
}
my (@email_rule,%userinfo,%savecaptcha);
my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
#
# Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data
# value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc.
#
if (($env{'form.cancreate_email'} eq 'email') || ($env{'form.cancreate_email'} eq 'emailapproval')) {
push(@contexts,'emailusername');
if (ref($types) eq 'ARRAY') {
foreach my $type (@{$types}) {
if (ref($infofields) eq 'ARRAY') {
foreach my $field (@{$infofields}) {
if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {
$cancreate{'emailusername'}{$type}{$field} = $1;
}
}
}
}
}
#
# Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of
# queued requests for self-creation of account using e-mail address as username
#
my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');
@approvalnotify = sort(@approvalnotify);
$cancreate{'notify'}{'approval'} = join(',',@approvalnotify);
if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
if (ref($curr_usercreation{'cancreate'}{'notify'}) eq 'HASH') {
if ($curr_usercreation{'cancreate'}{'notify'}{'approval'} ne $cancreate{'notify'}{'approval'}) {
push(@{$changes{'cancreate'}},'notify');
}
} else {
if ($cancreate{'notify'}{'approval'}) {
push(@{$changes{'cancreate'}},'notify');
}
}
} elsif ($cancreate{'notify'}{'approval'}) {
push(@{$changes{'cancreate'}},'notify');
}
#
# Retrieve rules (if any) governing types of e-mail address which may be used as a username
#
@email_rule = &Apache::loncommon::get_env_multiple('form.email_rule');
&process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});
if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {
if (@{$curr_usercreation{'email_rule'}} > 0) {
foreach my $type (@{$curr_usercreation{'email_rule'}}) {
if (!grep(/^\Q$type\E$/,@email_rule)) {
push(@{$changes{'email_rule'}},$type);
}
}
}
if (@email_rule > 0) {
foreach my $type (@email_rule) {
if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) {
push(@{$changes{'email_rule'}},$type);
}
}
}
} elsif (@email_rule > 0) {
push(@{$changes{'email_rule'}},@email_rule);
}
}
#
# Check if domain default is set appropriately, if selef-creation of accounts is to be available for
# institutional log-in.
#
if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) ||
($domdefaults{'auth_def'} eq 'localauth'))) {
$warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.
&mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');
}
}
my @fields = ('lastname','firstname','middlename','generation',
'permanentemail','id');
my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
#
# Where usernames may created for institutional log-in and/or institutional single sign on:
# (a) populate $cancreate{'statustocreate'} array reference with institutional status types who
# may self-create accounts
# (b) populate $save_usermodify{'selfcreate'} hash reference with status types, and information fields
# which the user may supply, if institutional data is unavailable.
#
if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {
if (ref($types) eq 'ARRAY') {
if (@{$types} > 1) {
@{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');
push(@contexts,'statustocreate');
} else {
undef($cancreate{'statustocreate'});
}
foreach my $type (@{$types}) {
my @modifiable = &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);
foreach my $field (@fields) {
if (grep(/^\Q$field\E$/,@modifiable)) {
$save_usermodify{'selfcreate'}{$type}{$field} = 1;
} else {
$save_usermodify{'selfcreate'}{$type}{$field} = 0;
}
}
}
if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {
foreach my $type (@{$types}) {
if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {
foreach my $field (@fields) {
if ($save_usermodify{'selfcreate'}{$type}{$field} ne
$curr_usermodify{'selfcreate'}{$type}{$field}) {
push(@{$changes{'selfcreate'}},$type);
last;
}
}
}
}
} else {
foreach my $type (@{$types}) {
push(@{$changes{'selfcreate'}},$type);
}
}
}
}
foreach my $item (@contexts) {
if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {
foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {
if (ref($cancreate{$item}) eq 'ARRAY') {
if (!grep(/^$curr$/,@{$cancreate{$item}})) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
}
}
if (ref($cancreate{$item}) eq 'ARRAY') {
foreach my $type (@{$cancreate{$item}}) {
if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
}
}
} elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {
if (ref($cancreate{$item}) eq 'HASH') {
foreach my $curr (keys(%{$curr_usercreation{'cancreate'}{$item}})) {
if (ref($curr_usercreation{'cancreate'}{$item}{$curr}) eq 'HASH') {
foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$curr}})) {
unless ($curr_usercreation{'cancreate'}{$item}{$curr}{$field} eq $cancreate{$item}{$curr}{$field}) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
}
} else {
if (!$cancreate{$item}{$curr}) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
}
}
foreach my $field (keys(%{$cancreate{$item}})) {
if (ref($cancreate{$item}{$field}) eq 'HASH') {
foreach my $inner (keys(%{$cancreate{$item}{$field}})) {
if (ref($curr_usercreation{'cancreate'}{$item}{$field}) eq 'HASH') {
unless ($curr_usercreation{'cancreate'}{$item}{$field}{$inner} eq $cancreate{$item}{$field}{$inner}) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
} else {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
}
} else {
if (!$curr_usercreation{'cancreate'}{$item}{$field}) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
}
}
}
} elsif ($curr_usercreation{'cancreate'}{$item}) {
if (ref($cancreate{$item}) eq 'ARRAY') {
if (!grep(/^\Q$curr_usercreation{'cancreate'}{$item}\E$/,@{$cancreate{$item}})) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
} elsif (ref($cancreate{$item}) eq 'HASH') {
if (!$cancreate{$item}{$curr_usercreation{'cancreate'}{$item}}) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
}
}
} elsif ($item eq 'emailusername') {
if (ref($cancreate{$item}) eq 'HASH') {
foreach my $type (keys(%{$cancreate{$item}})) {
if (ref($cancreate{$item}{$type}) eq 'HASH') {
foreach my $field (keys(%{$cancreate{$item}{$type}})) {
if ($cancreate{$item}{$type}{$field}) {
if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
push(@{$changes{'cancreate'}},$item);
}
last;
}
}
}
}
}
}
}
#
# Populate %save_usercreate hash with updates to self-creation configuration.
#
$save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'};
$save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'};
$save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'};
if (ref($cancreate{'notify'}) eq 'HASH') {
$save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'};
}
if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
$save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};
}
$save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};
$save_usercreate{'emailrule'} = \@email_rule;
my %userconfig_hash = (
usercreation => \%save_usercreate,
usermodification => \%save_usermodify,
);
my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,
$dom);
#
# Accumulate details of changes to domain cofiguration for self-creation of usernames in $resulttext
#
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
$resulttext = &mt('Changes made:').'<ul>';
if (ref($changes{'cancreate'}) eq 'ARRAY') {
my %lt = &selfcreation_types();
foreach my $type (@{$changes{'cancreate'}}) {
my $chgtext;
if ($type eq 'selfcreate') {
if (@{$cancreate{$type}} == 0) {
$chgtext .= &mt('Self creation of a new user account is not permitted.');
} else {
$chgtext .= &mt('Self-creation of a new account is permitted for:').
'<ul>';
foreach my $case (@{$cancreate{$type}}) {
$chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';
}
$chgtext .= '</ul>';
if (ref($cancreate{$type}) eq 'ARRAY') {
if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {
if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
if (@{$cancreate{'statustocreate'}} == 0) {
$chgtext .= '<br />'.
'<span class="LC_warning">'.
&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
'</span>';
}
}
}
}
}
} elsif ($type eq 'statustocreate') {
if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&
(ref($cancreate{'statustocreate'}) eq 'ARRAY')) {
if (@{$cancreate{'selfcreate'}} > 0) {
if (@{$cancreate{'statustocreate'}} == 0) {
$chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");
if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {
$chgtext .= '<br />'.
'<span class="LC_warning">'.
&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
'</span>';
}
} elsif (ref($usertypes) eq 'HASH') {
if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
$chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');
} else {
$chgtext .= &mt('Institutional affiliations permitted to create accounts with institutional authentication were set as follows:');
}
$chgtext .= '<ul>';
foreach my $case (@{$cancreate{$type}}) {
if ($case eq 'default') {
$chgtext .= '<li>'.$othertitle.'</li>';
} else {
$chgtext .= '<li>'.$usertypes->{$case}.'</li>';
}
}
$chgtext .= '</ul>';
if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
$chgtext .= '<br /><span class="LC_warning">'.
&mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').
'</span>';
}
}
} else {
if (@{$cancreate{$type}} == 0) {
$chgtext .= &mt("Institutional affiliations permitted to create accounts were set to 'none'.");
} else {
$chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');
}
}
}
} elsif ($type eq 'captcha') {
if ($savecaptcha{$type} eq 'notused') {
$chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');
} else {
my %captchas = &captcha_phrases();
if ($captchas{$savecaptcha{$type}}) {
$chgtext .= &mt("Validation for self-creation screen set to $captchas{$savecaptcha{$type}}.");
} else {
$chgtext .= &mt('Validation for self-creation screen set to unknown type.');
}
}
} elsif ($type eq 'recaptchakeys') {
my ($privkey,$pubkey);
if (ref($savecaptcha{$type}) eq 'HASH') {
$pubkey = $savecaptcha{$type}{'public'};
$privkey = $savecaptcha{$type}{'private'};
}
$chgtext .= &mt('ReCAPTCHA keys changes').'<ul>';
if (!$pubkey) {
$chgtext .= '<li>'.&mt('Public key deleted').'</li>';
} else {
$chgtext .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';
}
if (!$privkey) {
$chgtext .= '<li>'.&mt('Private key deleted').'</li>';
} else {
$chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';
}
$chgtext .= '</ul>';
} elsif ($type eq 'emailusername') {
if (ref($cancreate{'emailusername'}) eq 'HASH') {
if (ref($types) eq 'ARRAY') {
foreach my $type (@{$types}) {
if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {
if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {
$chgtext .= &mt('When self-creating account with e-mail as username, the following information will be provided by [_1]:',$usertypes->{$type}).
'<ul>';
foreach my $field (@{$infofields}) {
if ($cancreate{'emailusername'}{$type}{$field}) {
$chgtext .= '<li>'.$infotitles->{$field}.'</li>';
}
}
}
$chgtext .= '</ul>';
} else {
$chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',$usertypes->{$type}).'<br />';
}
}
}
}
} elsif ($type eq 'notify') {
$chgtext = &mt('No Domain Coordinators will receive notification of username requests requiring approval.');
if (ref($changes{'cancreate'}) eq 'ARRAY') {
if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {
if ($cancreate{'notify'}{'approval'}) {
$chgtext = &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'};
}
}
}
}
if ($chgtext) {
$resulttext .= '<li>'.$chgtext.'</li>';
}
}
}
if (ref($changes{'email_rule'}) eq 'ARRAY') {
my ($emailrules,$emailruleorder) =
&Apache::lonnet::inst_userrules($dom,'email');
my $chgtext = '<ul>';
foreach my $type (@email_rule) {
if (ref($emailrules->{$type}) eq 'HASH') {
$chgtext .= '<li>'.$emailrules->{$type}{'name'}.'</li>';
}
}
$chgtext .= '</ul>';
if (@email_rule > 0) {
$resulttext .= '<li>'.
&mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').
$chgtext.
'</li>';
} else {
$resulttext .= '<li>'.
&mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').
'</li>';
}
}
if (ref($changes{'selfcreate'}) eq 'ARRAY') {
$resulttext .= '<li>'.&mt('When self-creating institutional account:').'<ul>';
my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
foreach my $type (@{$changes{'selfcreate'}}) {
my $typename = $type;
if (ref($usertypes) eq 'HASH') {
if ($usertypes->{$type} ne '') {
$typename = $usertypes->{$type};
}
}
my @modifiable;
$resulttext .= '<li>'.
&mt('Self-creation of account by users with status: [_1]',
'<span class="LC_cusr_emph">'.$typename.'</span>').
' - '.&mt('modifiable fields (if institutional data blank): ');
foreach my $field (@fields) {
if ($save_usermodify{'selfcreate'}{$type}{$field}) {
push(@modifiable,'<b>'.$fieldtitles{$field}.'</b>');
}
}
if (@modifiable > 0) {
$resulttext .= join(', ',@modifiable);
} else {
$resulttext .= &mt('none');
}
$resulttext .= '</li>';
}
$resulttext .= '</ul></li>';
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to self-creation settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
if ($warningmsg ne '') {
$resulttext .= '<br /><span class="LC_warning">'.$warningmsg.'</span><br />';
}
return $resulttext;
}
sub process_captcha {
my ($container,$changes,$newsettings,$current) = @_;
return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
$newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
$newsettings->{'captcha'} = 'original';
}
if ($current->{'captcha'} ne $newsettings->{'captcha'}) {
if ($container eq 'cancreate') {
if (ref($changes->{'cancreate'}) eq 'ARRAY') {
push(@{$changes->{'cancreate'}},'captcha');
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['captcha'];
}
} else {
$changes->{'captcha'} = 1;
}
}
my ($newpub,$newpriv,$currpub,$currpriv);
if ($newsettings->{'captcha'} eq 'recaptcha') {
$newpub = $env{'form.'.$container.'_recaptchapub'};
$newpriv = $env{'form.'.$container.'_recaptchapriv'};
$newpub =~ s/\W//g;
$newpriv =~ s/\W//g;
$newsettings->{'recaptchakeys'} = {
public => $newpub,
private => $newpriv,
};
}
if (ref($current->{'recaptchakeys'}) eq 'HASH') {
$currpub = $current->{'recaptchakeys'}{'public'};
$currpriv = $current->{'recaptchakeys'}{'private'};
unless ($newsettings->{'captcha'} eq 'recaptcha') {
$newsettings->{'recaptchakeys'} = {
public => '',
private => '',
}
}
}
if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {
if ($container eq 'cancreate') {
if (ref($changes->{'cancreate'}) eq 'ARRAY') {
push(@{$changes->{'cancreate'}},'recaptchakeys');
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['recaptchakeys'];
}
} else {
$changes->{'recaptchakeys'} = 1;
}
}
return;
}
sub modify_usermodification {
my ($dom,%domconfig) = @_;
my ($resulttext,%curr_usermodification,%changes,%modifyhash);
if (ref($domconfig{'usermodification'}) eq 'HASH') {
foreach my $key (keys(%{$domconfig{'usermodification'}})) {
if ($key eq 'selfcreate') {
$modifyhash{$key} = $domconfig{'usermodification'}{$key};
} else {
$curr_usermodification{$key} = $domconfig{'usermodification'}{$key};
}
}
}
my @contexts = ('author','course');
my %context_title = (
author => 'In author context',
course => 'In course context',
);
my @fields = ('lastname','firstname','middlename','generation',
'permanentemail','id');
my %roles = (
author => ['ca','aa'],
course => ['st','ep','ta','in','cr'],
);
my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
foreach my $context (@contexts) {
foreach my $role (@{$roles{$context}}) {
my @modifiable = &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);
foreach my $item (@fields) {
if (grep(/^\Q$item\E$/,@modifiable)) {
$modifyhash{$context}{$role}{$item} = 1;
} else {
$modifyhash{$context}{$role}{$item} = 0;
}
}
}
if (ref($curr_usermodification{$context}) eq 'HASH') {
foreach my $role (@{$roles{$context}}) {
if (ref($curr_usermodification{$context}{$role}) eq 'HASH') {
foreach my $field (@fields) {
if ($modifyhash{$context}{$role}{$field} ne
$curr_usermodification{$context}{$role}{$field}) {
push(@{$changes{$context}},$role);
last;
}
}
}
}
} else {
foreach my $context (@contexts) {
foreach my $role (@{$roles{$context}}) {
push(@{$changes{$context}},$role);
}
}
}
}
my %usermodification_hash = (
usermodification => \%modifyhash,
);
my $putresult = &Apache::lonnet::put_dom('configuration',
\%usermodification_hash,$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
$resulttext = &mt('Changes made: ').'<ul>';
foreach my $context (@contexts) {
if (ref($changes{$context}) eq 'ARRAY') {
$resulttext .= '<li>'.$context_title{$context}.':<ul>';
if (ref($changes{$context}) eq 'ARRAY') {
foreach my $role (@{$changes{$context}}) {
my $rolename;
if ($role eq 'cr') {
$rolename = &mt('Custom');
} else {
$rolename = &Apache::lonnet::plaintext($role);
}
my @modifiable;
$resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Target user with [_1] role',$rolename).'</span> - '.&mt('modifiable fields: ');
foreach my $field (@fields) {
if ($modifyhash{$context}{$role}{$field}) {
push(@modifiable,$fieldtitles{$field});
}
}
if (@modifiable > 0) {
$resulttext .= join(', ',@modifiable);
} else {
$resulttext .= &mt('none');
}
$resulttext .= '</li>';
}
$resulttext .= '</ul></li>';
}
}
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to user modification settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
return $resulttext;
}
sub modify_defaults {
my ($dom,$lastactref,%domconfig) = @_;
my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def');
my @authtypes = ('internal','krb4','krb5','localauth');
foreach my $item (@items) {
$newvalues{$item} = $env{'form.'.$item};
if ($item eq 'auth_def') {
if ($newvalues{$item} ne '') {
if (!grep(/^\Q$newvalues{$item}\E$/,@authtypes)) {
push(@errors,$item);
}
}
} elsif ($item eq 'lang_def') {
if ($newvalues{$item} ne '') {
if ($newvalues{$item} =~ /^(\w+)/) {
my $langcode = $1;
if ($langcode ne 'x_chef') {
if (code2language($langcode) eq '') {
push(@errors,$item);
}
}
} else {
push(@errors,$item);
}
}
} elsif ($item eq 'timezone_def') {
if ($newvalues{$item} ne '') {
if (!DateTime::TimeZone->is_valid_name($newvalues{$item})) {
push(@errors,$item);
}
}
} elsif ($item eq 'datelocale_def') {
if ($newvalues{$item} ne '') {
my @datelocale_ids = DateTime::Locale->ids();
if (!grep(/^\Q$newvalues{$item}\E$/,@datelocale_ids)) {
push(@errors,$item);
}
}
} elsif ($item eq 'portal_def') {
if ($newvalues{$item} ne '') {
unless ($newvalues{$item} =~ /^https?\:\/\/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])\/?$/) {
push(@errors,$item);
}
}
}
if (grep(/^\Q$item\E$/,@errors)) {
$newvalues{$item} = $domdefaults{$item};
} elsif ($domdefaults{$item} ne $newvalues{$item}) {
$changes{$item} = 1;
}
$domdefaults{$item} = $newvalues{$item};
}
my %defaults_hash = (
defaults => \%newvalues,
);
my $title = &defaults_titles();
my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
$resulttext = &mt('Changes made:').'<ul>';
my $version = &Apache::lonnet::get_server_loncaparev($dom);
my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";
foreach my $item (sort(keys(%changes))) {
my $value = $env{'form.'.$item};
if ($value eq '') {
$value = &mt('none');
} elsif ($item eq 'auth_def') {
my %authnames = &authtype_names();
my %shortauth = (
internal => 'int',
krb4 => 'krb4',
krb5 => 'krb5',
localauth => 'loc',
);
$value = $authnames{$shortauth{$value}};
}
$resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
$mailmsgtext .= "$title->{$item} set to $value\n";
}
$resulttext .= '</ul>';
$mailmsgtext .= "\n";
my $cachetime = 24*60*60;
&Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domdefaults'} = 1;
}
if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {
my $notify = 1;
if (ref($domconfig{'contacts'}) eq 'HASH') {
if ($domconfig{'contacts'}{'reportupdates'} == 0) {
$notify = 0;
}
}
if ($notify) {
&Apache::lonmsg::sendemail('installrecord@loncapa.org',
"LON-CAPA Domain Settings Change - $dom",
$mailmsgtext);
}
}
} else {
$resulttext = &mt('No changes made to default authentication/language/timezone settings');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
if (@errors > 0) {
$resulttext .= '<br />'.&mt('The following were left unchanged because the values entered were invalid:');
foreach my $item (@errors) {
$resulttext .= ' "'.$title->{$item}.'",';
}
$resulttext =~ s/,$//;
}
return $resulttext;
}
sub modify_scantron {
my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
my ($resulttext,%confhash,%changes,$errors);
my $custom = 'custom.tab';
my $default = 'default.tab';
my $servadm = $r->dir_config('lonAdmEMail');
my ($configuserok,$author_ok,$switchserver) =
&config_check($dom,$confname,$servadm);
if ($env{'form.scantronformat.filename'} ne '') {
my $error;
if ($configuserok eq 'ok') {
if ($switchserver) {
$error = &mt("Upload of bubblesheet format file is not permitted to this server: [_1]",$switchserver);
} else {
if ($author_ok eq 'ok') {
my ($result,$scantronurl) =
&publishlogo($r,'upload','scantronformat',$dom,
$confname,'scantron','','',$custom);
if ($result eq 'ok') {
$confhash{'scantron'}{'scantronformat'} = $scantronurl;
$changes{'scantronformat'} = 1;
} else {
$error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$custom,$result);
}
} else {
$error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$custom,$confname,$dom,$author_ok);
}
}
} else {
$error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$custom,$confname,$dom,$configuserok);
}
if ($error) {
&Apache::lonnet::logthis($error);
$errors .= '<li><span class="LC_error">'.$error.'</span></li>';
}
}
if (ref($domconfig{'scantron'}) eq 'HASH') {
if ($domconfig{'scantron'}{'scantronformat'} ne '') {
if ($env{'form.scantronformat_del'}) {
$confhash{'scantron'}{'scantronformat'} = '';
$changes{'scantronformat'} = 1;
}
}
}
if (keys(%confhash) > 0) {
my $putresult = &Apache::lonnet::put_dom('configuration',\%confhash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
if (ref($confhash{'scantron'}) eq 'HASH') {
$resulttext = &mt('Changes made:').'<ul>';
if ($confhash{'scantron'}{'scantronformat'} eq '') {
$resulttext .= '<li>'.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).'</li>';
} else {
$resulttext .= '<li>'.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).'</li>';
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('Changes made to bubblesheet format file.');
}
$resulttext .= '</ul>';
&Apache::loncommon::devalidate_domconfig_cache($dom);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domainconfig'} = 1;
}
} else {
$resulttext = &mt('No changes made to bubblesheet format file');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
} else {
$resulttext = &mt('No changes made to bubblesheet format file');
}
if ($errors) {
$resulttext .= &mt('The following errors occurred: ').'<ul>'.
$errors.'</ul>';
}
return $resulttext;
}
sub modify_coursecategories {
my ($dom,%domconfig) = @_;
my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,
$cathash);
my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');
if (ref($domconfig{'coursecategories'}) eq 'HASH') {
$cathash = $domconfig{'coursecategories'}{'cats'};
if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {
$changes{'togglecats'} = 1;
$domconfig{'coursecategories'}{'togglecats'} = $env{'form.togglecats'};
}
if ($domconfig{'coursecategories'}{'categorize'} ne $env{'form.categorize'}) {
$changes{'categorize'} = 1;
$domconfig{'coursecategories'}{'categorize'} = $env{'form.categorize'};
}
if ($domconfig{'coursecategories'}{'togglecatscomm'} ne $env{'form.togglecatscomm'}) {
$changes{'togglecatscomm'} = 1;
$domconfig{'coursecategories'}{'togglecatscomm'} = $env{'form.togglecatscomm'};
}
if ($domconfig{'coursecategories'}{'categorizecomm'} ne $env{'form.categorizecomm'}) {
$changes{'categorizecomm'} = 1;
$domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};
}
} else {
$changes{'togglecats'} = 1;
$changes{'categorize'} = 1;
$changes{'togglecatscomm'} = 1;
$changes{'categorizecomm'} = 1;
$domconfig{'coursecategories'} = {
togglecats => $env{'form.togglecats'},
categorize => $env{'form.categorize'},
togglecatscomm => $env{'form.togglecatscomm'},
categorizecomm => $env{'form.categorizecomm'},
};
}
if (ref($cathash) eq 'HASH') {
if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '') && ($env{'form.instcode'} == 0)) {
push (@deletecategory,'instcode::0');
}
if (($domconfig{'coursecategories'}{'cats'}{'communities::0'} ne '') && ($env{'form.communities'} == 0)) {
push(@deletecategory,'communities::0');
}
}
my (@predelcats,@predeltrails,%predelallitems,%sort_by_deltrail);
if (ref($cathash) eq 'HASH') {
if (@deletecategory > 0) {
#FIXME Need to remove category from all courses using a deleted category
&Apache::loncommon::extract_categories($cathash,\@predelcats,\@predeltrails,\%predelallitems);
foreach my $item (@deletecategory) {
if ($domconfig{'coursecategories'}{'cats'}{$item} ne '') {
delete($domconfig{'coursecategories'}{'cats'}{$item});
$deletions{$item} = 1;
&recurse_cat_deletes($item,$cathash,\%deletions);
}
}
}
foreach my $item (keys(%{$cathash})) {
my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item);
if ($cathash->{$item} ne $env{'form.'.$item}) {
$reorderings{$item} = 1;
$domconfig{'coursecategories'}{'cats'}{$item} = $env{'form.'.$item};
}
if ($env{'form.addcategory_name_'.$item} ne '') {
my $newcat = $env{'form.addcategory_name_'.$item};
my $newdepth = $depth+1;
my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;
$domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos_'.$item};
$adds{$newitem} = 1;
}
if ($env{'form.subcat_'.$item} ne '') {
my $newcat = $env{'form.subcat_'.$item};
my $newdepth = $depth+1;
my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;
$domconfig{'coursecategories'}{'cats'}{$newitem} = 0;
$adds{$newitem} = 1;
}
}
}
if ($env{'form.instcode'} eq '1') {
if (ref($cathash) eq 'HASH') {
my $newitem = 'instcode::0';
if ($cathash->{$newitem} eq '') {
$domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'};
$adds{$newitem} = 1;
}
} else {
my $newitem = 'instcode::0';
$domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'};
$adds{$newitem} = 1;
}
}
if ($env{'form.communities'} eq '1') {
if (ref($cathash) eq 'HASH') {
my $newitem = 'communities::0';
if ($cathash->{$newitem} eq '') {
$domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'};
$adds{$newitem} = 1;
}
} else {
my $newitem = 'communities::0';
$domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'};
$adds{$newitem} = 1;
}
}
if ($env{'form.addcategory_name'} ne '') {
if (($env{'form.addcategory_name'} ne 'instcode') &&
($env{'form.addcategory_name'} ne 'communities')) {
my $newitem = &escape($env{'form.addcategory_name'}).'::0';
$domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos'};
$adds{$newitem} = 1;
}
}
my $putresult;
if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
if (keys(%deletions) > 0) {
foreach my $key (keys(%deletions)) {
if ($predelallitems{$key} ne '') {
$sort_by_deltrail{$predelallitems{$key}} = $predeltrails[$predelallitems{$key}];
}
}
}
my (@chkcats,@chktrails,%chkallitems);
&Apache::loncommon::extract_categories($domconfig{'coursecategories'}{'cats'},\@chkcats,\@chktrails,\%chkallitems);
if (ref($chkcats[0]) eq 'ARRAY') {
my $depth = 0;
my $chg = 0;
for (my $i=0; $i<@{$chkcats[0]}; $i++) {
my $name = $chkcats[0][$i];
my $item;
if ($name eq '') {
$chg ++;
} else {
$item = &escape($name).'::0';
if ($chg) {
$domconfig{'coursecategories'}{'cats'}{$item} -= $chg;
}
$depth ++;
&recurse_check(\@chkcats,$domconfig{'coursecategories'}{'cats'},$depth,$name);
$depth --;
}
}
}
}
if ((keys(%changes) > 0) || (keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
$putresult = &Apache::lonnet::put_dom('configuration',\%domconfig,$dom);
if ($putresult eq 'ok') {
my %title = (
togglecats => 'Show/Hide a course in catalog',
categorize => 'Assign a category to a course',
togglecatscomm => 'Show/Hide a community in catalog',
categorizecomm => 'Assign a category to a community',
);
my %level = (
dom => 'set in Domain ("Modify Course/Community")',
crs => 'set in Course ("Course Configuration")',
comm => 'set in Community ("Community Configuration")',
);
$resulttext = &mt('Changes made:').'<ul>';
if ($changes{'togglecats'}) {
$resulttext .= '<li>'.&mt("$title{'togglecats'} $level{$env{'form.togglecats'}}").'</li>';
}
if ($changes{'categorize'}) {
$resulttext .= '<li>'.&mt("$title{'categorize'} $level{$env{'form.categorize'}}").'</li>';
}
if ($changes{'togglecatscomm'}) {
$resulttext .= '<li>'.&mt("$title{'togglecatscomm'} $level{$env{'form.togglecatscomm'}}").'</li>';
}
if ($changes{'categorizecomm'}) {
$resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';
}
if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
my $cathash;
if (ref($domconfig{'coursecategories'}) eq 'HASH') {
$cathash = $domconfig{'coursecategories'}{'cats'};
} else {
$cathash = {};
}
my (@cats,@trails,%allitems);
&Apache::loncommon::extract_categories($cathash,\@cats,\@trails,\%allitems);
if (keys(%deletions) > 0) {
$resulttext .= '<li>'.&mt('Deleted categories:').'<ul>';
foreach my $predeltrail (sort {$a <=> $b } (keys(%sort_by_deltrail))) {
$resulttext .= '<li>'.$predeltrails[$predeltrail].'</li>';
}
$resulttext .= '</ul></li>';
}
if (keys(%reorderings) > 0) {
my %sort_by_trail;
$resulttext .= '<li>'.&mt('Reordered categories:').'<ul>';
foreach my $key (keys(%reorderings)) {
if ($allitems{$key} ne '') {
$sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];
}
}
foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {
$resulttext .= '<li>'.$trails[$trail].'</li>';
}
$resulttext .= '</ul></li>';
}
if (keys(%adds) > 0) {
my %sort_by_trail;
$resulttext .= '<li>'.&mt('Added categories:').'<ul>';
foreach my $key (keys(%adds)) {
if ($allitems{$key} ne '') {
$sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];
}
}
foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {
$resulttext .= '<li>'.$trails[$trail].'</li>';
}
$resulttext .= '</ul></li>';
}
}
$resulttext .= '</ul>';
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
} else {
$resulttext = &mt('No changes made to course and community categories');
}
return $resulttext;
}
sub modify_serverstatuses {
my ($dom,%domconfig) = @_;
my ($resulttext,%changes,%currserverstatus,%newserverstatus);
if (ref($domconfig{'serverstatuses'}) eq 'HASH') {
%currserverstatus = %{$domconfig{'serverstatuses'}};
}
my @pages = &serverstatus_pages();
foreach my $type (@pages) {
$newserverstatus{$type}{'namedusers'} = '';
$newserverstatus{$type}{'machines'} = '';
if (defined($env{'form.'.$type.'_namedusers'})) {
my @users = split(/,/,$env{'form.'.$type.'_namedusers'});
my @okusers;
foreach my $user (@users) {
my ($uname,$udom) = split(/:/,$user);
if (($udom =~ /^$match_domain$/) &&
(&Apache::lonnet::domain($udom)) &&
($uname =~ /^$match_username$/)) {
if (!grep(/^\Q$user\E/,@okusers)) {
push(@okusers,$user);
}
}
}
if (@okusers > 0) {
@okusers = sort(@okusers);
$newserverstatus{$type}{'namedusers'} = join(',',@okusers);
}
}
if (defined($env{'form.'.$type.'_machines'})) {
my @machines = split(/,/,$env{'form.'.$type.'_machines'});
my @okmachines;
foreach my $ip (@machines) {
my @parts = split(/\./,$ip);
next if (@parts < 4);
my $badip = 0;
for (my $i=0; $i<4; $i++) {
if (!(($parts[$i] >= 0) && ($parts[$i] <= 255))) {
$badip = 1;
last;
}
}
if (!$badip) {
push(@okmachines,$ip);
}
}
@okmachines = sort(@okmachines);
$newserverstatus{$type}{'machines'} = join(',',@okmachines);
}
}
my %serverstatushash = (
serverstatuses => \%newserverstatus,
);
foreach my $type (@pages) {
foreach my $setting ('namedusers','machines') {
my (@current,@new);
if (ref($currserverstatus{$type}) eq 'HASH') {
if ($currserverstatus{$type}{$setting} ne '') {
@current = split(/,/,$currserverstatus{$type}{$setting});
}
}
if ($newserverstatus{$type}{$setting} ne '') {
@new = split(/,/,$newserverstatus{$type}{$setting});
}
if (@current > 0) {
if (@new > 0) {
foreach my $item (@current) {
if (!grep(/^\Q$item\E$/,@new)) {
$changes{$type}{$setting} = 1;
last;
}
}
foreach my $item (@new) {
if (!grep(/^\Q$item\E$/,@current)) {
$changes{$type}{$setting} = 1;
last;
}
}
} else {
$changes{$type}{$setting} = 1;
}
} elsif (@new > 0) {
$changes{$type}{$setting} = 1;
}
}
}
if (keys(%changes) > 0) {
my $titles= &LONCAPA::lonauthcgi::serverstatus_titles();
my $putresult = &Apache::lonnet::put_dom('configuration',
\%serverstatushash,$dom);
if ($putresult eq 'ok') {
$resulttext .= &mt('Changes made:').'<ul>';
foreach my $type (@pages) {
if (ref($changes{$type}) eq 'HASH') {
$resulttext .= '<li>'.$titles->{$type}.'<ul>';
if ($changes{$type}{'namedusers'}) {
if ($newserverstatus{$type}{'namedusers'} eq '') {
$resulttext .= '<li>'.&mt("Access terminated for all specific (named) users").'</li>'."\n";
} else {
$resulttext .= '<li>'.&mt("Access available for the following specified users: ").$newserverstatus{$type}{'namedusers'}.'</li>'."\n";
}
}
if ($changes{$type}{'machines'}) {
if ($newserverstatus{$type}{'machines'} eq '') {
$resulttext .= '<li>'.&mt("Access terminated for all specific IP addresses").'</li>'."\n";
} else {
$resulttext .= '<li>'.&mt("Access available for the following specified IP addresses: ").$newserverstatus{$type}{'machines'}.'</li>'."\n";
}
}
$resulttext .= '</ul></li>';
}
}
$resulttext .= '</ul>';
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred saving access settings for server status pages: [_1].',$putresult).'</span>';
}
} else {
$resulttext = &mt('No changes made to access to server status pages');
}
return $resulttext;
}
sub modify_helpsettings {
my ($r,$dom,$confname,%domconfig) = @_;
my ($resulttext,$errors,%changes,%helphash);
my %defaultchecked = ('submitbugs' => 'on');
my @offon = ('off','on');
my @toggles = ('submitbugs');
if (ref($domconfig{'helpsettings'}) eq 'HASH') {
foreach my $item (@toggles) {
if ($defaultchecked{$item} eq 'on') {
if ($domconfig{'helpsettings'}{$item} eq '') {
if ($env{'form.'.$item} eq '0') {
$changes{$item} = 1;
}
} elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
$changes{$item} = 1;
}
} elsif ($defaultchecked{$item} eq 'off') {
if ($domconfig{'helpsettings'}{$item} eq '') {
if ($env{'form.'.$item} eq '1') {
$changes{$item} = 1;
}
} elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) {
$changes{$item} = 1;
}
}
if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) {
$helphash{'helpsettings'}{$item} = $env{'form.'.$item};
}
}
}
my $putresult;
if (keys(%changes) > 0) {
$putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
if ($putresult eq 'ok') {
$resulttext = &mt('Changes made:').'<ul>';
foreach my $item (sort(keys(%changes))) {
if ($item eq 'submitbugs') {
$resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',
&Apache::loncommon::modal_link('http://bugs.loncapa.org',
&mt('LON-CAPA bug tracker'),600,500)).'</li>';
}
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to help settings');
$errors .= '<li><span class="LC_error">'.
&mt('An error occurred storing the settings: [_1]',
$putresult).'</span></li>';
}
}
if ($errors) {
$resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
$errors.'</ul>';
}
return $resulttext;
}
sub modify_coursedefaults {
my ($dom,$lastactref,%domconfig) = @_;
my ($resulttext,$errors,%changes,%defaultshash);
my %defaultchecked = ('canuse_pdfforms' => 'off');
my @toggles = ('canuse_pdfforms');
my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',
'uploadquota_community','uploadquota_textbook');
my @types = ('official','unofficial','community','textbook');
my %staticdefaults = (
anonsurvey_threshold => 10,
uploadquota => 500,
);
$defaultshash{'coursedefaults'} = {};
if (ref($domconfig{'coursedefaults'}) ne 'HASH') {
if ($domconfig{'coursedefaults'} eq '') {
$domconfig{'coursedefaults'} = {};
}
}
if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
foreach my $item (@toggles) {
if ($defaultchecked{$item} eq 'on') {
if (($domconfig{'coursedefaults'}{$item} eq '') &&
($env{'form.'.$item} eq '0')) {
$changes{$item} = 1;
} elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {
$changes{$item} = 1;
}
} elsif ($defaultchecked{$item} eq 'off') {
if (($domconfig{'coursedefaults'}{$item} eq '') &&
($env{'form.'.$item} eq '1')) {
$changes{$item} = 1;
} elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {
$changes{$item} = 1;
}
}
$defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};
}
foreach my $item (@numbers) {
my ($currdef,$newdef);
$newdef = $env{'form.'.$item};
if ($item eq 'anonsurvey_threshold') {
$currdef = $domconfig{'coursedefaults'}{$item};
$newdef =~ s/\D//g;
if ($newdef eq '' || $newdef < 1) {
$newdef = 1;
}
$defaultshash{'coursedefaults'}{$item} = $newdef;
} else {
my ($type) = ($item =~ /^\Quploadquota_\E(\w+)$/);
if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
$currdef = $domconfig{'coursedefaults'}{'uploadquota'}{$type};
}
$newdef =~ s/[^\w.\-]//g;
$defaultshash{'coursedefaults'}{'uploadquota'}{$type} = $newdef;
}
if ($currdef ne $newdef) {
my $staticdef;
if ($item eq 'anonsurvey_threshold') {
unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
$changes{$item} = 1;
}
} else {
unless (($currdef eq '') && ($newdef == $staticdefaults{'uploadquota'})) {
$changes{'uploadquota'} = 1;
}
}
}
}
my $officialcreds = $env{'form.official_credits'};
$officialcreds =~ s/[^\d.]+//g;
my $unofficialcreds = $env{'form.unofficial_credits'};
$unofficialcreds =~ s/[^\d.]+//g;
my $textbookcreds = $env{'form.textbook_credits'};
$textbookcreds =~ s/[^\d.]+//g;
if (ref($domconfig{'coursedefaults'}{'coursecredits'} ne 'HASH') &&
($env{'form.coursecredits'} eq '1')) {
$changes{'coursecredits'} = 1;
} else {
if (($domconfig{'coursedefaults'}{'coursecredits'}{'official'} ne $officialcreds) ||
($domconfig{'coursedefaults'}{'coursecredits'}{'unofficial'} ne $unofficialcreds) ||
($domconfig{'coursedefaults'}{'coursecredits'}{'textbook'} ne $textbookcreds)) {
$changes{'coursecredits'} = 1;
}
}
$defaultshash{'coursedefaults'}{'coursecredits'} = {
official => $officialcreds,
unofficial => $unofficialcreds,
textbook => $textbookcreds,
}
}
my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
if (($changes{'canuse_pdfforms'}) || ($changes{'coursecredits'}) || ($changes{'uploadquota'})) {
if ($changes{'canuse_pdfforms'}) {
$domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'};
}
if ($changes{'coursecredits'}) {
if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
$domdefaults{'officialcredits'} =
$defaultshash{'coursedefaults'}{'coursecredits'}{'official'};
$domdefaults{'unofficialcredits'} =
$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'};
$domdefaults{'textbookcredits'} =
$domdefaults{'coursedefaults'}{'coursecredits'}{'textbook'};
}
}
if ($changes{'uploadquota'}) {
if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
foreach my $type (@types) {
$domdefaults{$type.'quota'}=$defaultshash{'coursedefaults'}{'uploadquota'}{$type};
}
}
}
my $cachetime = 24*60*60;
&Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domdefaults'} = 1;
}
}
$resulttext = &mt('Changes made:').'<ul>';
foreach my $item (sort(keys(%changes))) {
if ($item eq 'canuse_pdfforms') {
if ($env{'form.'.$item} eq '1') {
$resulttext .= '<li>'.&mt("Course/Community users can create/upload PDF forms set to 'on'").'</li>';
} else {
$resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
}
} elsif ($item eq 'anonsurvey_threshold') {
$resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';
} elsif ($item eq 'uploadquota') {
if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
$resulttext .= '<li>'.&mt('Default quota for content uploaded to a course/community via Course Editor set as follows:').'<ul>'.
'<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.
'<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.
'<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.
'<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.
'</ul>'.
'</li>';
} else {
$resulttext .= '<li>'.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'</li>';
}
} elsif ($item eq 'coursecredits') {
if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
if (($domdefaults{'officialcredits'} eq '') &&
($domdefaults{'unofficialcredits'} eq '') &&
($domdefaults{'textbookcredits'} eq '')) {
$resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
} else {
$resulttext .= '<li>'.&mt('Student credits can be set per course by a Domain Coordinator, with the following defaults applying:').'<ul>'.
'<li>'.&mt('Official courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'official'}).'</li>'.
'<li>'.&mt('Unofficial courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}).'</li>'.
'<li>'.&mt('Textbook courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'textbook'}).'</li>'.
'</ul>'.
'</li>';
}
} else {
$resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
}
}
}
$resulttext .= '</ul>';
} else {
$resulttext = &mt('No changes made to course defaults');
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
return $resulttext;
}
sub modify_usersessions {
my ($dom,$lastactref,%domconfig) = @_;
my @hostingtypes = ('version','excludedomain','includedomain');
my @offloadtypes = ('primary','default');
my %types = (
remote => \@hostingtypes,
hosted => \@hostingtypes,
spares => \@offloadtypes,
);
my @prefixes = ('remote','hosted','spares');
my @lcversions = &Apache::lonnet::all_loncaparevs();
my (%by_ip,%by_location,@intdoms);
&build_location_hashes(\@intdoms,\%by_ip,\%by_location);
my @locations = sort(keys(%by_location));
my (%defaultshash,%changes);
foreach my $prefix (@prefixes) {
$defaultshash{'usersessions'}{$prefix} = {};
}
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
my $resulttext;
my %iphost = &Apache::lonnet::get_iphost();
foreach my $prefix (@prefixes) {
next if ($prefix eq 'spares');
foreach my $type (@{$types{$prefix}}) {
my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
if ($type eq 'version') {
my $value = $env{'form.'.$prefix.'_'.$type};
my $okvalue;
if ($value ne '') {
if (grep(/^\Q$value\E$/,@lcversions)) {
$okvalue = $value;
}
}
if (ref($domconfig{'usersessions'}) eq 'HASH') {
if (ref($domconfig{'usersessions'}{$prefix}) eq 'HASH') {
if ($domconfig{'usersessions'}{$prefix}{$type} ne '') {
if ($inuse == 0) {
$changes{$prefix}{$type} = 1;
} else {
if ($okvalue ne $domconfig{'usersessions'}{$prefix}{$type}) {
$changes{$prefix}{$type} = 1;
}
if ($okvalue ne '') {
$defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
}
}
} else {
if (($inuse == 1) && ($okvalue ne '')) {
$defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
$changes{$prefix}{$type} = 1;
}
}
} else {
if (($inuse == 1) && ($okvalue ne '')) {
$defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
$changes{$prefix}{$type} = 1;
}
}
} else {
if (($inuse == 1) && ($okvalue ne '')) {
$defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
$changes{$prefix}{$type} = 1;
}
}
} else {
my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
my @okvals;
foreach my $val (@vals) {
if ($val =~ /:/) {
my @items = split(/:/,$val);
foreach my $item (@items) {
if (ref($by_location{$item}) eq 'ARRAY') {
push(@okvals,$item);
}
}
} else {
if (ref($by_location{$val}) eq 'ARRAY') {
push(@okvals,$val);
}
}
}
@okvals = sort(@okvals);
if (ref($domconfig{'usersessions'}) eq 'HASH') {
if (ref($domconfig{'usersessions'}{$prefix}) eq 'HASH') {
if (ref($domconfig{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
if ($inuse == 0) {
$changes{$prefix}{$type} = 1;
} else {
$defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
my @changed = &Apache::loncommon::compare_arrays($domconfig{'usersessions'}{$prefix}{$type},$defaultshash{'usersessions'}{$prefix}{$type});
if (@changed > 0) {
$changes{$prefix}{$type} = 1;
}
}
} else {
if ($inuse == 1) {
$defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
$changes{$prefix}{$type} = 1;
}
}
} else {
if ($inuse == 1) {
$defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
$changes{$prefix}{$type} = 1;
}
}
} else {
if ($inuse == 1) {
$defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
$changes{$prefix}{$type} = 1;
}
}
}
}
}
my @alldoms = &Apache::lonnet::all_domains();
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %spareid = ¤t_offloads_to($dom,$domconfig{'usersessions'},\%servers);
my $savespares;
foreach my $lonhost (sort(keys(%servers))) {
my $serverhomeID =
&Apache::lonnet::get_server_homeID($servers{$lonhost});
my $serverhostname = &Apache::lonnet::hostname($lonhost);
$defaultshash{'usersessions'}{'spares'}{$lonhost} = {};
my %spareschg;
foreach my $type (@{$types{'spares'}}) {
my @okspares;
my @checked = &Apache::loncommon::get_env_multiple('form.spare_'.$type.'_'.$lonhost);
foreach my $server (@checked) {
if (&Apache::lonnet::hostname($server) ne '') {
unless (&Apache::lonnet::hostname($server) eq $serverhostname) {
unless (grep(/^\Q$server\E$/,@okspares)) {
push(@okspares,$server);
}
}
}
}
my $new = $env{'form.newspare_'.$type.'_'.$lonhost};
my $newspare;
if (($new ne '') && (&Apache::lonnet::hostname($new))) {
unless (&Apache::lonnet::hostname($new) eq $serverhostname) {
$newspare = $new;
}
}
my @spares;
if (($newspare ne '') && (!grep(/^\Q$newspare\E$/,@okspares))) {
@spares = sort(@okspares,$newspare);
} else {
@spares = sort(@okspares);
}
$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type} = \@spares;
if (ref($spareid{$lonhost}) eq 'HASH') {
if (ref($spareid{$lonhost}{$type}) eq 'ARRAY') {
my @diffs = &Apache::loncommon::compare_arrays($spareid{$lonhost}{$type},\@spares);
if (@diffs > 0) {
$spareschg{$type} = 1;
}
}
}
}
if (keys(%spareschg) > 0) {
$changes{'spares'}{$lonhost} = \%spareschg;
}
}
if (ref($domconfig{'usersessions'}) eq 'HASH') {
if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
if (ref($changes{'spares'}) eq 'HASH') {
if (keys(%{$changes{'spares'}}) > 0) {
$savespares = 1;
}
}
} else {
$savespares = 1;
}
}
my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
if ((keys(%changes) > 0) || ($savespares)) {
my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
$dom);
if ($putresult eq 'ok') {
if (ref($defaultshash{'usersessions'}) eq 'HASH') {
if (ref($defaultshash{'usersessions'}{'remote'}) eq 'HASH') {
$domdefaults{'remotesessions'} = $defaultshash{'usersessions'}{'remote'};
}
if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {
$domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};
}
}
my $cachetime = 24*60*60;
&Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domdefaults'} = 1;
}
if (keys(%changes) > 0) {
my %lt = &usersession_titles();
$resulttext = &mt('Changes made:').'<ul>';
foreach my $prefix (@prefixes) {
if (ref($changes{$prefix}) eq 'HASH') {
$resulttext .= '<li>'.$lt{$prefix}.'<ul>';
if ($prefix eq 'spares') {
if (ref($changes{$prefix}) eq 'HASH') {
foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {
$resulttext .= '<li><b>'.$lonhost.'</b> ';
my $lonhostdom = &Apache::lonnet::host_domain($lonhost);
my $cachekey = &escape('spares').':'.&escape($lonhostdom);
&Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {
foreach my $type (@{$types{$prefix}}) {
if ($changes{$prefix}{$lonhost}{$type}) {
my $offloadto = &mt('None');
if (ref($defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}) eq 'ARRAY') {
if (@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}} > 0) {
$offloadto = join(', ',@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}});
}
}
$resulttext .= &mt('[_1] set to: [_2].','<i>'.$lt{$type}.'</i>',$offloadto).(' 'x3);
}
}
}
$resulttext .= '</li>';
}
}
} else {
foreach my $type (@{$types{$prefix}}) {
if (defined($changes{$prefix}{$type})) {
my $newvalue;
if (ref($defaultshash{'usersessions'}) eq 'HASH') {
if (ref($defaultshash{'usersessions'}{$prefix})) {
if ($type eq 'version') {
$newvalue = $defaultshash{'usersessions'}{$prefix}{$type};
} elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
$newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
}
}
}
}
if ($newvalue eq '') {
if ($type eq 'version') {
$resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';
} else {
$resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
}
} else {
if ($type eq 'version') {
$newvalue .= ' '.&mt('(or later)');
}
$resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
}
}
}
}
$resulttext .= '</ul>';
}
}
$resulttext .= '</ul>';
} else {
$resulttext = $nochgmsg;
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
} else {
$resulttext = $nochgmsg;
}
return $resulttext;
}
sub modify_loadbalancing {
my ($dom,%domconfig) = @_;
my $primary_id = &Apache::lonnet::domain($dom,'primary');
my $intdom = &Apache::lonnet::internet_dom($primary_id);
my ($othertitle,$usertypes,$types) =
&Apache::loncommon::sorted_inst_types($dom);
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my @sparestypes = ('primary','default');
my %typetitles = &sparestype_titles();
my $resulttext;
my (%currbalancer,%currtargets,%currrules,%existing);
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
}
&get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
\%currtargets,\%currrules);
my ($saveloadbalancing,%defaultshash,%changes);
my ($alltypes,$othertypes,$titles) =
&loadbalancing_titles($dom,$intdom,$usertypes,$types);
my %ruletitles = &offloadtype_text();
my @deletions = &Apache::loncommon::get_env_multiple('form.loadbalancing_delete');
for (my $i=0; $i<$env{'form.loadbalancing_total'}; $i++) {
my $balancer = $env{'form.loadbalancing_lonhost_'.$i};
if ($balancer eq '') {
next;
}
if (!exists($servers{$balancer})) {
if (exists($currbalancer{$balancer})) {
push(@{$changes{'delete'}},$balancer);
}
next;
}
if ((@deletions > 0) && (grep(/^\Q$i\E$/,@deletions))) {
push(@{$changes{'delete'}},$balancer);
next;
}
if (!exists($currbalancer{$balancer})) {
push(@{$changes{'add'}},$balancer);
}
$defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'} = [];
$defaultshash{'loadbalancing'}{$balancer}{'targets'}{'default'} = [];
$defaultshash{'loadbalancing'}{$balancer}{'rules'} = {};
unless (ref($domconfig{'loadbalancing'}) eq 'HASH') {
$saveloadbalancing = 1;
}
foreach my $sparetype (@sparestypes) {
my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$i.'_'.$sparetype);
my @offloadto;
foreach my $target (@targets) {
if (($servers{$target}) && ($target ne $balancer)) {
if ($sparetype eq 'default') {
if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}) eq 'ARRAY') {
next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}}));
}
}
unless(grep(/^\Q$target\E$/,@offloadto)) {
push(@offloadto,$target);
}
}
$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
}
}
if (ref($currtargets{$balancer}) eq 'HASH') {
foreach my $sparetype (@sparestypes) {
if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets{$balancer}{$sparetype},$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype});
if (@targetdiffs > 0) {
$changes{'curr'}{$balancer}{'targets'} = 1;
}
} elsif (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
$changes{'curr'}{$balancer}{'targets'} = 1;
}
}
}
} else {
if (ref($defaultshash{'loadbalancing'}{$balancer}) eq 'HASH') {
foreach my $sparetype (@sparestypes) {
if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
$changes{'curr'}{$balancer}{'targets'} = 1;
}
}
}
}
}
my $ishomedom;
if (&Apache::lonnet::host_domain($balancer) eq $dom) {
$ishomedom = 1;
}
if (ref($alltypes) eq 'ARRAY') {
foreach my $type (@{$alltypes}) {
my $rule;
unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) &&
(!$ishomedom)) {
$rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type};
}
if ($rule eq 'specific') {
$rule = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};
}
$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule;
if (ref($currrules{$balancer}) eq 'HASH') {
if ($rule ne $currrules{$balancer}{$type}) {
$changes{'curr'}{$balancer}{'rules'}{$type} = 1;
}
} elsif ($rule ne '') {
$changes{'curr'}{$balancer}{'rules'}{$type} = 1;
}
}
}
}
my $nochgmsg = &mt('No changes made to Load Balancer settings.');
if ((keys(%changes) > 0) || ($saveloadbalancing)) {
unless (ref($defaultshash{'loadbalancing'}) eq 'HASH') {
$defaultshash{'loadbalancing'} = {};
}
my $putresult = &Apache::lonnet::put_dom('configuration',
\%defaultshash,$dom);
if ($putresult eq 'ok') {
if (keys(%changes) > 0) {
if (ref($changes{'delete'}) eq 'ARRAY') {
foreach my $balancer (sort(@{$changes{'delete'}})) {
$resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';
my $cachekey = &escape('loadbalancing').':'.&escape($dom);
&Apache::lonnet::remote_devalidate_cache($balancer,[$cachekey]);
}
}
if (ref($changes{'add'}) eq 'ARRAY') {
foreach my $balancer (sort(@{$changes{'add'}})) {
$resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);
}
}
if (ref($changes{'curr'}) eq 'HASH') {
foreach my $balancer (sort(keys(%{$changes{'curr'}}))) {
if (ref($changes{'curr'}{$balancer}) eq 'HASH') {
if ($changes{'curr'}{$balancer}{'targets'}) {
my %offloadstr;
foreach my $sparetype (@sparestypes) {
if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
$offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
}
}
}
if (keys(%offloadstr) == 0) {
$resulttext .= '<li>'.&mt("Servers to which Load Balance server offloads set to 'None', by default").'</li>';
} else {
my $showoffload;
foreach my $sparetype (@sparestypes) {
$showoffload .= '<i>'.$typetitles{$sparetype}.'</i>: ';
if (defined($offloadstr{$sparetype})) {
$showoffload .= $offloadstr{$sparetype};
} else {
$showoffload .= &mt('None');
}
$showoffload .= (' 'x3);
}
$resulttext .= '<li>'.&mt('By default, Load Balancer: [_1] set to offload to - [_2]',$balancer,$showoffload).'</li>';
}
}
}
if (ref($changes{'curr'}{$balancer}{'rules'}) eq 'HASH') {
if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
foreach my $type (@{$alltypes}) {
if ($changes{'curr'}{$balancer}{'rules'}{$type}) {
my $rule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};
my $balancetext;
if ($rule eq '') {
$balancetext = $ruletitles{'default'};
} elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') ||
($rule eq 'balancer') || ($rule eq 'offloadedto')) {
$balancetext = $ruletitles{$rule};
} else {
$balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type});
}
$resulttext .= '<li>'.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'</li>';
}
}
}
}
my $cachekey = &escape('loadbalancing').':'.&escape($dom);
&Apache::lonnet::remote_devalidate_cache($balancer,[$cachekey]);
}
}
if ($resulttext ne '') {
$resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';
} else {
$resulttext = $nochgmsg;
}
} else {
$resulttext = $nochgmsg;
}
} else {
$resulttext = '<span class="LC_error">'.
&mt('An error occurred: [_1]',$putresult).'</span>';
}
} else {
$resulttext = $nochgmsg;
}
return $resulttext;
}
sub recurse_check {
my ($chkcats,$categories,$depth,$name) = @_;
if (ref($chkcats->[$depth]{$name}) eq 'ARRAY') {
my $chg = 0;
for (my $j=0; $j<@{$chkcats->[$depth]{$name}}; $j++) {
my $category = $chkcats->[$depth]{$name}[$j];
my $item;
if ($category eq '') {
$chg ++;
} else {
my $deeper = $depth + 1;
$item = &escape($category).':'.&escape($name).':'.$depth;
if ($chg) {
$categories->{$item} -= $chg;
}
&recurse_check($chkcats,$categories,$deeper,$category);
$deeper --;
}
}
}
return;
}
sub recurse_cat_deletes {
my ($item,$coursecategories,$deletions) = @_;
my ($deleted,$container,$depth) = map { &unescape($_); } split(/:/,$item);
my $subdepth = $depth + 1;
if (ref($coursecategories) eq 'HASH') {
foreach my $subitem (keys(%{$coursecategories})) {
my ($child,$parent,$itemdepth) = map { &unescape($_); } split(/:/,$subitem);
if (($parent eq $deleted) && ($itemdepth == $subdepth)) {
delete($coursecategories->{$subitem});
$deletions->{$subitem} = 1;
&recurse_cat_deletes($subitem,$coursecategories,$deletions);
}
}
}
return;
}
sub get_active_dcs {
my ($dom) = @_;
my $now = time;
my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now);
my %domcoords;
my $numdcs = 0;
foreach my $server (keys(%dompersonnel)) {
foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user);
$domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user};
}
}
return %domcoords;
}
sub active_dc_picker {
my ($dom,$numinrow,$inputtype,$name,%currhash) = @_;
my %domcoords = &get_active_dcs($dom);
my @domcoord = keys(%domcoords);
if (keys(%currhash)) {
foreach my $dc (keys(%currhash)) {
unless (exists($domcoords{$dc})) {
push(@domcoord,$dc);
}
}
}
@domcoord = sort(@domcoord);
my $numdcs = scalar(@domcoord);
my $rows = 0;
my $table;
if ($numdcs > 1) {
$table = '<table>';
for (my $i=0; $i<@domcoord; $i++) {
my $rem = $i%($numinrow);
if ($rem == 0) {
if ($i > 0) {
$table .= '</tr>';
}
$table .= '<tr>';
$rows ++;
}
my $check = '';
if ($inputtype eq 'radio') {
if (keys(%currhash) == 0) {
if (!$i) {
$check = ' checked="checked"';
}
} elsif (exists($currhash{$domcoord[$i]})) {
$check = ' checked="checked"';
}
} else {
if (exists($currhash{$domcoord[$i]})) {
$check = ' checked="checked"';
}
}
if ($i == @domcoord - 1) {
my $colsleft = $numinrow - $rem;
if ($colsleft > 1) {
$table .= '<td class="LC_left_item" colspan="'.$colsleft.'">';
} else {
$table .= '<td class="LC_left_item">';
}
} else {
$table .= '<td class="LC_left_item">';
}
my ($dcname,$dcdom) = split(':',$domcoord[$i]);
my $user = &Apache::loncommon::plainname($dcname,$dcdom);
$table .= '<span class="LC_nobreak"><label>'.
'<input type="'.$inputtype.'" name="'.$name.'"'.
' value="'.$domcoord[$i].'"'.$check.' />'.$user;
if ($user ne $dcname.':'.$dcdom) {
$table .= ' ('.$dcname.':'.$dcdom.')';
}
$table .= '</label></span></td>';
}
$table .= '</tr></table>';
} elsif ($numdcs == 1) {
my ($dcname,$dcdom) = split(':',$domcoord[0]);
my $user = &Apache::loncommon::plainname($dcname,$dcdom);
if ($inputtype eq 'radio') {
$table .= '<input type="hidden" name="'.$name.'" value="'.$domcoord[0].'" />'.$user;
if ($user ne $dcname.':'.$dcdom) {
$table .= ' ('.$dcname.':'.$dcdom.')';
}
} else {
my $check;
if (exists($currhash{$domcoord[0]})) {
$check = ' checked="checked"';
}
$table .= '<span class="LC_nobreak"><label>'.
'<input type="checkbox" name="'.$name.'" '.
'value="'.$domcoord[0].'"'.$check.' />'.$user;
if ($user ne $dcname.':'.$dcdom) {
$table .= ' ('.$dcname.':'.$dcdom.')';
}
$table .= '</label></span>';
$rows ++;
}
}
return ($numdcs,$table,$rows);
}
sub usersession_titles {
return &Apache::lonlocal::texthash(
hosted => 'Hosting of sessions for users from other domains on servers in this domain',
remote => 'Hosting of sessions for users in this domain on servers in other domains',
spares => 'Servers offloaded to, when busy',
version => 'LON-CAPA version requirement',
excludedomain => 'Allow all, but exclude specific domains',
includedomain => 'Deny all, but include specific domains',
primary => 'Primary (checked first)',
default => 'Default',
);
}
sub id_for_thisdom {
my (%servers) = @_;
my %altids;
foreach my $server (keys(%servers)) {
my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
if ($serverhome ne $server) {
$altids{$serverhome} = $server;
}
}
return %altids;
}
sub count_servers {
my ($currbalancer,%servers) = @_;
my (@spares,$numspares);
foreach my $lonhost (sort(keys(%servers))) {
next if ($currbalancer eq $lonhost);
push(@spares,$lonhost);
}
if ($currbalancer) {
$numspares = scalar(@spares);
} else {
$numspares = scalar(@spares) - 1;
}
return ($numspares,@spares);
}
sub lonbalance_targets_js {
my ($dom,$types,$servers,$settings) = @_;
my $select = &mt('Select');
my ($alltargets,$allishome,$allinsttypes,@alltypes);
if (ref($servers) eq 'HASH') {
$alltargets = join("','",sort(keys(%{$servers})));
my @homedoms;
foreach my $server (sort(keys(%{$servers}))) {
if (&Apache::lonnet::host_domain($server) eq $dom) {
push(@homedoms,'1');
} else {
push(@homedoms,'0');
}
}
$allishome = join("','",@homedoms);
}
if (ref($types) eq 'ARRAY') {
if (@{$types} > 0) {
@alltypes = @{$types};
}
}
push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
$allinsttypes = join("','",@alltypes);
my (%currbalancer,%currtargets,%currrules,%existing);
if (ref($settings) eq 'HASH') {
%existing = %{$settings};
}
&get_loadbalancers_config($servers,\%existing,\%currbalancer,
\%currtargets,\%currrules);
my $balancers = join("','",sort(keys(%currbalancer)));
return <<"END";
<script type="text/javascript">
// <![CDATA[
currBalancers = new Array('$balancers');
function toggleTargets(balnum) {
var lonhostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
var prevhostitem = document.getElementById('loadbalancing_prevlonhost_'+balnum);
var balancer = lonhostitem.options[lonhostitem.selectedIndex].value;
var prevbalancer = prevhostitem.value;
var baltotal = document.getElementById('loadbalancing_total').value;
prevhostitem.value = balancer;
if (prevbalancer != '') {
var prevIdx = currBalancers.indexOf(prevbalancer);
if (prevIdx != -1) {
currBalancers.splice(prevIdx,1);
}
}
if (balancer == '') {
hideSpares(balnum);
} else {
var currIdx = currBalancers.indexOf(balancer);
if (currIdx == -1) {
currBalancers.push(balancer);
}
var homedoms = new Array('$allishome');
var ishomedom = homedoms[lonhostitem.selectedIndex];
showSpares(balancer,ishomedom,balnum);
}
balancerChange(balnum,baltotal,'change',prevbalancer,balancer);
return;
}
function showSpares(balancer,ishomedom,balnum) {
var alltargets = new Array('$alltargets');
var insttypes = new Array('$allinsttypes');
var offloadtypes = new Array('primary','default');
document.getElementById('loadbalancing_targets_'+balnum).style.display='block';
document.getElementById('loadbalancing_disabled_'+balnum).style.display='none';
for (var i=0; i<offloadtypes.length; i++) {
var count = 0;
for (var j=0; j<alltargets.length; j++) {
if (alltargets[j] != balancer) {
var item = document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+count);
item.value = alltargets[j];
item.style.textAlign='left';
item.style.textFace='normal';
document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+count).innerHTML = alltargets[j];
if (currBalancers.indexOf(alltargets[j]) == -1) {
item.disabled = '';
} else {
item.disabled = 'disabled';
item.checked = false;
}
count ++;
}
}
}
for (var k=0; k<insttypes.length; k++) {
if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {
if (ishomedom == 1) {
document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
} else {
document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
}
} else {
document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
}
if ((insttypes[k] != '_LC_external') &&
((insttypes[k] != '_LC_internetdom') ||
((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {
var item = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]);
item.options.length = 0;
item.options[0] = new Option("","",true,true);
var idx = 0;
for (var m=0; m<alltargets.length; m++) {
if ((currBalancers.indexOf(alltargets[m]) == -1) && (alltargets[m] != balancer)) {
idx ++;
item.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
}
}
}
}
return;
}
function hideSpares(balnum) {
var alltargets = new Array('$alltargets');
var insttypes = new Array('$allinsttypes');
var offloadtypes = new Array('primary','default');
document.getElementById('loadbalancing_targets_'+balnum).style.display='none';
document.getElementById('loadbalancing_disabled_'+balnum).style.display='block';
var total = alltargets.length - 1;
for (var i=0; i<offloadtypes; i++) {
for (var j=0; j<total; j++) {
document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).checked = false;
document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).value = '';
document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+j).innerHTML = '';
}
}
for (var k=0; k<insttypes.length; k++) {
document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
if (insttypes[k] != '_LC_external') {
document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).length = 0;
document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).options[0] = new Option("","",true,true);
}
}
return;
}
function checkOffloads(item,balnum,type) {
var alltargets = new Array('$alltargets');
var offloadtypes = new Array('primary','default');
if (item.checked) {
var total = alltargets.length - 1;
var other;
if (type == offloadtypes[0]) {
other = offloadtypes[1];
} else {
other = offloadtypes[0];
}
for (var i=0; i<total; i++) {
var server = document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).value;
if (server == item.value) {
if (document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked) {
document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked = false;
}
}
}
}
return;
}
function singleServerToggle(balnum,type) {
var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex;
if (offloadtoSelIdx == 0) {
document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_0').checked = true;
document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
} else {
document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_2').checked = true;
document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
}
return;
}
function balanceruleChange(formname,balnum,type) {
if (type == '_LC_external') {
return;
}
var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+balnum+'_'+type);
for (var i=0; i<typesRules.length; i++) {
if (formname.elements[typesRules[i]].checked) {
if (formname.elements[typesRules[i]].value != 'specific') {
document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex = 0;
document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
} else {
document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
}
}
}
return;
}
function balancerDeleteChange(balnum) {
var hostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
var baltotal = document.getElementById('loadbalancing_total').value;
var addtarget;
var removetarget;
var action = 'delete';
if (document.getElementById('loadbalancing_delete_'+balnum)) {
var lonhost = hostitem.value;
var currIdx = currBalancers.indexOf(lonhost);
if (document.getElementById('loadbalancing_delete_'+balnum).checked) {
if (currIdx != -1) {
currBalancers.splice(currIdx,1);
}
addtarget = lonhost;
} else {
if (currIdx == -1) {
currBalancers.push(lonhost);
}
removetarget = lonhost;
action = 'undelete';
}
balancerChange(balnum,baltotal,action,addtarget,removetarget);
}
return;
}
function balancerChange(balnum,baltotal,action,addtarget,removetarget) {
if (baltotal > 1) {
var offloadtypes = new Array('primary','default');
var alltargets = new Array('$alltargets');
var insttypes = new Array('$allinsttypes');
for (var i=0; i<baltotal; i++) {
if (i != balnum) {
for (var j=0; j<offloadtypes.length; j++) {
var total = alltargets.length - 1;
for (var k=0; k<total; k++) {
var serveritem = document.getElementById('loadbalancing_target_'+i+'_'+offloadtypes[j]+'_'+k);
var server = serveritem.value;
if ((action == 'delete') || (action == 'change' && addtarget != '')) {
if (server == addtarget) {
serveritem.disabled = '';
}
}
if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
if (server == removetarget) {
serveritem.disabled = 'disabled';
serveritem.checked = false;
}
}
}
}
for (var j=0; j<insttypes.length; j++) {
if (insttypes[j] != '_LC_external') {
if (document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j])) {
var singleserver = document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j]);
var currSel = singleserver.selectedIndex;
var currVal = singleserver.options[currSel].value;
if ((action == 'delete') || (action == 'change' && addtarget != '')) {
var numoptions = singleserver.options.length;
var needsnew = 1;
for (var k=0; k<numoptions; k++) {
if (singleserver.options[k] == addtarget) {
needsnew = 0;
break;
}
}
if (needsnew == 1) {
singleserver.options[numoptions] = new Option(addtarget,addtarget,false,false);
}
}
if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
singleserver.options.length = 0;
if ((currVal) && (currVal != removetarget)) {
singleserver.options[0] = new Option("","",false,false);
} else {
singleserver.options[0] = new Option("","",true,true);
}
var idx = 0;
for (var m=0; m<alltargets.length; m++) {
if (currBalancers.indexOf(alltargets[m]) == -1) {
idx ++;
if (currVal == alltargets[m]) {
singleserver.options[idx] = new Option(alltargets[m],alltargets[m],true,true);
} else {
singleserver.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
}
}
}
}
}
}
}
}
}
}
return;
}
// ]]>
</script>
END
}
sub new_spares_js {
my @sparestypes = ('primary','default');
my $types = join("','",@sparestypes);
my $select = &mt('Select');
return <<"END";
<script type="text/javascript">
// <![CDATA[
function updateNewSpares(formname,lonhost) {
var types = new Array('$types');
var include = new Array();
var exclude = new Array();
for (var i=0; i<types.length; i++) {
var spareboxes = getIndicesByName(formname,'spare_'+types[i]+'_'+lonhost);
for (var j=0; j<spareboxes.length; j++) {
if (formname.elements[spareboxes[j]].checked) {
exclude.push(formname.elements[spareboxes[j]].value);
} else {
include.push(formname.elements[spareboxes[j]].value);
}
}
}
for (var i=0; i<types.length; i++) {
var newSpare = document.getElementById('newspare_'+types[i]+'_'+lonhost);
var selIdx = newSpare.selectedIndex;
var currnew = newSpare.options[selIdx].value;
var okSpares = new Array();
for (var j=0; j<newSpare.options.length; j++) {
var possible = newSpare.options[j].value;
if (possible != '') {
if (exclude.indexOf(possible) == -1) {
okSpares.push(possible);
} else {
if (currnew == possible) {
selIdx = 0;
}
}
}
}
for (var k=0; k<include.length; k++) {
if (okSpares.indexOf(include[k]) == -1) {
okSpares.push(include[k]);
}
}
okSpares.sort();
newSpare.options.length = 0;
if (selIdx == 0) {
newSpare.options[0] = new Option("$select","",true,true);
} else {
newSpare.options[0] = new Option("$select","",false,false);
}
for (var m=0; m<okSpares.length; m++) {
var idx = m+1;
var selThis = 0;
if (selIdx != 0) {
if (okSpares[m] == currnew) {
selThis = 1;
}
}
if (selThis == 1) {
newSpare.options[idx] = new Option(okSpares[m],okSpares[m],true,true);
} else {
newSpare.options[idx] = new Option(okSpares[m],okSpares[m],false,false);
}
}
}
return;
}
function checkNewSpares(lonhost,type) {
var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);
var chosen = newSpare.options[newSpare.selectedIndex].value;
if (chosen != '') {
var othertype;
var othernewSpare;
if (type == 'primary') {
othernewSpare = document.getElementById('newspare_default_'+lonhost);
}
if (type == 'default') {
othernewSpare = document.getElementById('newspare_primary_'+lonhost);
}
if (othernewSpare.options[othernewSpare.selectedIndex].value == chosen) {
othernewSpare.selectedIndex = 0;
}
}
return;
}
// ]]>
</script>
END
}
sub common_domprefs_js {
return <<"END";
<script type="text/javascript">
// <![CDATA[
function getIndicesByName(formname,item) {
var group = new Array();
for (var i=0;i<formname.elements.length;i++) {
if (formname.elements[i].name == item) {
group.push(formname.elements[i].id);
}
}
return group;
}
// ]]>
</script>
END
}
sub recaptcha_js {
my %lt = &captcha_phrases();
return <<"END";
<script type="text/javascript">
// <![CDATA[
function updateCaptcha(caller,context) {
var privitem;
var pubitem;
var privtext;
var pubtext;
if (document.getElementById(context+'_recaptchapub')) {
pubitem = document.getElementById(context+'_recaptchapub');
} else {
return;
}
if (document.getElementById(context+'_recaptchapriv')) {
privitem = document.getElementById(context+'_recaptchapriv');
} else {
return;
}
if (document.getElementById(context+'_recaptchapubtxt')) {
pubtext = document.getElementById(context+'_recaptchapubtxt');
} else {
return;
}
if (document.getElementById(context+'_recaptchaprivtxt')) {
privtext = document.getElementById(context+'_recaptchaprivtxt');
} else {
return;
}
if (caller.checked) {
if (caller.value == 'recaptcha') {
pubitem.type = 'text';
privitem.type = 'text';
pubitem.size = '40';
privitem.size = '40';
pubtext.innerHTML = "$lt{'pub'}";
privtext.innerHTML = "$lt{'priv'}";
} else {
pubitem.type = 'hidden';
privitem.type = 'hidden';
pubtext.innerHTML = '';
privtext.innerHTML = '';
}
}
return;
}
// ]]>
</script>
END
}
sub credits_js {
return <<"END";
<script type="text/javascript">
// <![CDATA[
function toggleCredits(domForm) {
if (document.getElementById('credits')) {
creditsitem = document.getElementById('credits');
var creditsLength = domForm.coursecredits.length;
if (creditsLength) {
var currval;
for (var i=0; i<creditsLength; i++) {
if (domForm.coursecredits[i].checked) {
currval = domForm.coursecredits[i].value;
}
}
if (currval == 1) {
creditsitem.style.display = 'block';
} else {
creditsitem.style.display = 'none';
}
}
}
return;
}
// ]]>
</script>
END
}
sub captcha_phrases {
return &Apache::lonlocal::texthash (
priv => 'Private key',
pub => 'Public key',
original => 'original (CAPTCHA)',
recaptcha => 'successor (ReCAPTCHA)',
notused => 'unused',
);
}
sub devalidate_remote_domconfs {
my ($dom,$cachekeys) = @_;
return unless (ref($cachekeys) eq 'HASH');
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %thismachine;
map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
my @posscached = ('domainconfig','domdefaults');
if (keys(%servers) > 1) {
foreach my $server (keys(%servers)) {
next if ($thismachine{$server});
my @cached;
foreach my $name (@posscached) {
if ($cachekeys->{$name}) {
push(@cached,&escape($name).':'.&escape($dom));
}
}
if (@cached) {
&Apache::lonnet::remote_devalidate_cache($server,\@cached);
}
}
}
return;
}
1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>