--- loncom/interface/domainprefs.pm 2011/08/17 11:16:59 1.154 +++ loncom/interface/domainprefs.pm 2013/09/22 01:54:13 1.160.6.25 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.154 2011/08/17 11:16:59 raeburn Exp $ +# $Id: domainprefs.pm,v 1.160.6.25 2013/09/22 01:54:13 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -45,7 +45,7 @@ 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 affliated with the institution. Accordingly, each domain +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. @@ -86,15 +86,17 @@ $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 (either quotas -or requestcourses). +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. +used by course owners to request creation of a course, and to display/store +default quota sizes for authoring spaces. + Outputs: 1 @@ -171,6 +173,9 @@ use Locale::Language; use DateTime::TimeZone; use DateTime::Locale; +my $registered_cleanup; +my $modified_urls; + sub handler { my $r=shift; if ($r->header_only) { @@ -190,6 +195,10 @@ sub handler { "/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']); @@ -203,14 +212,18 @@ sub handler { 'quotas','autoenroll','autoupdate','autocreate', 'directorysrch','usercreation','usermodification', 'contacts','defaults','scantron','coursecategories', - 'serverstatuses','requestcourses','helpsettings', - 'coursedefaults','usersessions','loadbalancing'],$dom); + 'serverstatuses','requestcourses','coursedefaults', + 'usersessions','loadbalancing','requestauthor'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', 'autoupdate','autocreate','directorysrch','contacts', 'usercreation','usermodification','scantron', - 'requestcourses','coursecategories','serverstatuses','helpsettings', - 'coursedefaults','usersessions'); - if (keys(%servers) > 1) { + 'requestcourses','requestauthor','coursecategories', + 'serverstatuses','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 = ( @@ -229,10 +242,11 @@ sub handler { 'login' => { text => 'Log-in page options', help => 'Domain_Configuration_Login_Page', - header => [{col1 => 'Item', - col2 => '',}], + header => [{col1 => 'Log-in Page Items', + col2 => '',}, + {col1 => 'Log-in Help', + col2 => 'Value'}], }, - 'defaults' => { text => 'Default authentication/language/timezone/portal', help => 'Domain_Configuration_LangTZAuth', @@ -240,11 +254,11 @@ sub handler { col2 => 'Value'}], }, 'quotas' => - { text => 'User blogs, personal information pages, portfolios', + { text => 'Blogs, personal web pages, webDAV/quotas, portfolios', help => 'Domain_Configuration_Quotas', header => [{col1 => 'User affiliation', col2 => 'Available tools', - col3 => 'Portfolio quota',}], + col3 => 'Quotas, Mb; (Authoring requires role)',}], }, 'autoenroll' => { text => 'Auto-enrollment settings', @@ -316,6 +330,14 @@ sub handler { {col1 => 'Setting', col2 => 'Value'}], }, + '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', @@ -333,28 +355,12 @@ sub handler { col3 => 'Specific IPs', }], }, - 'helpsettings' => - {text => 'Help page settings', - help => 'Domain_Configuration_Help_Settings', - header => [{col1 => 'Authenticated Help Settings', - col2 => ''}, - {col1 => 'Unauthenticated Help Settings', - col2 => ''}], - }, - 'coursedefaults' => + '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', + header => [{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', @@ -366,11 +372,11 @@ sub handler { col2 => 'Rules'}], }, 'loadbalancing' => - {text => 'Dedicated Load Balancer', + {text => 'Dedicated Load Balancer(s)', help => 'Domain_Configuration_Load_Balancing', - header => [{col1 => 'Server', + header => [{col1 => 'Balancers', col2 => 'Default destinations', - col3 => 'User affliation', + col3 => 'User affiliation', col4 => 'Overrides'}, ], }, @@ -381,29 +387,67 @@ sub handler { header => [{col1 => 'Log-in Service', col2 => 'Server Setting',}, {col1 => 'Log-in Page Items', - col2 => ''}], + 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') { - &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles); + if (&Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order, + \%prefs,\%domconfig,$confname,\@roles) eq 'update') { + $r->rflush(); + &devalidate_remote_domconfs($dom); + } } elsif ($phase eq 'display') { - my $js; - if (keys(%servers) > 1) { + 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). - &new_spares_js(). - &common_domprefs_js(). - &Apache::loncommon::javascript_array_indexof(); + $js .= &lonbalance_targets_js($dom,$types,\%servers, + $domconfig{'loadbalancing'}). + &new_spares_js(). + &common_domprefs_js(). + &Apache::loncommon::javascript_array_indexof(); } &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). + '
' + ); + 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.'). + '
'. + &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.'). + '
'. + &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). + '
'. + &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.'). + '
'. + &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(); @@ -443,21 +487,21 @@ sub handler { } sub process_changes { - my ($r,$dom,$confname,$action,$roles,$values) = @_; + 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,%domconfig); + $output = &modify_login($r,$dom,$confname,$lastactref,%domconfig); } elsif ($action eq 'rolecolors') { $output = &modify_rolecolors($r,$dom,$confname,$roles, - %domconfig); + $lastactref,%domconfig); } elsif ($action eq 'quotas') { $output = &modify_quotas($dom,$action,%domconfig); } elsif ($action eq 'autoenroll') { - $output = &modify_autoenroll($dom,%domconfig); + $output = &modify_autoenroll($dom,$lastactref,%domconfig); } elsif ($action eq 'autoupdate') { $output = &modify_autoupdate($dom,%domconfig); } elsif ($action eq 'autocreate') { @@ -469,19 +513,19 @@ sub process_changes { } elsif ($action eq 'usermodification') { $output = &modify_usermodification($dom,%domconfig); } elsif ($action eq 'contacts') { - $output = &modify_contacts($dom,%domconfig); + $output = &modify_contacts($dom,$lastactref,%domconfig); } elsif ($action eq 'defaults') { - $output = &modify_defaults($dom,$r); + $output = &modify_defaults($dom,$r,%domconfig); } elsif ($action eq 'scantron') { - $output = &modify_scantron($r,$dom,$confname,%domconfig); + $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($dom,$action,%domconfig); - } elsif ($action eq 'helpsettings') { - $output = &modify_helpsettings($r,$dom,$confname,%domconfig); + } elsif ($action eq 'requestauthor') { + $output = &modify_quotas($dom,$action,%domconfig); } elsif ($action eq 'coursedefaults') { $output = &modify_coursedefaults($dom,%domconfig); } elsif ($action eq 'usersessions') { @@ -514,7 +558,8 @@ sub print_config_box { if ($numheaders > 1) { my $colspan = ''; my $rightcolspan = ''; - if (($action eq 'rolecolors') || ($action eq 'coursecategories') || ($action eq 'helpsettings')) { + if (($action eq 'rolecolors') || ($action eq 'coursecategories') || + (($action eq 'login') && ($numheaders < 3))) { $colspan = ' colspan="2"'; } if ($action eq 'usersessions') { @@ -538,18 +583,20 @@ sub print_config_box { } elsif ($action eq 'coursecategories') { $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal); } elsif ($action eq 'login') { - $output .= &print_login('top',$dom,$confname,$phase,$settings,\$rowtotal); - $colspan = ' colspan="2"'; + 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 'helpsettings') { - $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal); + } 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 .= ' @@ -606,11 +653,26 @@ sub print_config_box { } elsif ($action eq 'coursecategories') { $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); } elsif ($action eq 'login') { - $output .= &print_login('bottom',$dom,$confname,$phase,$settings,\$rowtotal); + if ($numheaders == 3) { + $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).' + + + + + + + + + '. + &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_courserequestmail($dom,$settings,\$rowtotal); - } elsif ($action eq 'helpsettings') { - $output .= &print_helpsettings('bottom',$dom,$confname,$settings,\$rowtotal); + $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); + } elsif ($action eq 'requestauthor') { + $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); } elsif ($action eq 'usersessions') { $output .= &print_usersessions('middle',$dom,$settings,\$rowtotal).'
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
@@ -624,8 +686,6 @@ sub print_config_box { '.&mt($item->{'header'}->[2]->{'col2'}).' '. &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).' @@ -702,10 +762,7 @@ sub print_config_box { } $output .= ''; $rowtotal ++; - if ($action eq 'login') { - $output .= &print_login('bottom',$dom,$confname,$phase,$settings, - \$rowtotal); - } elsif ($action eq 'quotas') { + if ($action eq 'quotas') { $output .= &print_quotas($dom,$settings,\$rowtotal,$action); } elsif ($action eq 'autoenroll') { $output .= &print_autoenroll($dom,$settings,\$rowtotal); @@ -722,9 +779,11 @@ sub print_config_box { } elsif ($action eq 'serverstatuses') { $output .= &print_serverstatuses($dom,$settings,\$rowtotal); } elsif ($action eq 'helpsettings') { - $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal); + $output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal); } elsif ($action eq 'loadbalancing') { $output .= &print_loadbalancing($dom,$settings,\$rowtotal); + } elsif ($action eq 'coursedefaults') { + $output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal); } } $output .= ' @@ -736,11 +795,11 @@ sub print_config_box { } sub print_login { - my ($position,$dom,$confname,$phase,$settings,$rowtotal) = @_; + my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_; my ($css_class,$datatable); my %choices = &login_choices(); - if ($position eq 'top') { + if ($caller eq 'service') { my %servers = &Apache::lonnet::internet_dom_servers($dom); my $choice = $choices{'disallowlogin'}; $css_class = ' class="LC_odd_row"'; @@ -767,7 +826,7 @@ sub print_login { ''.&mt('Yes'). + ' '. + ''; + $itemcount ++; } - foreach my $item (@images) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext); + $datatable .= ''; + } 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 $item (@bgs) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + foreach my $lang ('nolang',sort(@currlangs)) { + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''; + if ($url{$lang} eq '') { + $url{$lang} = $defaulturl; + } + if ($type{$lang} eq '') { + $type{$lang} = $defaulttype; + } + $datatable .= ''; + 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 .= ''."\n". + ''; + if ($type{$lang} eq 'custom') { + $datatable .= ' '.$lt{'rep'}.''; + } else { + $datatable .= $lt{'upl'}; } + $datatable .='
'; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; + } + $datatable .= ''; + $itemcount ++; } - foreach my $item (@links) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + 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 .= ''. + &mt('Add log-in help page for a specific language:').' '. + &Apache::loncommon::select_form('','loginhelpurl_add_lang',\%toadd). + ''.$lt{'upl'}.'
'; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; } + $datatable .= ''; + $itemcount ++; } + $datatable .= &captcha_choice('login',$settings,$itemcount); } - 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 .= - ''.$choices{$item}. - ''. - ' '. - ''; - $itemcount ++; - } - $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext); - $datatable .= ''; return $datatable; } @@ -940,6 +1089,7 @@ sub login_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:", @@ -977,17 +1127,7 @@ sub print_rolecolors { my %designhash = &Apache::loncommon::get_domainconf($dom); my %defaultdesign = %Apache::loncommon::defaultdesign; my (%is_custom,%designs); - my %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}; - } + my %defaults = &role_defaults($role,\@bgs,\@links,\@images); if (ref($settings) eq 'HASH') { if (ref($settings->{$role}) eq 'HASH') { if ($settings->{$role}->{'img'} ne '') { @@ -1048,9 +1188,48 @@ sub print_rolecolors { 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 = ''. ''.$choices->{'font'}.''; @@ -1059,13 +1238,12 @@ sub display_color_options { } else { $datatable .= ' '; } - my $fontlink = &color_pick($phase,$role,'font',$choices->{'font'},$designs->{'font'}); + my $current_color = $designs->{'font'} ? $designs->{'font'} : $defaults->{'font'}; + $datatable .= ''. - ' '.$fontlink. - '    '. - ''; + ' '. + ' '; unless ($role eq 'login') { $datatable .= ''. ''.$choices->{'fontmenu'}.''; @@ -1074,13 +1252,13 @@ sub display_color_options { } else { $datatable .= ' '; } - $fontlink = &color_pick($phase,$role,'fontmenu',$choices->{'fontmenu'},$designs->{'fontmenu'}); + $current_color = $designs->{'fontmenu'} ? + $designs->{'fontmenu'} : $defaults->{'fontmenu'}; $datatable .= ''. - ' '.$fontlink. - '    '. - ''; + ' '. + ' '; } my $switchserver = &check_switchserver($dom,$confname); foreach my $img (@{$images}) { @@ -1095,7 +1273,7 @@ sub display_color_options { &login_header_options($img,$role,$defaults,$is_custom,$choices); $logincolors = &login_text_colors($img,$role,$logintext,$phase,$choices, - $designs); + $designs,$defaults); } elsif ($img ne 'domlogo') { $datatable.= &logo_display_options($img,$defaults,$designs); } @@ -1128,11 +1306,11 @@ sub display_color_options { $showfile = $imgfile; my $imgdir = $1; my $filename = $2; - if (-e "/home/httpd/html/$imgdir/tn-".$filename) { + if (-e "$londocroot/$imgdir/tn-".$filename) { $showfile = "/$imgdir/tn-".$filename; } else { - my $input = "/home/httpd/html".$imgfile; - my $output = '/home/httpd/html/'.$imgdir.'/tn-'.$filename; + my $input = $londocroot.$imgfile; + my $output = "$londocroot/$imgdir/tn-".$filename; if (!-e $output) { my ($width,$height) = &thumb_dimensions(); my ($fullwidth,$fullheight) = &check_dimensions($input); @@ -1140,7 +1318,7 @@ sub display_color_options { if ($fullwidth > $width && $fullheight > $height) { my $size = $width.'x'.$height; system("convert -sample $size $input $output"); - $showfile = '/'.$imgdir.'/tn-'.$filename; + $showfile = "/$imgdir/tn-".$filename; } } } @@ -1174,12 +1352,12 @@ sub display_color_options { $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import, $showfile,$fullsize,$role,$img,$imgfile,$logincolors); } else { - $datatable .= '
'. - &mt('Upload:'); + $datatable .= ' '. + &mt('Upload:').'
'; } } else { - $datatable .= '
'. - &mt('Upload:'); + $datatable .= ' '. + &mt('Upload:').'
'; } if ($switchserver) { $datatable .= &mt('Upload to library server: [_1]',$switchserver); @@ -1207,13 +1385,14 @@ sub display_color_options { } $datatable .= ''. ''; + foreach my $item (@{$bgs}) { - my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item}); - $datatable .= ''; } $datatable .= '
'.$link; + $datatable .= ''.$choices->{$item}; + my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item}; if ($designs->{'bgs'}{$item}) { - $datatable .= '    '; + $datatable .= ' '; } - $datatable .= '
'; @@ -1235,13 +1414,12 @@ sub display_color_options { $datatable .= ''. ''; foreach my $item (@{$links}) { - $datatable .= ''; } $$rowtotal += $itemcount; @@ -1295,17 +1473,13 @@ sub login_header_options { } sub login_text_colors { - my ($img,$role,$logintext,$phase,$choices,$designs) = @_; + my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_; my $color_menu = '
'."\n". - &color_pick($phase,$role,$item,$choices->{$item}, - $designs->{'links'}{$item}); + my $color = $designs->{'link'}{$item} ? $designs->{'link'}{$item} : $defaults->{'links'}{$item}; + $datatable .= ''.$choices->{$item}."\n"; if ($designs->{'links'}{$item}) { - $datatable.='    '; + $datatable.=' '; } - $datatable .= '
'; foreach my $item (@{$logintext}) { - my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'logintext'}{$item}); - $color_menu .= ''. - ''; + $color_menu .= ''; } $color_menu .= '
'.$link; - if ($designs->{'logintext'}{$item}) { - $color_menu .= '    '; - } - $color_menu .= '
 '.$choices->{$item}; + my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item}; + $color_menu .= '

'; return $color_menu; @@ -1337,20 +1511,12 @@ sub image_changes { $role.'_del_'.$img.'" value="1" />'.&mt('Delete?'). ' '.&mt('Replace:').'
'; } else { - $output .= ''.$logincolors.&mt('Upload:').'
'; + $output .= ''.$logincolors.&mt('Upload:').'
'; } } return $output; } -sub color_pick { - my ($phase,$role,$item,$desc,$curcol) = @_; - my $link = ''.$desc.''; - return $link; -} - sub print_quotas { my ($dom,$settings,$rowtotal,$action) = @_; my $context; @@ -1359,7 +1525,7 @@ sub print_quotas { } else { $context = $action; } - my ($datatable,$defaultquota,@usertools,@options,%validations); + my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $typecount = 0; my ($css_class,%titles); @@ -1368,20 +1534,28 @@ sub print_quotas { @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','portfolio'); + @usertools = ('aboutme','blog','webdav','portfolio'); %titles = &tool_titles(); } if (ref($types) eq 'ARRAY') { foreach my $type (@{$types}) { - my $currdefquota; - unless ($context eq 'requestcourses') { + 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}; + $currdefquota = $settings->{defaultquota}->{$type}; } else { $currdefquota = $settings->{$type}; } + if (ref($settings->{authorquota}) eq 'HASH') { + $currauthorquota = $settings->{authorquota}->{$type}; + } } } if (defined($usertypes->{$type})) { @@ -1445,6 +1619,28 @@ sub print_quotas { $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 .= '  '; + } } else { my $checked = 'checked="checked" '; if (ref($settings) eq 'HASH') { @@ -1470,25 +1666,35 @@ sub print_quotas { $datatable .= ''; } $datatable .= ''; - unless ($context eq 'requestcourses') { + unless (($context eq 'requestcourses') || + ($context eq 'requestauthor')) { $datatable .= - ''. + ''. + ''.&mt('Portfolio').': '. ' Mb'; + '" size="5" />'.(' ' x 2). + ''.&mt('Authoring').': '. + ''; } $datatable .= ''; } } } - unless ($context eq 'requestcourses') { + 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 ++; @@ -1551,6 +1757,28 @@ sub print_quotas { $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 .= '  '; + } } else { my $checked = 'checked="checked" '; if (ref($settings) eq 'HASH') { @@ -1576,16 +1804,20 @@ sub print_quotas { $datatable .= ''; } $datatable .= ''; - unless ($context eq 'requestcourses') { - $datatable .= ''. + unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + $datatable .= ''. + ''.&mt('Portfolio').': '. ' Mb'; + $defaultquota.'" size="5" />'.(' ' x2). + ''.&mt('Authoring').': '. + ''; } $datatable .= ''; $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; $datatable .= ''. - ''.&mt('LON-CAPA Advanced Users').' '; + ''.&mt('LON-CAPA Advanced Users').'
'; if ($context eq 'requestcourses') { $datatable .= &mt('(overrides affiliation, if set)'). ''. @@ -1654,6 +1886,33 @@ sub print_quotas { $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 .= '  '; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + my $checked = ''; + if ($val eq $curroption) { + $checked = ' checked="checked"'; + } + $datatable .= '  '; + } } else { my $checked = 'checked="checked" '; if (ref($settings) eq 'HASH') { @@ -1683,78 +1942,34 @@ sub print_quotas { return $datatable; } -sub print_courserequestmail { - my ($dom,$settings,$rowtotal) = @_; - my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows); +sub print_requestmail { + my ($dom,$action,$settings,$rowtotal) = @_; + my ($now,$datatable,%currapp); $now = time; - $rows = 0; - %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now); - foreach my $server (keys(%dompersonnel)) { - foreach my $user (sort(keys(%{$dompersonnel{$server}}))) { - my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user); - if (!grep(/^$uname:$udom$/,@domcoord)) { - push(@domcoord,$uname.':'.$udom); - } - } - } if (ref($settings) eq 'HASH') { if (ref($settings->{'notify'}) eq 'HASH') { if ($settings->{'notify'}{'approval'} ne '') { - @currapproval = split(',',$settings->{'notify'}{'approval'}); - } - } - } - if (@currapproval) { - foreach my $dc (@currapproval) { - unless (grep(/^\Q$dc\E$/,@domcoord)) { - push(@domcoord,$dc); + map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'}); } } } - @domcoord = sort(@domcoord); - my $numinrow = 4; - my $numdc = @domcoord; + my $numinrow = 2; my $css_class = 'class="LC_odd_row"'; - $datatable = ''. - ' '.&mt('Receive notification of course requests requiring approval.'). - ' '. + my $text; + if ($action eq 'requestcourses') { + $text = &mt('Receive notification of course requests requiring approval'); + } else { + $text = &mt('Receive notification of authoring space requests requiring approval') + } + $datatable = ''. + ' '.$text.''. ' '; - if (@domcoord > 0) { - $datatable .= ''; - for (my $i=0; $i<$numdc; $i++) { - my $rem = $i%($numinrow); - if ($rem == 0) { - if ($i > 0) { - $datatable .= ''; - } - $datatable .= ''; - $rows ++; - } - my $check = ' '; - if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) { - $check = ' checked="checked" '; - } - my ($uname,$udom) = split(':',$domcoord[$i]); - my $fullname = &Apache::loncommon::plainname($uname,$udom); - if ($i == $numdc-1) { - my $colsleft = $numinrow-$rem; - if ($colsleft > 1) { - $datatable .= ''; - } - $datatable .= '
'; - } else { - $datatable .= ''; - } - } else { - $datatable .= ''; - } - $datatable .= '
'; + my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox', + 'reqapprovalnotify',%currapp); + if ($numdc > 0) { + $datatable .= $table; } else { $datatable .= &mt('There are no active Domain Coordinators'); - $rows ++; } $datatable .=''; $$rowtotal += $rows; @@ -1909,8 +2124,7 @@ sub print_autoupdate { sub print_autocreate { my ($dom,$settings,$rowtotal) = @_; - my (%createon,%createoff); - my $curr_dc; + my (%createon,%createoff,%currhash); my @types = ('xml','req'); if (ref($settings) eq 'HASH') { foreach my $item (@types) { @@ -1923,7 +2137,9 @@ sub print_autocreate { } } } - $curr_dc = $settings->{'xmldc'}; + if ($settings->{'xmldc'} ne '') { + $currhash{$settings->{'xmldc'}} = 1; + } } else { foreach my $item (@types) { $createoff{$item} = ' checked="checked" '; @@ -1931,6 +2147,7 @@ sub print_autocreate { } } $$rowtotal += 2; + my $numinrow = 2; my $datatable=''. ''.&mt('Create pending official courses from XML files').''. ' '. ''; - my ($numdc,$dctable) = &active_dc_picker($dom,$curr_dc); + my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio', + 'autocreate_xmldc',%currhash); if ($numdc > 1) { $datatable .= ''. &mt('Course creation processed as: (choose Dom. Coord.)'). ''.$dctable.''; - $$rowtotal ++ ; } else { $datatable .= $dctable.''; } + $$rowtotal += $rows; return $datatable; } @@ -2076,7 +2294,7 @@ sub print_contacts { my @contacts = ('adminemail','supportemail'); my (%checked,%to,%otheremails,%bccemails); my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail', - 'requestsmail'); + 'requestsmail','updatesmail','idconflictsmail'); foreach my $type (@mailings) { $otheremails{$type} = ''; } @@ -2112,21 +2330,22 @@ sub print_contacts { $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) { - $rownum ++; $css_class = $rownum%2?' class="LC_odd_row"':''; $datatable .= ''. ''.$titles->{$item}. ''. ''; + $rownum ++; } foreach my $type (@mailings) { - $rownum ++; $css_class = $rownum%2?' class="LC_odd_row"':''; $datatable .= ''. ''. @@ -2149,107 +2368,44 @@ sub print_contacts { 'value="'.$bccemails{$type}.'" />'; } $datatable .= ''."\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',); - my ($position,$dom,$confname,$settings,$rowtotal) = @_; - my ($css_class,$datatable); - - my $switchserver = &check_switchserver($dom,$confname); - - my $itemcount = 1; - - if ($position eq 'top') { - - my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles); - - %choices = - &Apache::lonlocal::texthash ( - submitbugs => 'Display "Submit a bug" link?', - ); - - %defaultchecked = ('submitbugs' => 'on'); - - @toggles = ('submitbugs',); - - 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} = ' '; - } - } - } - - foreach my $item (@toggles) { - $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; - $datatable .= - ' - '.$choices{$item}.' -   - -   - '. - ''. - ''; - $itemcount ++; - } - - } else { - - $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; - - $datatable .= ''; - - if (ref($settings) eq 'HASH') { - if ($settings->{'loginhelpurl'} ne '') { - my($directory, $filename) = $settings->{'loginhelpurl'} =~ m/(.*\/)(.*)$/; - $datatable .= ''; - $datatable .= '' - } else { - $datatable .= ''; - $datatable .= ' '; - } - } else { - $datatable .= ' '; - $datatable .= ' '; - } - - $datatable .= ''; - if ($switchserver) { - $datatable .= &mt('Upload to library server: [_1]',$switchserver); - } else { - $datatable .= &mt('Upload Custom Login Page Help File:'); - $datatable .=''; - } - $datatable .= ''; - - } - - return $datatable; - + ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, + \%choices,$itemcount); + return $datatable; } - sub radiobutton_prefs { - my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_; + my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick, + $additional) = @_; return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') && (ref($choices) eq 'HASH')); @@ -2275,17 +2431,22 @@ sub radiobutton_prefs { } } } + if ($onclick) { + $onclick = ' onclick="'.$onclick.'"'; + } foreach my $item (@{$toggles}) { $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= - ''.$choices->{$item}. + ''. + ''.$choices->{$item}. ''. ''. ' '. - ''. + $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').''. + ''.$additional. + ''. ''; $itemcount ++; } @@ -2294,42 +2455,100 @@ sub radiobutton_prefs { sub print_coursedefaults { my ($position,$dom,$settings,$rowtotal) = @_; - my ($css_class,$datatable); + 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') { - my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles); - %choices = - &Apache::lonlocal::texthash ( - canuse_pdfforms => 'Course/Community users can create/upload PDF forms', - ); %defaultchecked = ('canuse_pdfforms' => 'off'); - @toggles = ('canuse_pdfforms',); + @toggles = ('canuse_pdfforms'); ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, \%choices,$itemcount); - $$rowtotal += $itemcount; } else { $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; - my %choices = - &Apache::lonlocal::texthash ( - anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys', - ); - my $currdefresponder; + my ($currdefresponder,$def_official_credits,$def_unofficial_credits,%curruploadquota); + my $currusecredits = 0; + my @types = ('official','unofficial','community'); 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'}; + if (($def_official_credits ne '') || ($def_unofficial_credits ne '')) { + $currusecredits = 1; + } + } } if (!$currdefresponder) { - $currdefresponder = 10; + $currdefresponder = $staticdefaults{'anonsurvey_threshold'}; } elsif ($currdefresponder < 1) { $currdefresponder = 1; } + foreach my $type (@types) { + if ($curruploadquota{$type} eq '') { + $curruploadquota{$type} = $staticdefaults{'uploadquota'}; + } + } $datatable .= - ''.$choices{'anonsurvey_threshold'}. + ''. + $choices{'anonsurvey_threshold'}. ''. ''. ''. - ''; + ''."\n". + ''. + $choices{'uploadquota'}. + ''. + ''. + ''; + foreach my $type (@types) { + $datatable .= ''; + } + $datatable .= '
'.&mt($type).'
'. + '
'."\n"; + $itemcount += 2; + my $onclick = 'toggleCredits(this.form);'; + my $display = 'none'; + if ($currusecredits) { + $display = 'block'; + } + my $additional = '
'. + ''. + &mt('Default credits for official courses [_1]', + ''). + '
'. + ''. + &mt('Default credits for unofficial courses [_1]', + ''). + '
'."\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; } @@ -2620,7 +2839,10 @@ sub spares_row { $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; $datatable .= ' - '.$server.' when busy, offloads to:'."\n"; + '. + &mt('[_1] when busy, offloads to:' + ,''.$server.''). + "\n"; my (%current,%canselect); my @choices = &possible_newspares($server,$spareid->{$server},$serverhomes,$altids); @@ -2744,16 +2966,13 @@ sub print_loadbalancing { my $numinrow = 1; my $datatable; my %servers = &Apache::lonnet::internet_dom_servers($dom); - my ($currbalancer,$currtargets,$currrules); - if (keys(%servers) > 1) { - if (ref($settings) eq 'HASH') { - $currbalancer = $settings->{'lonhost'}; - $currtargets = $settings->{'targets'}; - $currrules = $settings->{'rules'}; - } else { - ($currbalancer,$currtargets) = - &Apache::lonnet::get_lonbalancer_config(\%servers); - } + 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; } @@ -2763,104 +2982,190 @@ sub print_loadbalancing { if (ref($types) eq 'ARRAY') { $rownum += scalar(@{$types}); } - my $css_class = ' class="LC_odd_row"'; - my $targets_div_style = 'display: none'; - my $disabled_div_style = 'display: block'; - my $homedom_div_style = 'display: none'; - $datatable = ''. - ''. - '

'. - '
'.&mt('No dedicated Load Balancer').'
'."\n". - '
'.&mt('Offloads to:').'
'; - my ($numspares,@spares) = &count_servers($currbalancer,%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) eq 'HASH') { - if (ref($currtargets->{$sparetype}) eq 'ARRAY') { - if (grep(/^\Q$spares[$i]\E$/,@{$currtargets->{$sparetype}})) { - $checked = ' checked="checked"'; + 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 .= ''. + ''. + '

'; + if ($lonhost eq '') { + $datatable .= ''; + if (keys(%currbalancer) > 0) { + $datatable .= &mt('Add balancer:'); + } else { + $datatable .= &mt('Enable balancer:'); + } + $datatable .= ' '. + ''."\n". + ' '."\n"; + } else { + $datatable .= ''.$lonhost.'
'. + ''. + ''; + $targets_div_style = 'display: block'; + $disabled_div_style = 'display: none'; + if ($dom eq &Apache::lonnet::host_domain($lonhost)) { + $homedom_div_style = 'display: block'; + } + } + $datatable .= '

'. + '
'.$disabledtext.'
'."\n". + '
'.&mt('Offloads to:').'
'; + 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 .= + ''; + my $rem = $i%($numinrow); + if ($rem == 0) { + if (($i > 0) && ($i < $numspares-1)) { + $targettable .= ''; + } + if ($i < $numspares-1) { + $targettable .= ''; } } } - my $chkboxval; - if (($currbalancer ne '') && (grep((/^\Q$currbalancer\E$/,keys(%servers))))) { - $chkboxval = $spares[$i]; - } - $targettable .= ''; - my $rem = $i%($numinrow); - if ($rem == 0) { - if ($i > 0) { - $targettable .= ''; - } - $targettable .= ''; + if ($targettable ne '') { + my $rem = $numspares%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $targettable .= ''. + ' '; + } elsif ($colsleft == 1) { + $targettable .= ' '; + } + $datatable .= ''.$typetitles{$sparetype}.'
'. + ''.$targettable.'

'; + } + } + $datatable .= '
'. + &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 .= ''; + 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'}; } } - if ($targettable ne '') { - my $rem = $numspares%($numinrow); - my $colsleft = $numinrow - $rem; - if ($colsleft > 1 ) { - $targettable .= ''. - ' '; - } elsif ($colsleft == 1) { - $targettable .= ' '; + } 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}; } - $datatable .= ''.$typetitles{$sparetype}.'
'. - ''.$targettable.'

'; } } - $datatable .= '
'. - &loadbalancing_rules($dom,$intdom,$currrules,$othertitle, - $usertypes,$types,\%servers,$currbalancer, - $targets_div_style,$homedom_div_style,$css_class); - $$rowtotal += $rownum; - return $datatable; + return; } sub loadbalancing_rules { my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers, - $currbalancer,$targets_div_style,$homedom_div_style,$css_class) = @_; + $currbalancer,$lonhost,$targets_div_style,$homedom_div_style, + $css_class,$balnum,$islast) = @_; my $output; - my ($alltypes,$othertypes,$titles) = + 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')) { - if ($dom ne &Apache::lonnet::host_domain($currbalancer)) { + if ($dom ne &Apache::lonnet::host_domain($lonhost)) { $current = ''; } } $output .= &loadbalance_rule_row($type,$titles->{$type},$current, - $servers,$currbalancer,$dom, - $targets_div_style,$homedom_div_style,$css_class); + $servers,$currbalancer,$lonhost,$dom, + $targets_div_style,$homedom_div_style, + $css_class,$balnum,$num,$islast); } } return $output; @@ -2897,8 +3202,8 @@ sub loadbalancing_titles { } sub loadbalance_rule_row { - my ($type,$title,$current,$servers,$currbalancer,$dom,$targets_div_style, - $homedom_div_style,$css_class) = @_; + my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom, + $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_; my @rulenames = ('default','homeserver'); my %ruletitles = &offloadtype_text(); if ($type eq '_LC_external') { @@ -2906,13 +3211,20 @@ sub loadbalance_rule_row { } else { push(@rulenames,'specific'); } + push(@rulenames,'none'); my $style = $targets_div_style; if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) { $style = $homedom_div_style; } - my $output = - '
'.$title.'
'."\n". - '
'."\n"; + my $space; + if ($islast && $num == 1) { + $space = '
 
'; + } + my $output = + ''.$space. + '
'.$title.'
'."\n". + ''.$space. + '
'."\n"; for (my $i=0; $i<@rulenames; $i++) { my $rule = $rulenames[$i]; my ($checked,$extra); @@ -2928,17 +3240,20 @@ sub loadbalance_rule_row { unless ($checked) { $default = ' selected="selected"'; } - $extra = ': '."\n". + ''."\n"; + foreach my $server (sort(keys(%{$servers}))) { + if (ref($currbalancer) eq 'HASH') { + next if (exists($currbalancer->{$server})); + } my $selected; - if ($lonhost eq $current) { + if ($server eq $current) { $selected = ' selected="selected"'; } - $extra .= ''; + $extra .= ''; } $extra .= ''; } @@ -2946,9 +3261,9 @@ sub loadbalance_rule_row { $checked = ' checked="checked"'; } $output .= ''.$extra.'
'."\n"; } @@ -2962,6 +3277,7 @@ sub offloadtype_text { 'homeserver' => "Offloads to user's home server", 'externalbalancer' => "Offloads to Load Balancer in user's domain", 'specific' => 'Offloads to specific server', + 'none' => 'No offload', ); return %ruletitles; } @@ -2983,6 +3299,8 @@ sub contact_titles { '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', @@ -2993,8 +3311,9 @@ sub contact_titles { sub tool_titles { my %titles = &Apache::lonlocal::texthash ( - aboutme => 'Personal Information Page', + aboutme => 'Personal web page', blog => 'Blog', + webdav => 'WebDAV', portfolio => 'Portfolio', official => 'Official courses (with institutional codes)', unofficial => 'Unofficial courses', @@ -3017,10 +3336,19 @@ sub courserequest_titles { 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 instittutional validation).', + validate => '(Processing of request subject to institutional validation).', ); return %conditions; } @@ -3146,18 +3474,20 @@ sub print_usercreation { } my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + my $createsettings; + if (ref($settings) eq 'HASH') { + $createsettings = $settings->{cancreate}; + } if (ref($usertypes) eq 'HASH') { if (keys(%{$usertypes}) > 0) { - my $createsettings; - if (ref($settings) eq 'HASH') { - $createsettings = $settings->{cancreate}; - } $datatable .= &insttypes_row($createsettings,$types,$usertypes, $dom,$numinrow,$othertitle, 'statustocreate'); $$rowtotal ++; + $rownum ++; } } + $datatable .= &captcha_choice('cancreate',$createsettings,$rownum); } else { my @contexts = ('author','course','domain'); my @authtypes = ('int','krb4','krb5','loc'); @@ -3209,6 +3539,64 @@ sub print_usercreation { 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 (e-mail as username)'); + } 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 = ''. + ''.$rowname.''."\n". + ''."\n". + '
'."\n"; + foreach my $option ('original','recaptcha','notused') { + $output .= ''; + 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 .= '
'."\n". + ''.$pubtext.' '."\n". + '
'."\n". + ''.$privtext.' '."\n". + '
'."\n". + ''; + return $output; +} + sub user_formats_row { my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_; my $output; @@ -3383,6 +3771,12 @@ sub print_defaults { } elsif ($item eq 'datelocale_def') { my $includeempty = 1; $datatable .= &Apache::loncommon::select_datelocale($item,$domdefaults{$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($domdefaults{$item},$item, + \%langchoices); } else { my $size; if ($item eq 'portal_def') { @@ -3398,6 +3792,17 @@ sub print_defaults { 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 ( @@ -3530,8 +3935,8 @@ sub print_scantronformat { $datatable .= ''.&mt('Default in use:').'
'. ''; if ($scantronurl) { - $datatable .= ''. - &mt('Default bubblesheet format file').''; + $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'); } @@ -3556,11 +3961,12 @@ sub print_scantronformat { } $datatable .= ''.$errorstr.' '; } elsif ($scantronurl) { + my $link = &Apache::loncommon::modal_link($scantronurl,&mt('Custom bubblesheet format file'),600,500, + undef,undef,undef,undef,'background-color:#ffffff'); $datatable .= ''. - ''. - &mt('Custom bubblesheet format file').''. + $link. + ''. ' '. &mt('Replace:').'
'; } @@ -3858,8 +4264,8 @@ sub print_serverstatuses { sub serverstatus_pages { return ('userstatus','lonstatus','loncron','server-status','codeversions', - 'clusterstatus','metadata_keywords','metadata_harvest', - 'takeoffline','takeonline','showenv','toggledebug'); + 'checksums','clusterstatus','metadata_keywords','metadata_harvest', + 'takeoffline','takeonline','showenv','toggledebug','ping','domconf'); } sub coursecategories_javascript { @@ -4016,7 +4422,7 @@ sub build_category_rows { if (ref($cats->[$depth]{$parent}) eq 'ARRAY') { my $numchildren = @{$cats->[$depth]{$parent}}; my $css_class = $itemcount%2?' class="LC_odd_row"':''; - $text .= ''; + $text .= '
'; my ($idxnum,$parent_name,$parent_item); my $higher = $depth - 1; if ($higher == 0) { @@ -4173,9 +4579,13 @@ sub insttypes_row { if ($context eq 'cansearch') { $showdom = ' ('.$dom.')'; } + my $class = 'LC_left_item'; + if ($context eq 'statustocreate') { + $class = 'LC_right_item'; + } my $output = ''. '
'.$lt{$context}.$showdom. - ''; + '
'; my $rem; if (ref($types) eq 'ARRAY') { for (my $i=0; $i<@{$types}; $i++) { @@ -4304,14 +4714,15 @@ sub usertype_update_row { } sub modify_login { - my ($r,$dom,$confname,%domconfig) = @_; - my ($resulttext,$errors,$colchgtext,%changes,%colchanges); - my %title = ( coursecatalog => 'Display course catalog', - adminmail => 'Display administrator E-mail address', - newuser => 'Link for visitors to create a user account', - loginheader => 'Log-in box header'); - my @offon = ('off','on'); - my %curr_loginvia; + 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}})) { @@ -4319,10 +4730,9 @@ sub modify_login { } } } - my %loginhash; ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'], \%domconfig,\%loginhash); - my @toggles = ('coursecatalog','adminmail','newuser'); + my @toggles = ('coursecatalog','adminmail','helpdesk','newuser'); foreach my $item (@toggles) { $loginhash{login}{$item} = $env{'form.'.$item}; } @@ -4392,7 +4802,6 @@ sub modify_login { $new = ''; } } - $loginhash{login}{loginvia}{$lonhost}{$item} = $new; } } @@ -4418,12 +4827,103 @@ sub modify_login { } } + 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 .= '
  • '.$puberror.'
  • '; + 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 .= '
  • '.$error.'
  • '; + } + } + &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','newuser'); + my @toggles = ('coursecatalog','adminmail','helpdesk','newuser'); my %defaultchecked = ( 'coursecatalog' => 'on', + 'helpdesk' => 'on', 'adminmail' => 'off', 'newuser' => 'off', ); @@ -4452,6 +4952,7 @@ sub modify_login { } if (keys(%changes) > 0 || $colchgtext) { &Apache::loncommon::devalidate_domconfig_cache($dom); + $$lastactref = 'update'; $resulttext = &mt('Changes made:').'
      '; foreach my $item (sort(keys(%changes))) { if ($item eq 'loginvia') { @@ -4483,6 +4984,68 @@ sub modify_login { } $resulttext .= '
    '; } + } 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 .= '
  • '.$chg.'
  • '; + } 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 .= '
  • '.&Apache::loncommon::modal_link( + $loginhash{'login'}{'helpurl'}{$lang}. + '?inhibitmenu=yes',$chg,600,500). + '
  • '; + } + } + } + } 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 .= '
  • '.$chgtxt.'
  • '; + } + } 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').'
      '; + if (!$pubkey) { + $chgtxt .= '
    • '.&mt('Public key deleted').'
    • '; + } else { + $chgtxt .= '
    • '.&mt('Public key set to [_1]',$pubkey).'
    • '; + } + if (!$privkey) { + $chgtxt .= '
    • '.&mt('Private key deleted').'
    • '; + } else { + $chgtxt .= '
    • '.&mt('Private key set to [_1]',$pubkey).'
    • '; + } + $chgtxt .= '
    '; + $resulttext .= '
  • '.$chgtxt.'
  • '; + } } else { $resulttext .= '
  • '.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'
  • '; } @@ -4510,7 +5073,7 @@ sub color_font_choices { links => "Link colors", images => "Images", font => "Font color", - fontmenu => "Font Menu", + fontmenu => "Font menu", pgbg => "Page", tabbg => "Header", sidebg => "Border", @@ -4522,7 +5085,7 @@ sub color_font_choices { } sub modify_rolecolors { - my ($r,$dom,$confname,$roles,%domconfig) = @_; + my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_; my ($resulttext,%rolehash); $rolehash{'rolecolors'} = {}; if (ref($domconfig{'rolecolors'}) ne 'HASH') { @@ -4537,6 +5100,7 @@ sub modify_rolecolors { if ($putresult eq 'ok') { if (keys(%changes) > 0) { &Apache::loncommon::devalidate_domconfig_cache($dom); + $$lastactref = 'update'; $resulttext = &display_colorchgs($dom,\%changes,$roles, $rolehash{'rolecolors'}); } else { @@ -4562,24 +5126,45 @@ sub modify_colors { 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(); - $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'}; } if ($role eq 'login') { @images = ('img','logo','domlogo','login'); @bgs = ('pgbg','mainbg','sidebg'); } else { @images = ('img'); - @bgs = ('pgbg','tabbg','sidebg'); + @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}; + } } - $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'}; - foreach my $item (@bgs,@links,@logintext) { - $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); @@ -4927,15 +5512,17 @@ sub publishlogo { # See if there is anything left unless ($fname) { return ('error: no uploaded file'); } $fname="$subdir/$fname"; - my $filepath='/home/'.$confname.'/public_html'; + 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.'/'.$fnamepath); + my @parts=split(/\//,"$filepath/$relpath/$fnamepath"); my $count; - for ($count=4;$count<=$#parts;$count++) { + for ($count=5;$count<=$#parts;$count++) { $filepath.="/$parts[$count]"; if ((-e $filepath)!=1) { mkdir($filepath,02770); @@ -4945,19 +5532,19 @@ sub publishlogo { if ($file=~/\.(\w+)$/ && (&Apache::loncommon::fileembstyle($1) eq 'hdn')) { $output = - &mt('Invalid file extension ([_1]) - reserved for LONCAPA use.',$1); + &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('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2); + $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('File name is a directory name - rename the file and re-upload'); + $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 Construction Space')); + return (&mt('No write permission to Authoring Space')); } print $logfile "\n================= Publish ".localtime()." ================\n". @@ -4982,7 +5569,6 @@ $env{'user.name'}.':'.$env{'user.domain' close(FH); chmod(0660, $source); # Permissions to rw-rw---. - my $docroot=$r->dir_config('lonDocRoot'); my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath; my $copyfile=$targetdir.'/'.$file; @@ -5005,8 +5591,15 @@ $env{'user.name'}.':'.$env{'user.domain' if (copy($source,$copyfile)) { print $logfile "\nCopied original source to ".$copyfile."\n"; $output = 'ok'; - &write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile); $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').", $!"; @@ -5024,8 +5617,15 @@ $env{'user.name'}.':'.$env{'user.domain' my $copyfile=$targetdir.'/tn-'.$file; if (copy($outfile,$copyfile)) { print $logfile "\nCopied source to ".$copyfile."\n"; - &write_metadata($dom,$confname,$formname, - $targetdir,'tn-'.$file,$logfile); + 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"; @@ -5090,30 +5690,79 @@ sub write_metadata { { print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file; my $mfh; - unless (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) { + 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},'<>&"') + .''; + } + } + $output = 'ok'; + print $logfile "\nWrote metadata"; + close($mfh); + } else { + print $logfile "\nFailed to open metadata file"; $output = &mt('Could not write metadata'); } - 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},'<>&"') - .''; - } - } - $output = 'ok'; - print $logfile "\nWrote metadata"; - close($mfh); } + 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 { @@ -5126,7 +5775,7 @@ sub check_switchserver { my @ids=&Apache::lonnet::current_machine_ids(); foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } if (!$allowed) { - $switchserver=''.&mt('Switch Server').''; + $switchserver=''.&mt('Switch Server').''; } return $switchserver; } @@ -5147,8 +5796,11 @@ sub modify_quotas { %titles = &courserequest_titles(); $toolregexp = join('|',@usertools); %conditions = &courserequest_conditions(); + } elsif ($context eq 'requestauthor') { + @usertools = ('author'); + %titles = &authorrequest_titles(); } else { - @usertools = ('aboutme','blog','portfolio'); + @usertools = ('aboutme','blog','webdav','portfolio'); %titles = &tool_titles(); } my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); @@ -5164,16 +5816,21 @@ sub modify_quotas { $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}; - } - if ($key =~ /^form\.\Q$context\E_(.+)$/) { + } 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') { + if (($context eq 'requestcourses') || ($context eq 'requestauthor')) { my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify'); @approvalnotify = sort(@approvalnotify); $confhash{'notify'}{'approval'} = join(',',@approvalnotify); @@ -5194,6 +5851,7 @@ sub modify_quotas { } } else { $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'}; + $confhash{'authorquota'}{'default'} = $env{'form.authorquota'}; } foreach my $item (@usertools) { foreach my $type (@{$types},'default','_LC_adv') { @@ -5209,6 +5867,11 @@ sub modify_quotas { $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; @@ -5217,7 +5880,11 @@ sub modify_quotas { } } if (ref($domconfig{$action}) eq 'HASH') { - if (ref($domconfig{$action}{$item}) 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; } @@ -5237,6 +5904,10 @@ sub modify_quotas { 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; @@ -5245,7 +5916,7 @@ sub modify_quotas { } } } - unless ($context eq 'requestcourses') { + 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'}})) { @@ -5268,6 +5939,17 @@ sub modify_quotas { } } } + 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'}})) { @@ -5286,12 +5968,31 @@ sub modify_quotas { } } } + 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; + } + } + } } - foreach my $key (keys(%confhash)) { - $domdefaults{$key} = $confhash{$key}; + if ($context eq 'requestauthor') { + $domdefaults{'requestauthor'} = \%confhash; + } else { + foreach my $key (keys(%confhash)) { + $domdefaults{$key} = $confhash{$key}; + } } - + my %quotahash = ( $action => { %confhash } ); @@ -5303,7 +6004,8 @@ sub modify_quotas { &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); $resulttext = &mt('Changes made:').'
      '; - unless ($context eq 'requestcourses') { + unless (($context eq 'requestcourses') || + ($context eq 'requestauthor')) { if (ref($changes{'defaultquota'}) eq 'HASH') { $resulttext .= '
    • '.&mt('Portfolio default quotas').'
        '; foreach my $type (@{$types},'default') { @@ -5317,15 +6019,41 @@ sub modify_quotas { } $resulttext .= '
    • '; } + if (ref($changes{'authorquota'}) eq 'HASH') { + $resulttext .= '
    • '.&mt('Authoring space default quotas').'
        '; + foreach my $type (@{$types},'default') { + if (defined($changes{'authorquota'}{$type})) { + my $typetitle = $usertypes->{$type}; + if ($type eq 'default') { + $typetitle = $othertitle; + } + $resulttext .= '
      • '.&mt('[_1] set to [_2] Mb',$typetitle,$confhash{'authorquota'}{$type}).'
      • '; + } + } + $resulttext .= '
    • '; + } } my %newenv; foreach my $item (@usertools) { - if (ref($changes{$item}) eq 'HASH') { + 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') { + if (($context eq 'requestcourses') || + ($context eq 'requestauthor')) { if ($env{'environment.canrequest.'.$item} ne $newacc) { $newenv{'environment.canrequest.'.$item} = $newacc; } @@ -5334,34 +6062,40 @@ sub modify_quotas { $newenv{'environment.availabletools.'.$item} = $newacc; } } - $resulttext .= '
    • '.$titles{$item}.'
        '; + unless ($context eq 'requestauthor') { + $resulttext .= '
      • '.$titles{$item}.'
          '; + } foreach my $type (@{$types},'default','_LC_adv') { - if ($changes{$item}{$type}) { + if ($haschgs{$type}) { my $typetitle = $usertypes->{$type}; if ($type eq 'default') { $typetitle = $othertitle; } elsif ($type eq '_LC_adv') { $typetitle = 'LON-CAPA Advanced Users'; } - if ($confhash{$item}{$type}) { + if ($inconf{$type}) { if ($context eq 'requestcourses') { my $cond; - if ($confhash{$item}{$type} =~ /^autolimit=(\d*)$/) { + 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{$confhash{$item}{$type}}; + $cond = $conditions{$inconf{$type}}; } $resulttext .= '
        • '.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'
        • '; + } elsif ($context eq 'requestauthor') { + $resulttext .= '
        • '.&mt('Set to "[_1]" for "[_2]".', + $titles{$inconf{$type}},$typetitle); + } else { $resulttext .= '
        • '.&mt('Set to be available to [_1]',$typetitle).'
        • '; } } else { if ($type eq '_LC_adv') { - if ($confhash{$item}{$type} eq '0') { + if ($inconf{$type} eq '0') { $resulttext .= '
        • '.&mt('Set to be unavailable to [_1]',$typetitle).'
        • '; } else { $resulttext .= '
        • '.&mt('No override set for [_1]',$typetitle).'
        • '; @@ -5372,17 +6106,19 @@ sub modify_quotas { } } } - $resulttext .= '
      • '; + unless ($context eq 'requestauthor') { + $resulttext .= '
    • '; + } } } - if ($action eq 'requestcourses') { + 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 .= '
    • '.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'
    • '; } else { - $resulttext .= '
    • '.&mt('No Domain Coordinators will receive notification of course requests requiring approval.').'
    • '; + $resulttext .= '
    • '.&mt('No Domain Coordinators will receive notification of requests requiring approval.').'
    • '; } } } @@ -5395,6 +6131,8 @@ sub modify_quotas { } 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'); } @@ -5407,7 +6145,7 @@ sub modify_quotas { } sub modify_autoenroll { - my ($dom,%domconfig) = @_; + my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,%changes); my %currautoenroll; if (ref($domconfig{'autoenroll'}) eq 'HASH') { @@ -5475,6 +6213,7 @@ sub modify_autoenroll { if ($changes{'coowners'}) { $resulttext .= '
    • '.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'
    • '; &Apache::loncommon::devalidate_domconfig_cache($dom); + $$lastactref = 'update'; } $resulttext .= '
    '; } else { @@ -5725,13 +6464,16 @@ sub modify_autocreate { foreach my $item (@types) { if ($changes{$item}) { my $newtxt = $offon[$newvals{$item}]; - $resulttext .= '
  • '.&mt("$title{$item} set to [_1]$newtxt [_2]",'','').'
  • '; + $resulttext .= '
  • '. + &mt("$title{$item} set to [_1]$newtxt [_2]", + '',''). + '
  • '; } } if ($changes{'xmldc'}) { my ($dcname,$dcdom) = split(':',$newvals{'xmldc'}); my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom); - $resulttext .= '
  • '.&mt("$title{'xmldc'} set to [_1]$newtxt [_2]",'','').'
  • '; + $resulttext .= '
  • '.&mt("$title{'xmldc'} set to [_1]",''.$newtxt.'').'
  • '; } $resulttext .= ''; } else { @@ -5877,7 +6619,11 @@ sub modify_directorysrch { } else { $chgtext =~ s/\; $//; } - $resulttext .= '
  • '.&mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]",$dom,$chgtext).'
  • '; + $resulttext .= + '
  • '. + &mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]", + ''.$dom.'',$chgtext). + '
  • '; } } } @@ -5905,7 +6651,7 @@ sub modify_directorysrch { } } $chgtext =~ s/\; $//; - $resulttext .= '
  • '.&mt("$title{'searchtypes'} set to: \"[_1]\"",$chgtext).'
  • '; + $resulttext .= '
  • '.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'
  • '; } $resulttext .= ''; } else { @@ -5919,7 +6665,7 @@ sub modify_directorysrch { } sub modify_contacts { - my ($dom,%domconfig) = @_; + my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash); if (ref($domconfig{'contacts'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'contacts'}})) { @@ -5929,7 +6675,8 @@ sub modify_contacts { my (%others,%to,%bcc); my @contacts = ('supportemail','adminemail'); my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail', - 'requestsmail'); + 'requestsmail','updatesmail','idconflictsmail'); + my @toggles = ('reporterrors','reportupdates'); foreach my $type (@mailings) { @{$newsetting{$type}} = &Apache::loncommon::get_env_multiple('form.'.$type); @@ -5951,6 +6698,11 @@ sub modify_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}) { @@ -5985,10 +6737,11 @@ sub modify_contacts { $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})) { @@ -6005,10 +6758,20 @@ sub modify_contacts { } } } + 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); + $$lastactref = 'update'; my ($titles,$short_titles) = &contact_titles(); $resulttext = &mt('Changes made:').'
      '; foreach my $item (@contacts) { @@ -6039,6 +6802,23 @@ sub modify_contacts { $resulttext .= ''; } } + my @offon = ('off','on'); + if ($changes{'reporterrors'}) { + $resulttext .= '
    • '. + &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)). + '
    • '; + } + if ($changes{'reportupdates'}) { + $resulttext .= '
    • '. + &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)). + '
    • '; + } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to contact information'); @@ -6089,6 +6869,7 @@ sub modify_usercreation { } push(@contexts,'statustocreate'); } + &process_captcha('cancreate',\%changes,\%cancreate,\%curr_usercreation); if (ref($curr_usercreation{'cancreate'}) eq 'HASH') { foreach my $item (@contexts) { if (($item eq 'selfcreate') || ($item eq 'statustocreate')) { @@ -6271,7 +7052,7 @@ sub modify_usercreation { my %lt = &usercreation_types(); foreach my $type (@{$changes{'cancreate'}}) { my $chgtext; - unless ($type eq 'statustocreate') { + unless (($type eq 'statustocreate') || ($type eq 'captcha') || ($type eq 'recaptchakeys')) { $chgtext = $lt{$type}.', '; } if ($type eq 'selfcreate') { @@ -6330,6 +7111,35 @@ sub modify_usercreation { } } } + } elsif ($type eq 'captcha') { + if ($cancreate{$type} eq 'notused') { + $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.'); + } else { + my %captchas = &captcha_phrases(); + if ($captchas{$cancreate{$type}}) { + $chgtext .= &mt("Validation for self-creation screen set to $captchas{$cancreate{$type}}."); + } else { + $chgtext .= &mt('Validation for self-creation screen set to unknown type.'); + } + } + } elsif ($type eq 'recaptchakeys') { + my ($privkey,$pubkey); + if (ref($cancreate{$type}) eq 'HASH') { + $pubkey = $cancreate{$type}{'public'}; + $privkey = $cancreate{$type}{'private'}; + } + $chgtext .= &mt('ReCAPTCHA keys changes').'
      '; + if (!$pubkey) { + $chgtext .= '
    • '.&mt('Public key deleted').'
    • '; + } else { + $chgtext .= '
    • '.&mt('Public key set to [_1]',$pubkey).'
    • '; + } + if (!$privkey) { + $chgtext .= '
    • '.&mt('Private key deleted').'
    • '; + } else { + $chgtext .= '
    • '.&mt('Private key set to [_1]',$pubkey).'
    • '; + } + $chgtext .= '
    '; } else { if ($cancreate{$type} eq 'none') { $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.'); @@ -6429,6 +7239,59 @@ sub modify_usercreation { 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); @@ -6550,7 +7413,7 @@ sub modify_usermodification { } sub modify_defaults { - my ($dom,$r) = @_; + my ($dom,$r,%domconfig) = @_; my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors); my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def'); @@ -6636,8 +7499,17 @@ sub modify_defaults { my $cachetime = 24*60*60; &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) { - my $sysmail = $r->dir_config('lonSysEMail'); - &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext); + 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'); @@ -6657,7 +7529,7 @@ sub modify_defaults { } sub modify_scantron { - my ($r,$dom,$confname,%domconfig) = @_; + my ($r,$dom,$confname,$lastactref,%domconfig) = @_; my ($resulttext,%confhash,%changes,$errors); my $custom = 'custom.tab'; my $default = 'default.tab'; @@ -6718,6 +7590,7 @@ sub modify_scantron { } $resulttext .= ''; &Apache::loncommon::devalidate_domconfig_cache($dom); + $$lastactref = 'update'; } else { $resulttext = &mt('No changes made to bubblesheet format file'); } @@ -7085,122 +7958,56 @@ sub modify_serverstatuses { sub modify_helpsettings { my ($r,$dom,$confname,%domconfig) = @_; - my ($resulttext,$errors,%changes,%helphash); - - my $customhelpfile = $env{'form.loginhelpurl.filename'}; - my $defaulthelpfile = 'defaulthelp.html'; - my $servadm = $r->dir_config('lonAdmEMail'); - my ($configuserok,$author_ok,$switchserver) = - &config_check($dom,$confname,$servadm); - - my %defaultchecked = ('submitbugs' => 'on'); - my @offon = ('off','on'); - my %title = ( submitbugs => 'Display link for users to submit a bug', - loginhelpurl => 'Unauthenticated login help page set to custom file'); - + my ($resulttext,$errors,%changes,%helphash); + my %defaultchecked = ('submitbugs' => 'on'); + my @offon = ('off','on'); my @toggles = ('submitbugs'); - - $helphash{'helpsettings'} = {}; - - if (ref($domconfig{'helpsettings'}) ne 'HASH') { - if ($domconfig{'helpsettings'} eq '') { - $domconfig{'helpsettings'} = {}; - } - } - if (ref($domconfig{'helpsettings'}) eq 'HASH') { - foreach my $item (@toggles) { - - if ($defaultchecked{$item} eq 'on') { - if (($domconfig{'helpsettings'}{$item} eq '') && - ($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 '') && - ($env{'form.'.$item} eq '1')) { - $changes{$item} = 1; - } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) { - $changes{$item} = 1; - } - } - $helphash{'helpsettings'}{$item} = $env{'form.'.$item}; - } - - if ($customhelpfile ne '') { - my $error; - if ($configuserok eq 'ok') { - if ($switchserver) { - $error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver); - } else { - if ($author_ok eq 'ok') { - my ($result,$loginhelpurl) = - &publishlogo($r,'upload','loginhelpurl',$dom, - $confname,'help','','',$customhelpfile); - if ($result eq 'ok') { - $helphash{'helpsettings'}{'loginhelpurl'} = $loginhelpurl; - $changes{'loginhelpurl'} = 1; - } else { - $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customhelpfile,$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].",$customhelpfile,$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].",$customhelpfile,$confname,$dom,$configuserok); - } - if ($error) { - &Apache::lonnet::logthis($error); - $errors .= '
  • '.$error.'
  • '; - } - } - - if ($domconfig{'helpsettings'}{'loginhelpurl'} ne '') { - if ($env{'form.loginhelpurl_del'}) { - $helphash{'helpsettings'}{'loginhelpurl'} = ''; - $changes{'loginhelpurl'} = 1; + 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); - } else { - $putresult = 'ok'; - } - - if ($putresult eq 'ok') { - if (keys(%changes) > 0) { - $resulttext = &mt('Changes made:').'
      '; - foreach my $item (sort(keys(%changes))) { - if ($item eq 'submitbugs') { - $resulttext .= '
    • '.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'
    • '; - } - if ($item eq 'loginhelpurl') { - if ($helphash{'helpsettings'}{'loginhelpurl'} eq '') { - $resulttext .= '
    • '.&mt('[_1] help file removed; [_2] file will be used for the unathorized help page in this domain.',$customhelpfile,$defaulthelpfile).'
    • '; - } else { - $resulttext .= '
    • '.&mt("$title{$item} [_1]",$customhelpfile).'
    • '; - } - } - } - $resulttext .= '
    '; - } else { - $resulttext = &mt('No changes made to help settings'); - } - } else { - $resulttext = ''. - &mt('An error occurred: [_1]',$putresult).''; + $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom); + if ($putresult eq 'ok') { + $resulttext = &mt('Changes made:').'
      '; + foreach my $item (sort(keys(%changes))) { + if ($item eq 'submitbugs') { + $resulttext .= '
    • '.&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)).'
    • '; + } + } + $resulttext .= '
    '; + } else { + $resulttext = &mt('No changes made to help settings'); + $errors .= '
  • '. + &mt('An error occurred storing the settings: [_1]', + $putresult).'
  • '; + } } if ($errors) { - $resulttext .= &mt('The following errors occurred: ').'
      '. + $resulttext .= '
      '.&mt('The following errors occurred: ').'
        '. $errors.'
      '; } return $resulttext; @@ -7210,8 +8017,14 @@ sub modify_coursedefaults { my ($dom,%domconfig) = @_; my ($resulttext,$errors,%changes,%defaultshash); my %defaultchecked = ('canuse_pdfforms' => 'off'); - my @offon = ('off','on'); my @toggles = ('canuse_pdfforms'); + my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial', + 'uploadquota_community'); + my @types = ('official','unofficial','community'); + my %staticdefaults = ( + anonsurvey_threshold => 10, + uploadquota => 500, + ); $defaultshash{'coursedefaults'} = {}; @@ -7227,7 +8040,7 @@ sub modify_coursedefaults { if (($domconfig{'coursedefaults'}{$item} eq '') && ($env{'form.'.$item} eq '0')) { $changes{$item} = 1; - } elsif ($domconfig{'coursdefaults'}{$item} ne $env{'form.'.$item}) { + } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) { $changes{$item} = 1; } } elsif ($defaultchecked{$item} eq 'off') { @@ -7240,26 +8053,80 @@ sub modify_coursedefaults { } $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item}; } - my $currdefresponder = $domconfig{'coursedefaults'}{'anonsurvey_threshold'}; - my $newdefresponder = $env{'form.anonsurvey_threshold'}; - $newdefresponder =~ s/\D//g; - if ($newdefresponder eq '' || $newdefresponder < 1) { - $newdefresponder = 1; - } - $defaultshash{'coursedefaults'}{'anonsurvey_threshold'} = $newdefresponder; - if ($currdefresponder ne $newdefresponder) { - unless ($currdefresponder eq '' && $newdefresponder == 10) { - $changes{'anonsurvey_threshold'} = 1; + foreach my $item (@numbers) { + my ($currdef,$newdef); + my $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; + 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)) { + $changes{'coursecredits'} = 1; + } + } + $defaultshash{'coursedefaults'}{'coursecredits'} = { + official => $officialcreds, + unofficial => $unofficialcreds, + } } my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash, $dom); if ($putresult eq 'ok') { + my %domdefaults; if (keys(%changes) > 0) { - if ($changes{'canuse_pdfforms'}) { - my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); - $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'}; + if (($changes{'canuse_pdfforms'}) || ($changes{'coursecredits'}) || ($changes{'uploadquota'})) { + %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + 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'}; + } + } + 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); } @@ -7273,6 +8140,32 @@ sub modify_coursedefaults { } } elsif ($item eq 'anonsurvey_threshold') { $resulttext .= '
    • '.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'
    • '; + } elsif ($item eq 'uploadquota') { + if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') { + $resulttext .= '
    • '.&mt('Default quota for content uploaded to a course/community via Course Editor set as follows:').'
        '. + '
      • '.&mt('Official courses: [_1] MB',''.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'').'
      • '. + '
      • '.&mt('Unofficial courses: [_1] MB',''.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'').'
      • '. + '
      • '.&mt('Communities: [_1] MB',''.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'').'
      • '. + '
      '. + '
    • '; + } else { + $resulttext .= '
    • '.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'
    • '; + } + } elsif ($item eq 'coursecredits') { + if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') { + if (($domdefaults{'officialcredits'} eq '') && + ($domdefaults{'unofficialcredits'} eq '')) { + $resulttext .= '
    • '.&mt('Student credits not in use for courses in this domain').'
    • '; + } else { + $resulttext .= '
    • '.&mt('Student credits can be set per course by a Domain Coordinator, with the following defaults applying:').'
        '. + '
      • '.&mt('Official courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'official'}).'
      • '. + '
      • '.&mt('Unofficial courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}).'
      • '. + '
      '. + '
    • '; + } + } else { + $resulttext .= '
    • '.&mt('Student credits not in use for courses in this domain').'
    • '; + } } } $resulttext .= '
    '; @@ -7565,186 +8458,192 @@ sub modify_loadbalancing { my @sparestypes = ('primary','default'); my %typetitles = &sparestype_titles(); my $resulttext; - if (keys(%servers) > 1) { - my ($currbalancer,$currtargets,$currrules); - if (ref($domconfig{'loadbalancing'}) eq 'HASH') { - $currbalancer = $domconfig{'loadbalancing'}{'lonhost'}; - $currtargets = $domconfig{'loadbalancing'}{'targets'}; - $currrules = $domconfig{'loadbalancing'}{'rules'}; - } else { - ($currbalancer,$currtargets) = - &Apache::lonnet::get_lonbalancer_config(\%servers); - } - my ($saveloadbalancing,%defaultshash,%changes); - my ($alltypes,$othertypes,$titles) = - &loadbalancing_titles($dom,$intdom,$usertypes,$types); - my %ruletitles = &offloadtype_text(); - my $balancer = $env{'form.loadbalancing_lonhost'}; - if (!$servers{$balancer}) { - undef($balancer); - } - if ($currbalancer ne $balancer) { - $changes{'lonhost'} = 1; - } - $defaultshash{'loadbalancing'}{'lonhost'} = $balancer; - if ($balancer ne '') { - unless (ref($domconfig{'loadbalancing'}) eq 'HASH') { - $saveloadbalancing = 1; + 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); } - foreach my $sparetype (@sparestypes) { - my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$sparetype); - my @offloadto; - foreach my $target (@targets) { - if (($servers{$target}) && ($target ne $balancer)) { - if ($sparetype eq 'default') { - if (ref($defaultshash{'loadbalancing'}{'targets'}{'primary'}) eq 'ARRAY') { - next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{'targets'}{'primary'}})); - } - } - unless(grep(/^\Q$target\E$/,@offloadto)) { - push(@offloadto,$target); + 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'}})); } } - $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = \@offloadto; + unless(grep(/^\Q$target\E$/,@offloadto)) { + push(@offloadto,$target); + } } - } - } else { - foreach my $sparetype (@sparestypes) { - $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = []; + $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto; } } - if (ref($currtargets) eq 'HASH') { + if (ref($currtargets{$balancer}) eq 'HASH') { foreach my $sparetype (@sparestypes) { - if (ref($currtargets->{$sparetype}) eq 'ARRAY') { - my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets->{$sparetype},$defaultshash{'loadbalancing'}{'targets'}{$sparetype}); + 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{'targets'} = 1; + $changes{'curr'}{$balancer}{'targets'} = 1; } - } elsif (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') { - if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) { - $changes{'targets'} = 1; + } elsif (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') { + if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) { + $changes{'curr'}{$balancer}{'targets'} = 1; } } } } else { - foreach my $sparetype (@sparestypes) { - if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') { - if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) { - $changes{'targets'} = 1; + 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 ($balancer ne '') { - if (&Apache::lonnet::host_domain($balancer) eq $dom) { - $ishomedom = 1; - } + if (&Apache::lonnet::host_domain($balancer) eq $dom) { + $ishomedom = 1; } if (ref($alltypes) eq 'ARRAY') { foreach my $type (@{$alltypes}) { my $rule; - if ($balancer ne '') { - unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && + unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && (!$ishomedom)) { - $rule = $env{'form.loadbalancing_rules_'.$type}; - } - if ($rule eq 'specific') { - $rule = $env{'form.loadbalancing_singleserver_'.$type}; - } + $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type}; + } + if ($rule eq 'specific') { + $rule = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type}; } - $defaultshash{'loadbalancing'}{'rules'}{$type} = $rule; - if (ref($currrules) eq 'HASH') { - if ($rule ne $currrules->{$type}) { - $changes{'rules'}{$type} = 1; + $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{'rules'}{$type} = 1; + $changes{'curr'}{$balancer}{'rules'}{$type} = 1; } } } - my $nochgmsg = &mt('No changes made to Load Balancer settings.'); - if ((keys(%changes) > 0) || ($saveloadbalancing)) { - my $putresult = &Apache::lonnet::put_dom('configuration', - \%defaultshash,$dom); - if ($putresult eq 'ok') { - if (keys(%changes) > 0) { - if ($changes{'lonhost'}) { - if ($currbalancer ne '') { - &Apache::lonnet::remote_devalidate_cache($currbalancer,'loadbalancing',$dom); - } - if ($balancer eq '') { - $resulttext .= '
  • '.&mt('Load Balancing with dedicated server discontinued').'
  • '; - } else { - &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); - $resulttext .= '
  • '.&mt('Dedicated Load Balancer server set to [_1]',$balancer); - } - } else { + } + 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 .= '
  • '.&mt('Load Balancing discontinued for: [_1]',$balancer).'
  • '; &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); } - if (($changes{'targets'}) && ($balancer ne '')) { - my %offloadstr; - foreach my $sparetype (@sparestypes) { - if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') { - if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) { - $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}}); + } + if (ref($changes{'add'}) eq 'ARRAY') { + foreach my $balancer (sort(@{$changes{'add'}})) { + $resulttext .= '
  • '.&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 .= '
  • '.&mt("Servers to which Load Balance server offloads set to 'None', by default").'
  • '; - } else { - my $showoffload; - foreach my $sparetype (@sparestypes) { - $showoffload .= ''.$typetitles{$sparetype}.': '; - if (defined($offloadstr{$sparetype})) { - $showoffload .= $offloadstr{$sparetype}; + if (keys(%offloadstr) == 0) { + $resulttext .= '
  • '.&mt("Servers to which Load Balance server offloads set to 'None', by default").'
  • '; } else { - $showoffload .= &mt('None'); + my $showoffload; + foreach my $sparetype (@sparestypes) { + $showoffload .= ''.$typetitles{$sparetype}.': '; + if (defined($offloadstr{$sparetype})) { + $showoffload .= $offloadstr{$sparetype}; + } else { + $showoffload .= &mt('None'); + } + $showoffload .= (' 'x3); + } + $resulttext .= '
  • '.&mt('By default, Load Balancer: [_1] set to offload to - [_2]',$balancer,$showoffload).'
  • '; } - $showoffload .= (' 'x3); } - $resulttext .= '
  • '.&mt('By default, Load Balancer server set to offload to: [_1]',$showoffload).'
  • '; } - } - if ((ref($changes{'rules'}) eq 'HASH') && ($balancer ne '')) { - if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) { - foreach my $type (@{$alltypes}) { - if ($changes{'rules'}{$type}) { - my $rule = $defaultshash{'loadbalancing'}{'rules'}{$type}; - my $balancetext; - if ($rule eq '') { - $balancetext = $ruletitles{'default'}; - } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer')) { - $balancetext = $ruletitles{$rule}; - } else { - $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{'rules'}{$type}); + 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')) { + $balancetext = $ruletitles{$rule}; + } else { + $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type}); + } + $resulttext .= '
  • '.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'
  • '; } - $resulttext .= '
  • '.&mt('Load Balancing for [_1] set to: [_2]',$titles->{$type},$balancetext).'
  • '; } } } + &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); } - if ($resulttext ne '') { - $resulttext = &mt('Changes made:').'
      '.$resulttext.'
    '; - } else { - $resulttext = $nochgmsg; - } + } + if ($resulttext ne '') { + $resulttext = &mt('Changes made:').'
      '.$resulttext.'
    '; } else { $resulttext = $nochgmsg; - if ($balancer ne '') { - &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); - } } } else { - $resulttext = ''. - &mt('An error occurred: [_1]',$putresult).''; + $resulttext = $nochgmsg; } } else { - $resulttext = $nochgmsg; + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; } } else { - $resulttext = &mt('Load Balancing unavailable as this domain only has one server.'); + $resulttext = $nochgmsg; } return $resulttext; } @@ -7791,72 +8690,94 @@ sub recurse_cat_deletes { sub get_active_dcs { my ($dom) = @_; - my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']); + my $now = time; + my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now); my %domcoords; my $numdcs = 0; - my $now = time; foreach my $server (keys(%dompersonnel)) { foreach my $user (sort(keys(%{$dompersonnel{$server}}))) { my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user); - my ($end,$start) = split(':',$dompersonnel{$server}{$user}); - if (($end eq '') || ($end == 0) || ($end > $now)) { - if ($start <= $now) { - $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user}; - } - } + $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user}; } } return %domcoords; } sub active_dc_picker { - my ($dom,$curr_dc) = @_; + my ($dom,$numinrow,$inputtype,$name,%currhash) = @_; my %domcoords = &get_active_dcs($dom); - my @dcs = sort(keys(%domcoords)); - my $numdcs = scalar(@dcs); - my $datatable; - my $numinrow = 2; + 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) { - $datatable = '
    '; - for (my $i=0; $i<@dcs; $i++) { + $table = '
    '; + for (my $i=0; $i<@domcoord; $i++) { my $rem = $i%($numinrow); if ($rem == 0) { if ($i > 0) { - $datatable .= ''; + $table .= ''; } - $datatable .= ''; + $table .= ''; + $rows ++; } - my $check = ' '; - if ($curr_dc eq '') { - if (!$i) { - $check = ' checked="checked" '; + 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"'; } - } elsif ($dcs[$i] eq $curr_dc) { - $check = ' checked="checked" '; } - if ($i == @dcs - 1) { + if ($i == @domcoord - 1) { my $colsleft = $numinrow - $rem; if ($colsleft > 1) { - $datatable .= ''; } - my ($dcname,$dcdom) = split(':',$dcs[$i]); - $datatable .= ''; } - $datatable .= '
    '; + $table .= ''; } else { - $datatable .= ''; + $table .= ''; } } else { - $datatable .= ''; + $table .= ''; + } + my ($dcname,$dcdom) = split(':',$domcoord[$i]); + my $user = &Apache::loncommon::plainname($dcname,$dcdom); + $table .= '
    '; - } elsif (@dcs) { - $datatable .= ''; + $table .= '
    '; + } elsif ($numdcs == 1) { + if ($inputtype eq 'radio') { + $table .= ''; + } else { + my $check; + if (exists($currhash{$domcoord[0]})) { + $check = ' checked="checked"'; + } + $table .= ''; + $rows ++; + } } - return ($numdcs,$datatable); + return ($numdcs,$table,$rows); } sub usersession_titles { @@ -7900,7 +8821,7 @@ sub count_servers { } sub lonbalance_targets_js { - my ($dom,$types,$servers) = @_; + my ($dom,$types,$servers,$settings) = @_; my $select = &mt('Select'); my ($alltargets,$allishome,$allinsttypes,@alltypes); if (ref($servers) eq 'HASH') { @@ -7922,39 +8843,71 @@ sub lonbalance_targets_js { } 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"; + +END + +} + +sub credits_js { + return <<"END"; + + + +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) = @_; + my $primary_id = &Apache::lonnet::domain($dom,'primary'); + my $intdom = &Apache::lonnet::internet_dom($primary_id); + my %servers = &Apache::lonnet::internet_dom_servers($dom); + my %thismachine; + map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids(); + if (keys(%servers) > 1) { + foreach my $server (keys(%servers)) { + next if ($thismachine{$server}); + &Apache::lonnet::remote_devalidate_cache($server,'domainconfig',$dom); + } + } + return; +} + 1;