Annotation of loncom/interface/domainprefs.pm, revision 1.428
1.1 raeburn 1: # The LearningOnline Network with CAPA
2: # Handler to set domain-wide configuration settings
3: #
1.428 ! raeburn 4: # $Id: domainprefs.pm,v 1.427 2023/06/20 14:03:52 raeburn Exp $
1.2 albertel 5: #
1.1 raeburn 6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
1.286 raeburn 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
1.1 raeburn 24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28: #
29: ###############################################################
1.297 raeburn 30: ###############################################################
1.1 raeburn 31:
1.101 raeburn 32: =pod
33:
34: =head1 NAME
35:
36: Apache::domainprefs.pm
37:
38: =head1 SYNOPSIS
39:
40: Handles configuration of a LON-CAPA domain.
41:
42: This is part of the LearningOnline Network with CAPA project
43: described at http://www.lon-capa.org.
44:
45:
46: =head1 OVERVIEW
47:
48: Each institution using LON-CAPA will typically have a single domain designated
1.183 bisitz 49: for use by individuals affiliated with the institution. Accordingly, each domain
1.101 raeburn 50: may define a default set of logos and a color scheme which can be used to "brand"
51: the LON-CAPA instance. In addition, an institution will typically have a language
52: and timezone which are used for the majority of courses.
53:
54: LON-CAPA provides a mechanism to display and modify these defaults, as well as a
55: host of other domain-wide settings which determine the types of functionality
56: available to users and courses in the domain.
57:
58: There is also a mechanism to configure cataloging of courses in the domain, and
59: controls on the operation of automated processes which govern such things as
60: roster updates, user directory updates and processing of course requests.
61:
62: The domain coordination manual which is built dynamically on install/update of
63: LON-CAPA from the relevant help items provides more information about domain
64: configuration.
65:
66: Most of the domain settings are stored in the configuration.db GDBM file which is
67: housed on the primary library server for the domain in /home/httpd/lonUsers/$dom,
68: where $dom is the domain. The configuration.db stores settings in a number of
69: frozen hashes of hashes. In a few cases, domain information must be uploaded to
70: the domain as files (e.g., image files for logos etc., or plain text files for
71: bubblesheet formats). In this case the domainprefs.pm must be running in a user
72: session hosted on the primary library server in the domain, as these files are
73: stored in author space belonging to a special $dom-domainconfig user.
74:
75: domainprefs.pm in combination with lonconfigsettings.pm will retrieve and display
76: the current settings, and provides an interface to make modifications.
77:
78: =head1 SUBROUTINES
79:
80: =over
81:
82: =item print_quotas()
83:
84: Inputs: 4
85:
86: $dom,$settings,$rowtotal,$action.
87:
88: $dom is the domain, $settings is a reference to a hash of current settings for
89: the current context, $rowtotal is a reference to the scalar used to record the
1.210 raeburn 90: number of rows displayed on the page, and $action is the context (quotas,
1.163 raeburn 91: requestcourses or requestauthor).
1.101 raeburn 92:
93: The print_quotas routine was orginally created to display/store information
94: about default quota sizes for portfolio spaces for the different types of
95: institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.),
96: but is now also used to manage availability of user tools:
97: i.e., blogs, aboutme page, and portfolios, and the course request tool,
1.197 raeburn 98: used by course owners to request creation of a course, and to display/store
1.223 bisitz 99: default quota sizes for Authoring Spaces.
1.101 raeburn 100:
101: Outputs: 1
102:
103: $datatable - HTML containing form elements which allow settings to be changed.
104:
105: In the case of course requests, radio buttons are displayed for each institutional
106: affiliate type (and also default, and _LC_adv) for each of the course types
1.325 raeburn 107: (official, unofficial, community, textbook, placement, and lti).
1.425 raeburn 108: In each case the radio buttons allow the selection of one of four values:
1.101 raeburn 109:
1.104 raeburn 110: 0, approval, validate, autolimit=N (where N is blank, or a positive integer).
1.101 raeburn 111: which have the following effects:
112:
113: 0
114:
115: =over
116:
117: - course requests are not allowed for this course types/affiliation
118:
119: =back
120:
1.104 raeburn 121: approval
1.101 raeburn 122:
123: =over
124:
125: - course requests must be approved by a Doman Coordinator in the
126: course's domain
127:
128: =back
129:
130: validate
131:
132: =over
133:
134: - an institutional validation (e.g., check requestor is instructor
135: of record) needs to be passed before the course will be created. The required
136: validation is in localenroll.pm on the primary library server for the course
137: domain.
138:
139: =back
140:
141: autolimit
142:
143: =over
144:
1.143 raeburn 145: - course requests will be processed automatically up to a limit of
1.101 raeburn 146: N requests for the course type for the particular requestor.
147: If N is undefined, there is no limit to the number of course requests
148: which a course owner may submit and have processed automatically.
149:
150: =back
151:
152: =item modify_quotas()
153:
154: =back
155:
156: =cut
157:
1.1 raeburn 158: package Apache::domainprefs;
159:
160: use strict;
161: use Apache::Constants qw(:common :http);
162: use Apache::lonnet;
163: use Apache::loncommon();
164: use Apache::lonhtmlcommon();
165: use Apache::lonlocal;
1.43 raeburn 166: use Apache::lonmsg();
1.91 raeburn 167: use Apache::lonconfigsettings;
1.232 raeburn 168: use Apache::lonuserutils();
1.235 raeburn 169: use Apache::loncoursequeueadmin();
1.419 raeburn 170: use Apache::courseprefs();
1.69 raeburn 171: use LONCAPA qw(:DEFAULT :match);
1.6 raeburn 172: use LONCAPA::Enrollment;
1.81 raeburn 173: use LONCAPA::lonauthcgi();
1.275 raeburn 174: use LONCAPA::SSL;
1.9 raeburn 175: use File::Copy;
1.43 raeburn 176: use Locale::Language;
1.62 raeburn 177: use DateTime::TimeZone;
1.68 raeburn 178: use DateTime::Locale;
1.267 raeburn 179: use Time::HiRes qw( sleep );
1.373 raeburn 180: use Net::CIDR;
1.424 raeburn 181: use Crypt::CBC;
1.1 raeburn 182:
1.155 raeburn 183: my $registered_cleanup;
184: my $modified_urls;
185:
1.1 raeburn 186: sub handler {
187: my $r=shift;
188: if ($r->header_only) {
189: &Apache::loncommon::content_type($r,'text/html');
190: $r->send_http_header;
191: return OK;
192: }
193:
1.91 raeburn 194: my $context = 'domain';
1.1 raeburn 195: my $dom = $env{'request.role.domain'};
1.5 albertel 196: my $domdesc = &Apache::lonnet::domain($dom,'description');
1.1 raeburn 197: if (&Apache::lonnet::allowed('mau',$dom)) {
198: &Apache::loncommon::content_type($r,'text/html');
199: $r->send_http_header;
200: } else {
201: $env{'user.error.msg'}=
202: "/adm/domainprefs:mau:0:0:Cannot modify domain settings";
203: return HTTP_NOT_ACCEPTABLE;
204: }
1.155 raeburn 205:
206: $registered_cleanup=0;
207: @{$modified_urls}=();
208:
1.1 raeburn 209: &Apache::lonhtmlcommon::clear_breadcrumbs();
210: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.58 raeburn 211: ['phase','actions']);
1.30 raeburn 212: my $phase = 'pickactions';
1.3 raeburn 213: if ( exists($env{'form.phase'}) ) {
214: $phase = $env{'form.phase'};
215: }
1.150 raeburn 216: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.3 raeburn 217: my %domconfig =
1.6 raeburn 218: &Apache::lonnet::get_dom('configuration',['login','rolecolors',
1.125 raeburn 219: 'quotas','autoenroll','autoupdate','autocreate',
220: 'directorysrch','usercreation','usermodification',
221: 'contacts','defaults','scantron','coursecategories',
222: 'serverstatuses','requestcourses','helpsettings',
1.163 raeburn 223: 'coursedefaults','usersessions','loadbalancing',
1.267 raeburn 224: 'requestauthor','selfenrollment','inststatus',
1.421 raeburn 225: 'ltitools','toolsec','ssl','trust','lti','ltisec',
226: 'privacy','passwords','proctoring','wafproxy','ipaccess'],$dom);
1.320 raeburn 227: my %encconfig =
1.405 raeburn 228: &Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring','linkprot'],$dom,undef,1);
1.424 raeburn 229: my ($checked_is_home,$is_home);
1.297 raeburn 230: if (ref($domconfig{'ltitools'}) eq 'HASH') {
231: if (ref($encconfig{'ltitools'}) eq 'HASH') {
1.423 raeburn 232: my $home = &Apache::lonnet::domain($dom,'primary');
233: unless (($home eq 'no_host') || ($home eq '')) {
234: my @ids=&Apache::lonnet::current_machine_ids();
235: if (grep(/^\Q$home\E$/,@ids)) {
236: $is_home = 1;
237: }
238: }
1.425 raeburn 239: $checked_is_home = 1;
1.297 raeburn 240: foreach my $id (keys(%{$domconfig{'ltitools'}})) {
1.320 raeburn 241: if ((ref($domconfig{'ltitools'}{$id}) eq 'HASH') &&
242: (ref($encconfig{'ltitools'}{$id}) eq 'HASH')) {
1.421 raeburn 243: $domconfig{'ltitools'}{$id}{'key'} = $encconfig{'ltitools'}{$id}{'key'};
1.423 raeburn 244: if (($is_home) && ($phase eq 'process')) {
245: $domconfig{'ltitools'}{$id}{'secret'} = $encconfig{'ltitools'}{$id}{'secret'};
246: }
1.297 raeburn 247: }
248: }
249: }
250: }
1.320 raeburn 251: if (ref($domconfig{'lti'}) eq 'HASH') {
252: if (ref($encconfig{'lti'}) eq 'HASH') {
1.424 raeburn 253: unless ($checked_is_home) {
254: my $home = &Apache::lonnet::domain($dom,'primary');
255: unless (($home eq 'no_host') || ($home eq '')) {
256: my @ids=&Apache::lonnet::current_machine_ids();
257: if (grep(/^\Q$home\E$/,@ids)) {
258: $is_home = 1;
259: }
260: }
261: $checked_is_home = 1;
262: }
1.320 raeburn 263: foreach my $id (keys(%{$domconfig{'lti'}})) {
264: if ((ref($domconfig{'lti'}{$id}) eq 'HASH') &&
265: (ref($encconfig{'lti'}{$id}) eq 'HASH')) {
1.424 raeburn 266: $domconfig{'lti'}{$id}{'key'} = $encconfig{'lti'}{$id}{'key'};
267: if (($is_home) && ($phase eq 'process')) {
268: $domconfig{'lti'}{$id}{'secret'} = $encconfig{'lti'}{$id}{'secret'};
1.320 raeburn 269: }
270: }
271: }
272: }
273: }
1.405 raeburn 274: if (ref($domconfig{'ltisec'}) eq 'HASH') {
1.406 raeburn 275: if (ref($domconfig{'ltisec'}{'linkprot'}) eq 'HASH') {
1.405 raeburn 276: if (ref($encconfig{'linkprot'}) eq 'HASH') {
1.406 raeburn 277: foreach my $id (keys(%{$domconfig{'ltisec'}{'linkprot'}})) {
278: unless ($id =~ /^\d+$/) {
279: delete($domconfig{'ltisec'}{'linkprot'}{$id});
280: }
281: if ((ref($domconfig{'ltisec'}{'linkprot'}{$id}) eq 'HASH') &&
1.405 raeburn 282: (ref($encconfig{'linkprot'}{$id}) eq 'HASH')) {
283: foreach my $item ('key','secret') {
1.406 raeburn 284: $domconfig{'ltisec'}{'linkprot'}{$id}{$item} = $encconfig{'linkprot'}{$id}{$item};
1.405 raeburn 285: }
286: }
287: }
288: }
289: }
290: }
1.372 raeburn 291: if (ref($domconfig{'proctoring'}) eq 'HASH') {
292: if (ref($encconfig{'proctoring'}) eq 'HASH') {
293: foreach my $provider (keys(%{$domconfig{'proctoring'}})) {
294: if ((ref($domconfig{'proctoring'}{$provider}) eq 'HASH') &&
295: (ref($encconfig{'proctoring'}{$provider}) eq 'HASH')) {
296: foreach my $item ('key','secret') {
297: $domconfig{'proctoring'}{$provider}{$item} = $encconfig{'proctoring'}{$provider}{$item};
298: }
299: }
300: }
301: }
302: }
1.394 raeburn 303: my @prefs_order = ('rolecolors','login','ipaccess','defaults','wafproxy','passwords',
304: 'quotas','autoenroll','autoupdate','autocreate','directorysrch',
1.373 raeburn 305: 'contacts','privacy','usercreation','selfcreation',
1.374 raeburn 306: 'usermodification','scantron','requestcourses','requestauthor',
1.373 raeburn 307: 'coursecategories','serverstatuses','helpsettings','coursedefaults',
1.372 raeburn 308: 'ltitools','proctoring','selfenrollment','usersessions','ssl',
309: 'trust','lti');
1.171 raeburn 310: my %existing;
311: if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
312: %existing = %{$domconfig{'loadbalancing'}};
313: }
314: if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
1.150 raeburn 315: push(@prefs_order,'loadbalancing');
316: }
1.30 raeburn 317: my %prefs = (
318: 'rolecolors' =>
319: { text => 'Default color schemes',
1.67 raeburn 320: help => 'Domain_Configuration_Color_Schemes',
1.30 raeburn 321: header => [{col1 => 'Student Settings',
322: col2 => '',},
323: {col1 => 'Coordinator Settings',
324: col2 => '',},
325: {col1 => 'Author Settings',
326: col2 => '',},
327: {col1 => 'Administrator Settings',
328: col2 => '',}],
1.230 raeburn 329: print => \&print_rolecolors,
330: modify => \&modify_rolecolors,
1.30 raeburn 331: },
1.110 raeburn 332: 'login' =>
1.30 raeburn 333: { text => 'Log-in page options',
1.67 raeburn 334: help => 'Domain_Configuration_Login_Page',
1.168 raeburn 335: header => [{col1 => 'Log-in Page Items',
336: col2 => '',},
337: {col1 => 'Log-in Help',
1.256 raeburn 338: col2 => 'Value'},
339: {col1 => 'Custom HTML in document head',
1.386 raeburn 340: col2 => 'Value'},
341: {col1 => 'SSO',
342: col2 => 'Dual login: SSO and non-SSO options'},
343: ],
1.230 raeburn 344: print => \&print_login,
345: modify => \&modify_login,
1.30 raeburn 346: },
1.43 raeburn 347: 'defaults' =>
1.236 raeburn 348: { text => 'Default authentication/language/timezone/portal/types',
1.67 raeburn 349: help => 'Domain_Configuration_LangTZAuth',
1.43 raeburn 350: header => [{col1 => 'Setting',
1.236 raeburn 351: col2 => 'Value'},
352: {col1 => 'Institutional user types',
1.409 raeburn 353: col2 => 'Name displayed'},
354: {col1 => 'Mapping for missing usernames via standard log-in',
355: col2 => 'Rules in use'}],
1.230 raeburn 356: print => \&print_defaults,
357: modify => \&modify_defaults,
1.43 raeburn 358: },
1.381 raeburn 359: 'wafproxy' =>
360: { text => 'Web Application Firewall/Reverse Proxy',
1.373 raeburn 361: help => 'Domain_Configuration_WAF_Proxy',
1.381 raeburn 362: header => [{col1 => 'Domain(s)',
363: col2 => 'Servers and WAF/Reverse Proxy alias(es)',
1.373 raeburn 364: },
1.381 raeburn 365: {col1 => 'Domain(s)',
366: col2 => 'WAF Configuration',}],
1.373 raeburn 367: print => \&print_wafproxy,
1.381 raeburn 368: modify => \&modify_wafproxy,
1.373 raeburn 369: },
1.354 raeburn 370: 'passwords' =>
371: { text => 'Passwords (Internal authentication)',
372: help => 'Domain_Configuration_Passwords',
373: header => [{col1 => 'Resetting Forgotten Password',
374: col2 => 'Settings'},
375: {col1 => 'Encryption of Stored Passwords (Internal Auth)',
376: col2 => 'Settings'},
377: {col1 => 'Rules for LON-CAPA Passwords',
378: col2 => 'Settings'},
379: {col1 => 'Course Owner Changing Student Passwords',
380: col2 => 'Settings'}],
381: print => \&print_passwords,
382: modify => \&modify_passwords,
383: },
1.30 raeburn 384: 'quotas' =>
1.413 raeburn 385: { text => 'Blogs, personal pages/timezones, webDAV/quotas, portfolio',
1.67 raeburn 386: help => 'Domain_Configuration_Quotas',
1.77 raeburn 387: header => [{col1 => 'User affiliation',
1.72 raeburn 388: col2 => 'Available tools',
1.213 raeburn 389: col3 => 'Quotas, MB; (Authoring requires role)',}],
1.230 raeburn 390: print => \&print_quotas,
391: modify => \&modify_quotas,
1.30 raeburn 392: },
393: 'autoenroll' =>
394: { text => 'Auto-enrollment settings',
1.67 raeburn 395: help => 'Domain_Configuration_Auto_Enrollment',
1.30 raeburn 396: header => [{col1 => 'Configuration setting',
397: col2 => 'Value(s)'}],
1.230 raeburn 398: print => \&print_autoenroll,
399: modify => \&modify_autoenroll,
1.30 raeburn 400: },
401: 'autoupdate' =>
402: { text => 'Auto-update settings',
1.67 raeburn 403: help => 'Domain_Configuration_Auto_Updates',
1.30 raeburn 404: header => [{col1 => 'Setting',
405: col2 => 'Value',},
1.131 raeburn 406: {col1 => 'Setting',
407: col2 => 'Affiliation'},
1.43 raeburn 408: {col1 => 'User population',
1.227 bisitz 409: col2 => 'Updatable user data'}],
1.230 raeburn 410: print => \&print_autoupdate,
411: modify => \&modify_autoupdate,
1.30 raeburn 412: },
1.125 raeburn 413: 'autocreate' =>
414: { text => 'Auto-course creation settings',
415: help => 'Domain_Configuration_Auto_Creation',
416: header => [{col1 => 'Configuration Setting',
417: col2 => 'Value',}],
1.230 raeburn 418: print => \&print_autocreate,
419: modify => \&modify_autocreate,
1.125 raeburn 420: },
1.30 raeburn 421: 'directorysrch' =>
1.277 raeburn 422: { text => 'Directory searches',
1.67 raeburn 423: help => 'Domain_Configuration_InstDirectory_Search',
1.277 raeburn 424: header => [{col1 => 'Institutional Directory Setting',
425: col2 => 'Value',},
426: {col1 => 'LON-CAPA Directory Setting',
1.30 raeburn 427: col2 => 'Value',}],
1.230 raeburn 428: print => \&print_directorysrch,
429: modify => \&modify_directorysrch,
1.30 raeburn 430: },
431: 'contacts' =>
1.286 raeburn 432: { text => 'E-mail addresses and helpform',
1.67 raeburn 433: help => 'Domain_Configuration_Contact_Info',
1.286 raeburn 434: header => [{col1 => 'Default e-mail addresses',
435: col2 => 'Value',},
436: {col1 => 'Recipient(s) for notifications',
437: col2 => 'Value',},
1.340 raeburn 438: {col1 => 'Nightly status check e-mail',
439: col2 => 'Settings',},
1.286 raeburn 440: {col1 => 'Ask helpdesk form settings',
441: col2 => 'Value',},],
1.230 raeburn 442: print => \&print_contacts,
443: modify => \&modify_contacts,
1.30 raeburn 444: },
445: 'usercreation' =>
446: { text => 'User creation',
1.67 raeburn 447: help => 'Domain_Configuration_User_Creation',
1.43 raeburn 448: header => [{col1 => 'Format rule type',
449: col2 => 'Format rules in force'},
1.34 raeburn 450: {col1 => 'User account creation',
451: col2 => 'Usernames which may be created',},
1.30 raeburn 452: {col1 => 'Context',
1.43 raeburn 453: col2 => 'Assignable authentication types'}],
1.230 raeburn 454: print => \&print_usercreation,
455: modify => \&modify_usercreation,
1.30 raeburn 456: },
1.224 raeburn 457: 'selfcreation' =>
458: { text => 'Users self-creating accounts',
459: help => 'Domain_Configuration_Self_Creation',
460: header => [{col1 => 'Self-creation with institutional username',
461: col2 => 'Enabled?'},
462: {col1 => 'Institutional user type (login/SSO self-creation)',
463: col2 => 'Information user can enter'},
1.303 raeburn 464: {col1 => 'Self-creation with e-mail verification',
1.224 raeburn 465: col2 => 'Settings'}],
1.230 raeburn 466: print => \&print_selfcreation,
467: modify => \&modify_selfcreation,
1.224 raeburn 468: },
1.69 raeburn 469: 'usermodification' =>
1.33 raeburn 470: { text => 'User modification',
1.67 raeburn 471: help => 'Domain_Configuration_User_Modification',
1.33 raeburn 472: header => [{col1 => 'Target user has role',
1.227 bisitz 473: col2 => 'User information updatable in author context'},
1.33 raeburn 474: {col1 => 'Target user has role',
1.227 bisitz 475: col2 => 'User information updatable in course context'}],
1.230 raeburn 476: print => \&print_usermodification,
477: modify => \&modify_usermodification,
1.33 raeburn 478: },
1.69 raeburn 479: 'scantron' =>
1.346 raeburn 480: { text => 'Bubblesheet format',
1.67 raeburn 481: help => 'Domain_Configuration_Scantron_Format',
1.346 raeburn 482: header => [ {col1 => 'Bubblesheet format file',
483: col2 => ''},
484: {col1 => 'Bubblesheet data upload formats',
485: col2 => 'Settings'}],
1.230 raeburn 486: print => \&print_scantron,
487: modify => \&modify_scantron,
1.46 raeburn 488: },
1.86 raeburn 489: 'requestcourses' =>
490: {text => 'Request creation of courses',
491: help => 'Domain_Configuration_Request_Courses',
492: header => [{col1 => 'User affiliation',
1.102 raeburn 493: col2 => 'Availability/Processing of requests',},
494: {col1 => 'Setting',
1.216 raeburn 495: col2 => 'Value'},
496: {col1 => 'Available textbooks',
1.235 raeburn 497: col2 => ''},
1.242 raeburn 498: {col1 => 'Available templates',
499: col2 => ''},
1.235 raeburn 500: {col1 => 'Validation (not official courses)',
501: col2 => 'Value'},],
1.230 raeburn 502: print => \&print_quotas,
503: modify => \&modify_quotas,
1.86 raeburn 504: },
1.163 raeburn 505: 'requestauthor' =>
1.223 bisitz 506: {text => 'Request Authoring Space',
1.163 raeburn 507: help => 'Domain_Configuration_Request_Author',
508: header => [{col1 => 'User affiliation',
509: col2 => 'Availability/Processing of requests',},
510: {col1 => 'Setting',
511: col2 => 'Value'}],
1.230 raeburn 512: print => \&print_quotas,
513: modify => \&modify_quotas,
1.163 raeburn 514: },
1.69 raeburn 515: 'coursecategories' =>
1.120 raeburn 516: { text => 'Cataloging of courses/communities',
1.67 raeburn 517: help => 'Domain_Configuration_Cataloging_Courses',
1.238 raeburn 518: header => [{col1 => 'Catalog type/availability',
519: col2 => '',},
520: {col1 => 'Category settings for standard catalog',
1.57 raeburn 521: col2 => '',},
522: {col1 => 'Categories',
523: col2 => '',
524: }],
1.230 raeburn 525: print => \&print_coursecategories,
526: modify => \&modify_coursecategories,
1.69 raeburn 527: },
528: 'serverstatuses' =>
1.77 raeburn 529: {text => 'Access to server status pages',
1.69 raeburn 530: help => 'Domain_Configuration_Server_Status',
531: header => [{col1 => 'Status Page',
532: col2 => 'Other named users',
533: col3 => 'Specific IPs',
534: }],
1.230 raeburn 535: print => \&print_serverstatuses,
536: modify => \&modify_serverstatuses,
1.69 raeburn 537: },
1.118 jms 538: 'helpsettings' =>
1.282 raeburn 539: {text => 'Support settings',
1.118 jms 540: help => 'Domain_Configuration_Help_Settings',
1.282 raeburn 541: header => [{col1 => 'Help Page Settings (logged-in users)',
542: col2 => 'Value'},
543: {col1 => 'Helpdesk Roles',
544: col2 => 'Settings'},],
1.230 raeburn 545: print => \&print_helpsettings,
546: modify => \&modify_helpsettings,
1.118 jms 547: },
1.121 raeburn 548: 'coursedefaults' =>
549: {text => 'Course/Community defaults',
550: help => 'Domain_Configuration_Course_Defaults',
1.139 raeburn 551: header => [{col1 => 'Defaults which can be overridden in each course by a CC',
552: col2 => 'Value',},
553: {col1 => 'Defaults which can be overridden for each course by a DC',
554: col2 => 'Value',},],
1.230 raeburn 555: print => \&print_coursedefaults,
556: modify => \&modify_coursedefaults,
1.121 raeburn 557: },
1.231 raeburn 558: 'selfenrollment' =>
559: {text => 'Self-enrollment in Course/Community',
560: help => 'Domain_Configuration_Selfenrollment',
561: header => [{col1 => 'Configuration Rights',
562: col2 => 'Configured by Course Personnel or Domain Coordinator?'},
563: {col1 => 'Defaults',
564: col2 => 'Value'},
565: {col1 => 'Self-enrollment validation (optional)',
566: col2 => 'Value'},],
567: print => \&print_selfenrollment,
568: modify => \&modify_selfenrollment,
569: },
1.120 raeburn 570: 'privacy' =>
1.427 raeburn 571: {text => 'Role assignments and user privacy',
1.120 raeburn 572: help => 'Domain_Configuration_User_Privacy',
1.357 raeburn 573: header => [{col1 => 'Role assigned in different domain',
574: col2 => 'Approval options'},
575: {col1 => 'Role assigned in different domain to user of type',
576: col2 => 'User information available in that domain'},
577: {col1 => "Role assigned in user's domain",
578: col2 => 'Information viewable by privileged user'},
579: {col1 => "Role assigned in user's domain",
580: col2 => 'Information viewable by unprivileged user'}],
1.230 raeburn 581: print => \&print_privacy,
582: modify => \&modify_privacy,
1.120 raeburn 583: },
1.141 raeburn 584: 'usersessions' =>
1.145 raeburn 585: {text => 'User session hosting/offloading',
1.137 raeburn 586: help => 'Domain_Configuration_User_Sessions',
1.145 raeburn 587: header => [{col1 => 'Domain server',
588: col2 => 'Servers to offload sessions to when busy'},
589: {col1 => 'Hosting of users from other domains',
1.137 raeburn 590: col2 => 'Rules'},
591: {col1 => "Hosting domain's own users elsewhere",
592: col2 => 'Rules'}],
1.230 raeburn 593: print => \&print_usersessions,
594: modify => \&modify_usersessions,
1.137 raeburn 595: },
1.279 raeburn 596: 'loadbalancing' =>
1.185 raeburn 597: {text => 'Dedicated Load Balancer(s)',
1.150 raeburn 598: help => 'Domain_Configuration_Load_Balancing',
1.171 raeburn 599: header => [{col1 => 'Balancers',
1.150 raeburn 600: col2 => 'Default destinations',
1.183 bisitz 601: col3 => 'User affiliation',
1.150 raeburn 602: col4 => 'Overrides'},
603: ],
1.230 raeburn 604: print => \&print_loadbalancing,
605: modify => \&modify_loadbalancing,
1.150 raeburn 606: },
1.425 raeburn 607: 'ltitools' =>
1.267 raeburn 608: {text => 'External Tools (LTI)',
1.296 raeburn 609: help => 'Domain_Configuration_LTI_Tools',
1.421 raeburn 610: header => [{col1 => 'Encryption of shared secrets',
611: col2 => 'Settings'},
612: {col1 => 'Rules for shared secrets',
613: col2 => 'Settings'},
614: {col1 => 'Providers',
615: col2 => 'Settings',}],
1.267 raeburn 616: print => \&print_ltitools,
617: modify => \&modify_ltitools,
618: },
1.372 raeburn 619: 'proctoring' =>
620: {text => 'Remote Proctoring Integration',
621: help => 'Domain_Configuration_Proctoring',
622: header => [{col1 => 'Name',
623: col2 => 'Configuration'}],
624: print => \&print_proctoring,
625: modify => \&modify_proctoring,
626: },
1.279 raeburn 627: 'ssl' =>
1.275 raeburn 628: {text => 'LON-CAPA Network (SSL)',
629: help => 'Domain_Configuration_Network_SSL',
630: header => [{col1 => 'Server',
631: col2 => 'Certificate Status'},
632: {col1 => 'Connections to other servers',
633: col2 => 'Rules'},
1.293 raeburn 634: {col1 => 'Connections from other servers',
635: col2 => 'Rules'},
1.275 raeburn 636: {col1 => "Replicating domain's published content",
637: col2 => 'Rules'}],
638: print => \&print_ssl,
639: modify => \&modify_ssl,
640: },
1.279 raeburn 641: 'trust' =>
642: {text => 'Trust Settings',
643: help => 'Domain_Configuration_Trust',
644: header => [{col1 => "Access to this domain's content by others",
645: col2 => 'Rules'},
646: {col1 => "Access to other domain's content by this domain",
647: col2 => 'Rules'},
648: {col1 => "Enrollment in this domain's courses by others",
649: col2 => 'Rules',},
650: {col1 => "Co-author roles in this domain for others",
651: col2 => 'Rules',},
652: {col1 => "Co-author roles for this domain's users elsewhere",
653: col2 => 'Rules',},
654: {col1 => "Domain roles in this domain assignable to others",
655: col2 => 'Rules'},
656: {col1 => "Course catalog for this domain displayed elsewhere",
657: col2 => 'Rules'},
658: {col1 => "Requests for creation of courses in this domain by others",
659: col2 => 'Rules'},
660: {col1 => "Users in other domains can send messages to this domain",
661: col2 => 'Rules'},],
662: print => \&print_trust,
663: modify => \&modify_trust,
664: },
1.425 raeburn 665: 'lti' =>
1.405 raeburn 666: {text => 'LTI Link Protection and LTI Consumers',
1.320 raeburn 667: help => 'Domain_Configuration_LTI_Provider',
1.405 raeburn 668: header => [{col1 => 'Encryption of shared secrets',
669: col2 => 'Settings'},
1.425 raeburn 670: {col1 => 'Rules for shared secrets',
1.405 raeburn 671: col2 => 'Settings'},
1.406 raeburn 672: {col1 => 'Link Protectors',
1.405 raeburn 673: col2 => 'Settings'},
674: {col1 => 'Consumers',
675: col2 => 'Settings'},],
1.320 raeburn 676: print => \&print_lti,
677: modify => \&modify_lti,
678: },
1.425 raeburn 679: 'ipaccess' =>
1.394 raeburn 680: {text => 'IP-based access control',
681: help => 'Domain_Configuration_IP_Access',
682: header => [{col1 => 'Setting',
683: col2 => 'Value'},],
684: print => \&print_ipaccess,
685: modify => \&modify_ipaccess,
686: },
1.3 raeburn 687: );
1.110 raeburn 688: if (keys(%servers) > 1) {
689: $prefs{'login'} = { text => 'Log-in page options',
690: help => 'Domain_Configuration_Login_Page',
691: header => [{col1 => 'Log-in Service',
692: col2 => 'Server Setting',},
693: {col1 => 'Log-in Page Items',
1.405 raeburn 694: col2 => 'Settings'},
1.168 raeburn 695: {col1 => 'Log-in Help',
1.256 raeburn 696: col2 => 'Value'},
697: {col1 => 'Custom HTML in document head',
1.386 raeburn 698: col2 => 'Value'},
699: {col1 => 'SSO',
700: col2 => 'Dual login: SSO and non-SSO options'},
701: ],
1.230 raeburn 702: print => \&print_login,
703: modify => \&modify_login,
1.110 raeburn 704: };
705: }
1.174 foxr 706:
1.6 raeburn 707: my @roles = ('student','coordinator','author','admin');
1.30 raeburn 708: my @actions = &Apache::loncommon::get_env_multiple('form.actions');
1.3 raeburn 709: &Apache::lonhtmlcommon::add_breadcrumb
1.30 raeburn 710: ({href=>"javascript:changePage(document.$phase,'pickactions')",
1.133 raeburn 711: text=>"Settings to display/modify"});
1.9 raeburn 712: my $confname = $dom.'-domainconfig';
1.174 foxr 713:
1.3 raeburn 714: if ($phase eq 'process') {
1.212 raeburn 715: my $result = &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,
716: \%prefs,\%domconfig,$confname,\@roles);
1.224 raeburn 717: if ((ref($result) eq 'HASH') && (keys(%{$result}))) {
1.205 raeburn 718: $r->rflush();
1.212 raeburn 719: &devalidate_remote_domconfs($dom,$result);
1.205 raeburn 720: }
1.30 raeburn 721: } elsif ($phase eq 'display') {
1.192 raeburn 722: my $js = &recaptcha_js().
1.236 raeburn 723: &toggle_display_js();
1.171 raeburn 724: if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
1.152 raeburn 725: my ($othertitle,$usertypes,$types) =
726: &Apache::loncommon::sorted_inst_types($dom);
1.171 raeburn 727: $js .= &lonbalance_targets_js($dom,$types,\%servers,
728: $domconfig{'loadbalancing'}).
1.170 raeburn 729: &new_spares_js().
730: &common_domprefs_js().
731: &Apache::loncommon::javascript_array_indexof();
1.152 raeburn 732: }
1.216 raeburn 733: if (grep(/^requestcourses$/,@actions)) {
734: my $javascript_validations;
735: my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'});
736: $js .= <<END;
737: <script type="text/javascript">
738: $javascript_validations
739: </script>
740: $coursebrowserjs
741: END
1.394 raeburn 742: } elsif (grep(/^ipaccess$/,@actions)) {
743: $js .= &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'});
1.216 raeburn 744: }
1.305 raeburn 745: if (grep(/^selfcreation$/,@actions)) {
746: $js .= &selfcreate_javascript();
747: }
1.286 raeburn 748: if (grep(/^contacts$/,@actions)) {
749: $js .= &contacts_javascript();
750: }
1.346 raeburn 751: if (grep(/^scantron$/,@actions)) {
752: $js .= &scantron_javascript();
753: }
1.150 raeburn 754: &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
1.1 raeburn 755: } else {
1.180 raeburn 756: # check if domconfig user exists for the domain.
757: my $servadm = $r->dir_config('lonAdmEMail');
758: my ($configuserok,$author_ok,$switchserver) =
759: &config_check($dom,$confname,$servadm);
760: unless ($configuserok eq 'ok') {
1.181 raeburn 761: &Apache::lonconfigsettings::print_header($r,$phase,$context);
762: $r->print(&mt('The domain configuration user "[_1]" has yet to be created.',
1.210 raeburn 763: $confname).
1.181 raeburn 764: '<br />'
765: );
1.180 raeburn 766: if ($switchserver) {
1.181 raeburn 767: $r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.').
768: '<br />'.
769: &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.').
770: '<br />'.
771: &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).
772: '<br />'.
773: &mt('To do that now, use the following link: [_1]',$switchserver)
774: );
775: } else {
776: $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.').
777: '<br />'.
778: &mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain')
779: );
1.180 raeburn 780: }
781: $r->print(&Apache::loncommon::end_page());
782: return OK;
783: }
1.21 raeburn 784: if (keys(%domconfig) == 0) {
785: my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
1.29 raeburn 786: my @ids=&Apache::lonnet::current_machine_ids();
787: if (!grep(/^\Q$primarylibserv\E$/,@ids)) {
1.21 raeburn 788: my %designhash = &Apache::loncommon::get_domainconf($dom);
1.41 raeburn 789: my @loginimages = ('img','logo','domlogo','login');
1.21 raeburn 790: my $custom_img_count = 0;
791: foreach my $img (@loginimages) {
792: if ($designhash{$dom.'.login.'.$img} ne '') {
793: $custom_img_count ++;
794: }
795: }
796: foreach my $role (@roles) {
797: if ($designhash{$dom.'.'.$role.'.img'} ne '') {
798: $custom_img_count ++;
799: }
800: }
801: if ($custom_img_count > 0) {
1.94 raeburn 802: &Apache::lonconfigsettings::print_header($r,$phase,$context);
1.21 raeburn 803: my $switch_server = &check_switchserver($dom,$confname);
1.29 raeburn 804: $r->print(
805: &mt('Domain configuration settings have yet to be saved for this domain via the web-based domain preferences interface.').'<br />'.
806: &mt("While this remains so, you must switch to the domain's primary library server in order to update settings.").'<br /><br />'.
807: &mt("Thereafter, (with a Domain Coordinator role selected in the domain) you will be able to update settings when logged in to any server in the LON-CAPA network.").'<br />'.
808: &mt("However, you will still need to switch to the domain's primary library server to upload new images or logos.").'<br /><br />');
809: if ($switch_server) {
1.30 raeburn 810: $r->print($switch_server.' '.&mt('to primary library server for domain: [_1]',$dom));
1.29 raeburn 811: }
1.91 raeburn 812: $r->print(&Apache::loncommon::end_page());
1.21 raeburn 813: return OK;
814: }
815: }
816: }
1.91 raeburn 817: &Apache::lonconfigsettings::display_choices($r,$phase,$context,\@prefs_order,\%prefs);
1.3 raeburn 818: }
819: return OK;
820: }
821:
822: sub process_changes {
1.205 raeburn 823: my ($r,$dom,$confname,$action,$roles,$values,$lastactref) = @_;
1.92 raeburn 824: my %domconfig;
825: if (ref($values) eq 'HASH') {
826: %domconfig = %{$values};
827: }
1.3 raeburn 828: my $output;
829: if ($action eq 'login') {
1.205 raeburn 830: $output = &modify_login($r,$dom,$confname,$lastactref,%domconfig);
1.6 raeburn 831: } elsif ($action eq 'rolecolors') {
1.9 raeburn 832: $output = &modify_rolecolors($r,$dom,$confname,$roles,
1.205 raeburn 833: $lastactref,%domconfig);
1.3 raeburn 834: } elsif ($action eq 'quotas') {
1.216 raeburn 835: $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
1.3 raeburn 836: } elsif ($action eq 'autoenroll') {
1.205 raeburn 837: $output = &modify_autoenroll($dom,$lastactref,%domconfig);
1.3 raeburn 838: } elsif ($action eq 'autoupdate') {
839: $output = &modify_autoupdate($dom,%domconfig);
1.125 raeburn 840: } elsif ($action eq 'autocreate') {
841: $output = &modify_autocreate($dom,%domconfig);
1.23 raeburn 842: } elsif ($action eq 'directorysrch') {
1.295 raeburn 843: $output = &modify_directorysrch($dom,$lastactref,%domconfig);
1.27 raeburn 844: } elsif ($action eq 'usercreation') {
1.28 raeburn 845: $output = &modify_usercreation($dom,%domconfig);
1.224 raeburn 846: } elsif ($action eq 'selfcreation') {
1.305 raeburn 847: $output = &modify_selfcreation($dom,$lastactref,%domconfig);
1.33 raeburn 848: } elsif ($action eq 'usermodification') {
849: $output = &modify_usermodification($dom,%domconfig);
1.28 raeburn 850: } elsif ($action eq 'contacts') {
1.205 raeburn 851: $output = &modify_contacts($dom,$lastactref,%domconfig);
1.43 raeburn 852: } elsif ($action eq 'defaults') {
1.212 raeburn 853: $output = &modify_defaults($dom,$lastactref,%domconfig);
1.46 raeburn 854: } elsif ($action eq 'scantron') {
1.205 raeburn 855: $output = &modify_scantron($r,$dom,$confname,$lastactref,%domconfig);
1.48 raeburn 856: } elsif ($action eq 'coursecategories') {
1.239 raeburn 857: $output = &modify_coursecategories($dom,$lastactref,%domconfig);
1.69 raeburn 858: } elsif ($action eq 'serverstatuses') {
859: $output = &modify_serverstatuses($dom,%domconfig);
1.86 raeburn 860: } elsif ($action eq 'requestcourses') {
1.216 raeburn 861: $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
1.163 raeburn 862: } elsif ($action eq 'requestauthor') {
1.216 raeburn 863: $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig);
1.118 jms 864: } elsif ($action eq 'helpsettings') {
1.285 raeburn 865: $output = &modify_helpsettings($r,$dom,$confname,$lastactref,%domconfig);
1.121 raeburn 866: } elsif ($action eq 'coursedefaults') {
1.212 raeburn 867: $output = &modify_coursedefaults($dom,$lastactref,%domconfig);
1.231 raeburn 868: } elsif ($action eq 'selfenrollment') {
869: $output = &modify_selfenrollment($dom,$lastactref,%domconfig)
1.137 raeburn 870: } elsif ($action eq 'usersessions') {
1.212 raeburn 871: $output = &modify_usersessions($dom,$lastactref,%domconfig);
1.150 raeburn 872: } elsif ($action eq 'loadbalancing') {
873: $output = &modify_loadbalancing($dom,%domconfig);
1.267 raeburn 874: } elsif ($action eq 'ltitools') {
875: $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
1.372 raeburn 876: } elsif ($action eq 'proctoring') {
877: $output = &modify_proctoring($r,$dom,$action,$lastactref,%domconfig);
1.275 raeburn 878: } elsif ($action eq 'ssl') {
879: $output = &modify_ssl($dom,$lastactref,%domconfig);
1.279 raeburn 880: } elsif ($action eq 'trust') {
881: $output = &modify_trust($dom,$lastactref,%domconfig);
1.320 raeburn 882: } elsif ($action eq 'lti') {
883: $output = &modify_lti($r,$dom,$action,$lastactref,%domconfig);
1.357 raeburn 884: } elsif ($action eq 'privacy') {
1.427 raeburn 885: $output = &modify_privacy($dom,$lastactref,%domconfig);
1.354 raeburn 886: } elsif ($action eq 'passwords') {
887: $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);
1.373 raeburn 888: } elsif ($action eq 'wafproxy') {
889: $output = &modify_wafproxy($dom,$action,$lastactref,%domconfig);
1.394 raeburn 890: } elsif ($action eq 'ipaccess') {
891: $output = &modify_ipaccess($dom,$lastactref,%domconfig);
1.3 raeburn 892: }
893: return $output;
894: }
895:
896: sub print_config_box {
1.9 raeburn 897: my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_;
1.30 raeburn 898: my $rowtotal = 0;
1.49 raeburn 899: my $output;
900: if ($action eq 'coursecategories') {
901: $output = &coursecategories_javascript($settings);
1.236 raeburn 902: } elsif ($action eq 'defaults') {
903: $output = &defaults_javascript($settings);
1.354 raeburn 904: } elsif ($action eq 'passwords') {
1.405 raeburn 905: $output = &passwords_javascript($action);
1.282 raeburn 906: } elsif ($action eq 'helpsettings') {
907: my (%privs,%levelscurrent);
908: my %full=();
909: my %levels=(
910: course => {},
911: domain => {},
912: system => {},
913: );
914: my $context = 'domain';
915: my $crstype = 'Course';
916: my $formname = 'display';
917: &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
918: my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
919: $output =
1.425 raeburn 920: &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,
1.282 raeburn 921: \@templateroles);
1.334 raeburn 922: } elsif ($action eq 'ltitools') {
1.421 raeburn 923: $output .= &Apache::lonconfigsettings::ltitools_javascript($settings);
1.334 raeburn 924: } elsif ($action eq 'lti') {
1.421 raeburn 925: $output .= &passwords_javascript('ltisecrets')."\n".
1.405 raeburn 926: <i_javascript($dom,$settings);
1.372 raeburn 927: } elsif ($action eq 'proctoring') {
928: $output .= &proctoring_javascript($settings);
1.381 raeburn 929: } elsif ($action eq 'wafproxy') {
930: $output .= &wafproxy_javascript($dom);
1.385 raeburn 931: } elsif ($action eq 'autoupdate') {
932: $output .= &autoupdate_javascript();
1.399 raeburn 933: } elsif ($action eq 'autoenroll') {
934: $output .= &autoenroll_javascript();
1.386 raeburn 935: } elsif ($action eq 'login') {
936: $output .= &saml_javascript();
1.394 raeburn 937: } elsif ($action eq 'ipaccess') {
938: $output .= &ipaccess_javascript($settings);
1.91 raeburn 939: }
1.236 raeburn 940: $output .=
1.30 raeburn 941: '<table class="LC_nested_outer">
1.3 raeburn 942: <tr>
1.306 raeburn 943: <th class="LC_left_item LC_middle"><span class="LC_nobreak">'.
1.66 raeburn 944: &mt($item->{text}).' '.
945: &Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".
946: '</tr>';
1.30 raeburn 947: $rowtotal ++;
1.110 raeburn 948: my $numheaders = 1;
949: if (ref($item->{'header'}) eq 'ARRAY') {
950: $numheaders = scalar(@{$item->{'header'}});
951: }
952: if ($numheaders > 1) {
1.64 raeburn 953: my $colspan = '';
1.145 raeburn 954: my $rightcolspan = '';
1.369 raeburn 955: my $leftnobr = '';
1.238 raeburn 956: if (($action eq 'rolecolors') || ($action eq 'defaults') ||
1.277 raeburn 957: ($action eq 'directorysrch') ||
1.386 raeburn 958: (($action eq 'login') && ($numheaders < 5))) {
1.64 raeburn 959: $colspan = ' colspan="2"';
960: }
1.145 raeburn 961: if ($action eq 'usersessions') {
962: $rightcolspan = ' colspan="3"';
963: }
1.369 raeburn 964: if ($action eq 'passwords') {
965: $leftnobr = ' LC_nobreak';
966: }
1.30 raeburn 967: $output .= '
1.3 raeburn 968: <tr>
969: <td>
970: <table class="LC_nested">
971: <tr class="LC_info_row">
1.369 raeburn 972: <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
1.145 raeburn 973: <td class="LC_right_item"'.$rightcolspan.'>'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
1.30 raeburn 974: </tr>';
1.69 raeburn 975: $rowtotal ++;
1.230 raeburn 976: if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||
1.236 raeburn 977: ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
1.277 raeburn 978: ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
1.286 raeburn 979: ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
1.421 raeburn 980: ($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'wafproxy') ||
981: ($action eq 'lti') || ($action eq 'ltitools')) {
1.230 raeburn 982: $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
1.354 raeburn 983: } elsif ($action eq 'passwords') {
984: $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);
1.57 raeburn 985: } elsif ($action eq 'coursecategories') {
1.230 raeburn 986: $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
1.346 raeburn 987: } elsif ($action eq 'scantron') {
988: $output .= $item->{'print'}->($r,'top',$dom,$confname,$settings,\$rowtotal);
1.110 raeburn 989: } elsif ($action eq 'login') {
1.386 raeburn 990: if ($numheaders == 5) {
1.168 raeburn 991: $colspan = ' colspan="2"';
992: $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal);
993: } else {
994: $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal);
995: }
1.230 raeburn 996: } elsif (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
1.163 raeburn 997: $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
1.122 jms 998: } elsif ($action eq 'rolecolors') {
1.30 raeburn 999: $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal);
1.6 raeburn 1000: }
1.30 raeburn 1001: $output .= '
1.6 raeburn 1002: </table>
1003: </td>
1004: </tr>
1005: <tr>
1006: <td>
1007: <table class="LC_nested">
1008: <tr class="LC_info_row">
1.230 raeburn 1009: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col1'}).'</td>
1.59 bisitz 1010: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
1.30 raeburn 1011: </tr>';
1012: $rowtotal ++;
1.230 raeburn 1013: if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
1014: ($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
1.275 raeburn 1015: ($action eq 'usersessions') || ($action eq 'coursecategories') ||
1.409 raeburn 1016: ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults') ||
1.421 raeburn 1017: ($action eq 'privacy') || ($action eq 'passwords') || ($action eq 'lti') ||
1018: ($action eq 'ltitools')) {
1.238 raeburn 1019: if ($action eq 'coursecategories') {
1020: $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
1021: $colspan = ' colspan="2"';
1.279 raeburn 1022: } elsif ($action eq 'trust') {
1023: $output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
1.354 raeburn 1024: } elsif ($action eq 'passwords') {
1025: $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);
1.238 raeburn 1026: } else {
1027: $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
1028: }
1.279 raeburn 1029: if ($action eq 'trust') {
1030: $output .= '
1031: </table>
1032: </td>
1033: </tr>';
1034: my @trusthdrs = qw(2 3 4 5 6 7);
1035: my @prefixes = qw(enroll othcoau coaurem domroles catalog reqcrs);
1036: for (my $i=0; $i<@trusthdrs; $i++) {
1037: $output .= '
1038: <tr>
1039: <td>
1040: <table class="LC_nested">
1041: <tr class="LC_info_row">
1042: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col1'}).'</td>
1043: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[$trusthdrs[$i]]->{'col2'}).'</td></tr>'.
1044: $item->{'print'}->($prefixes[$i],$dom,$settings,\$rowtotal).'
1045: </table>
1046: </td>
1047: </tr>';
1048: }
1049: $output .= '
1050: <tr>
1051: <td>
1052: <table class="LC_nested">
1053: <tr class="LC_info_row">
1054: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col1'}).'</td>
1055: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col2'}).'</td></tr>'.
1056: $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
1057: } else {
1058: $output .= '
1.63 raeburn 1059: </table>
1060: </td>
1061: </tr>
1062: <tr>
1063: <td>
1064: <table class="LC_nested">
1065: <tr class="LC_info_row">
1066: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
1.224 raeburn 1067: <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
1.238 raeburn 1068: </tr>'."\n";
1.279 raeburn 1069: if ($action eq 'coursecategories') {
1070: $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
1.405 raeburn 1071: } elsif (($action eq 'contacts') || ($action eq 'privacy') ||
1072: ($action eq 'passwords') || ($action eq 'lti')) {
1.354 raeburn 1073: if ($action eq 'passwords') {
1074: $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal);
1075: } else {
1076: $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal);
1077: }
1078: $output .= '
1.340 raeburn 1079: </tr>
1080: </table>
1081: </td>
1082: </tr>
1083: <tr>
1084: <td>
1085: <table class="LC_nested">
1086: <tr class="LC_info_row">
1.369 raeburn 1087: <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
1.354 raeburn 1088: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n";
1089: if ($action eq 'passwords') {
1090: $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal);
1091: } else {
1092: $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
1093: }
1094: $output .= '
1.340 raeburn 1095: </table>
1096: </td>
1097: </tr>
1098: <tr>';
1.279 raeburn 1099: } else {
1100: $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
1101: }
1.238 raeburn 1102: }
1.63 raeburn 1103: $rowtotal ++;
1.236 raeburn 1104: } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
1.409 raeburn 1105: ($action eq 'directorysrch') || ($action eq 'helpsettings') ||
1106: ($action eq 'wafproxy')) {
1.230 raeburn 1107: $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
1.346 raeburn 1108: } elsif ($action eq 'scantron') {
1109: $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);
1.293 raeburn 1110: } elsif ($action eq 'ssl') {
1111: $output .= $item->{'print'}->('connto',$dom,$settings,\$rowtotal).'
1112: </table>
1113: </td>
1114: </tr>
1115: <tr>
1116: <td>
1117: <table class="LC_nested">
1118: <tr class="LC_info_row">
1119: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
1120: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
1121: $item->{'print'}->('connfrom',$dom,$settings,\$rowtotal).'
1122: </table>
1123: </td>
1124: </tr>
1125: <tr>
1126: <td>
1127: <table class="LC_nested">
1128: <tr class="LC_info_row">
1129: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
1130: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'.
1131: $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
1.110 raeburn 1132: } elsif ($action eq 'login') {
1.386 raeburn 1133: if ($numheaders == 5) {
1.168 raeburn 1134: $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
1135: </table>
1136: </td>
1137: </tr>
1138: <tr>
1139: <td>
1140: <table class="LC_nested">
1141: <tr class="LC_info_row">
1142: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
1.216 raeburn 1143: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td></tr>'.
1.168 raeburn 1144: &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
1145: $rowtotal ++;
1146: } else {
1147: $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal);
1148: }
1.256 raeburn 1149: $output .= '
1150: </table>
1151: </td>
1152: </tr>
1153: <tr>
1154: <td>
1155: <table class="LC_nested">
1156: <tr class="LC_info_row">';
1.386 raeburn 1157: if ($numheaders == 5) {
1.256 raeburn 1158: $output .= '
1159: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
1160: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
1161: </tr>';
1162: } else {
1163: $output .= '
1164: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
1165: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
1166: </tr>';
1167: }
1168: $rowtotal ++;
1.386 raeburn 1169: $output .= &print_login('headtag',$dom,$confname,$phase,$settings,\$rowtotal).'
1170: </table>
1171: </td>
1172: </tr>
1173: <tr>
1174: <td>
1175: <table class="LC_nested">
1176: <tr class="LC_info_row">';
1177: if ($numheaders == 5) {
1178: $output .= '
1179: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[4]->{'col1'}).'</td>
1180: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[4]->{'col2'}).'</td>
1181: </tr>';
1182: } else {
1183: $output .= '
1184: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
1185: <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
1186: </tr>';
1187: }
1188: $rowtotal ++;
1189: $output .= &print_login('saml',$dom,$confname,$phase,$settings,\$rowtotal);
1.102 raeburn 1190: } elsif ($action eq 'requestcourses') {
1.247 raeburn 1191: $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
1192: $rowtotal ++;
1193: $output .= &print_studentcode($settings,\$rowtotal).'
1.216 raeburn 1194: </table>
1195: </td>
1196: </tr>
1197: <tr>
1198: <td>
1199: <table class="LC_nested">
1200: <tr class="LC_info_row">
1201: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
1202: <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> </tr>'.
1.242 raeburn 1203: &textbookcourses_javascript($settings).
1204: &print_textbookcourses($dom,'textbooks',$settings,\$rowtotal).'
1205: </table>
1206: </td>
1207: </tr>
1208: <tr>
1209: <td>
1210: <table class="LC_nested">
1211: <tr class="LC_info_row">
1212: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
1213: <td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td> </tr>'.
1214: &print_textbookcourses($dom,'templates',$settings,\$rowtotal).'
1.235 raeburn 1215: </table>
1216: </td>
1217: </tr>
1218: <tr>
1219: <td>
1220: <table class="LC_nested">
1221: <tr class="LC_info_row">
1.306 raeburn 1222: <td class="LC_left_item"'.$colspan.' style="vertical-align: top">'.&mt($item->{'header'}->[4]->{'col1'}).'</td>
1223: <td class="LC_right_item" style="vertical-align: top">'.&mt($item->{'header'}->[4]->{'col2'}).'</td>
1.235 raeburn 1224: </tr>'.
1225: &print_validation_rows('requestcourses',$dom,$settings,\$rowtotal);
1.163 raeburn 1226: } elsif ($action eq 'requestauthor') {
1227: $output .= &print_requestmail($dom,$action,$settings,\$rowtotal);
1.247 raeburn 1228: $rowtotal ++;
1.122 jms 1229: } elsif ($action eq 'rolecolors') {
1.30 raeburn 1230: $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
1.6 raeburn 1231: </table>
1232: </td>
1233: </tr>
1234: <tr>
1235: <td>
1236: <table class="LC_nested">
1237: <tr class="LC_info_row">
1.306 raeburn 1238: <td class="LC_left_item"'.$colspan.' style="vertical-align: top">'.
1.69 raeburn 1239: &mt($item->{'header'}->[2]->{'col1'}).'</td>
1.306 raeburn 1240: <td class="LC_right_item" style="vertical-align: top">'.
1.69 raeburn 1241: &mt($item->{'header'}->[2]->{'col2'}).'</td>
1.3 raeburn 1242: </tr>'.
1.30 raeburn 1243: &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
1.3 raeburn 1244: </table>
1245: </td>
1246: </tr>
1247: <tr>
1248: <td>
1249: <table class="LC_nested">
1250: <tr class="LC_info_row">
1.59 bisitz 1251: <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
1252: <td class="LC_right_item">'.&mt($item->{'header'}->[3]->{'col2'}).'</td>
1.3 raeburn 1253: </tr>'.
1.30 raeburn 1254: &print_rolecolors($phase,'admin',$dom,$confname,$settings,\$rowtotal);
1255: $rowtotal += 2;
1.6 raeburn 1256: }
1.3 raeburn 1257: } else {
1.30 raeburn 1258: $output .= '
1.3 raeburn 1259: <tr>
1260: <td>
1261: <table class="LC_nested">
1.30 raeburn 1262: <tr class="LC_info_row">';
1.277 raeburn 1263: if ($action eq 'login') {
1.30 raeburn 1264: $output .= '
1.59 bisitz 1265: <td class="LC_left_item" colspan="2">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
1.69 raeburn 1266: } elsif ($action eq 'serverstatuses') {
1267: $output .= '
1.306 raeburn 1268: <td class="LC_left_item" style="vertical-align: top">'.&mt($item->{'header'}->[0]->{'col1'}).
1.69 raeburn 1269: '<br />('.&mt('Automatic access for Dom. Coords.').')</td>';
1270:
1.6 raeburn 1271: } else {
1.30 raeburn 1272: $output .= '
1.306 raeburn 1273: <td class="LC_left_item" style="vertical-align: top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
1.69 raeburn 1274: }
1.72 raeburn 1275: if (defined($item->{'header'}->[0]->{'col3'})) {
1.306 raeburn 1276: $output .= '<td class="LC_left_item" style="vertical-align: top">'.
1.72 raeburn 1277: &mt($item->{'header'}->[0]->{'col2'});
1278: if ($action eq 'serverstatuses') {
1279: $output .= '<br />(<tt>'.&mt('user1:domain1,user2:domain2 etc.').'</tt>)';
1280: }
1.69 raeburn 1281: } else {
1.306 raeburn 1282: $output .= '<td class="LC_right_item" style="vertical-align: top">'.
1.69 raeburn 1283: &mt($item->{'header'}->[0]->{'col2'});
1284: }
1285: $output .= '</td>';
1286: if ($item->{'header'}->[0]->{'col3'}) {
1.150 raeburn 1287: if (defined($item->{'header'}->[0]->{'col4'})) {
1.306 raeburn 1288: $output .= '<td class="LC_left_item" style="vertical-align: top">'.
1.150 raeburn 1289: &mt($item->{'header'}->[0]->{'col3'});
1290: } else {
1.306 raeburn 1291: $output .= '<td class="LC_right_item" style="vertical-align: top">'.
1.150 raeburn 1292: &mt($item->{'header'}->[0]->{'col3'});
1293: }
1.69 raeburn 1294: if ($action eq 'serverstatuses') {
1295: $output .= '<br />(<tt>'.&mt('IP1,IP2 etc.').'</tt>)';
1296: }
1297: $output .= '</td>';
1.6 raeburn 1298: }
1.150 raeburn 1299: if ($item->{'header'}->[0]->{'col4'}) {
1.306 raeburn 1300: $output .= '<td class="LC_right_item" style="vertical-align: top">'.
1.150 raeburn 1301: &mt($item->{'header'}->[0]->{'col4'});
1302: }
1.69 raeburn 1303: $output .= '</tr>';
1.48 raeburn 1304: $rowtotal ++;
1.168 raeburn 1305: if ($action eq 'quotas') {
1.86 raeburn 1306: $output .= &print_quotas($dom,$settings,\$rowtotal,$action);
1.277 raeburn 1307: } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') ||
1.286 raeburn 1308: ($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||
1.421 raeburn 1309: ($action eq 'proctoring') || ($action eq 'ipaccess')) {
1.230 raeburn 1310: $output .= $item->{'print'}->($dom,$settings,\$rowtotal);
1.121 raeburn 1311: }
1.3 raeburn 1312: }
1.30 raeburn 1313: $output .= '
1.3 raeburn 1314: </table>
1315: </td>
1316: </tr>
1.30 raeburn 1317: </table><br />';
1318: return ($output,$rowtotal);
1.1 raeburn 1319: }
1320:
1.3 raeburn 1321: sub print_login {
1.168 raeburn 1322: my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_;
1.386 raeburn 1323: my ($css_class,$datatable,$switchserver,%lt);
1.6 raeburn 1324: my %choices = &login_choices();
1.386 raeburn 1325: if (($caller eq 'help') || ($caller eq 'headtag') || ($caller eq 'saml')) {
1326: %lt = &login_file_options();
1327: $switchserver = &check_switchserver($dom,$confname);
1328: }
1.168 raeburn 1329: if ($caller eq 'service') {
1.149 raeburn 1330: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.110 raeburn 1331: my $choice = $choices{'disallowlogin'};
1332: $css_class = ' class="LC_odd_row"';
1.128 raeburn 1333: $datatable .= '<tr'.$css_class.'><td>'.$choice.'</td>'.
1.306 raeburn 1334: '<td style="text-align: right"><table><tr><th>'.$choices{'hostid'}.'</th>'.
1.128 raeburn 1335: '<th>'.$choices{'server'}.'</th>'.
1336: '<th>'.$choices{'serverpath'}.'</th>'.
1337: '<th>'.$choices{'custompath'}.'</th>'.
1338: '<th><span class="LC_nobreak">'.$choices{'exempt'}.'</span></th></tr>'."\n";
1.110 raeburn 1339: my %disallowed;
1340: if (ref($settings) eq 'HASH') {
1341: if (ref($settings->{'loginvia'}) eq 'HASH') {
1342: %disallowed = %{$settings->{'loginvia'}};
1343: }
1344: }
1345: foreach my $lonhost (sort(keys(%servers))) {
1346: my $direct = 'selected="selected"';
1.128 raeburn 1347: if (ref($disallowed{$lonhost}) eq 'HASH') {
1348: if ($disallowed{$lonhost}{'server'} ne '') {
1349: $direct = '';
1350: }
1.110 raeburn 1351: }
1.115 raeburn 1352: $datatable .= '<tr><td>'.$servers{$lonhost}.'</td>'.
1.128 raeburn 1353: '<td><select name="'.$lonhost.'_server">'.
1.110 raeburn 1354: '<option value=""'.$direct.'>'.$choices{'directlogin'}.
1355: '</option>';
1.184 raeburn 1356: foreach my $hostid (sort(keys(%servers))) {
1.115 raeburn 1357: next if ($servers{$hostid} eq $servers{$lonhost});
1.110 raeburn 1358: my $selected = '';
1.128 raeburn 1359: if (ref($disallowed{$lonhost}) eq 'HASH') {
1360: if ($hostid eq $disallowed{$lonhost}{'server'}) {
1361: $selected = 'selected="selected"';
1362: }
1.110 raeburn 1363: }
1364: $datatable .= '<option value="'.$hostid.'"'.$selected.'>'.
1365: $servers{$hostid}.'</option>';
1366: }
1.128 raeburn 1367: $datatable .= '</select></td>'.
1368: '<td><select name="'.$lonhost.'_serverpath">';
1369: foreach my $path ('','/','/adm/login','/adm/roles','custom') {
1370: my $pathname = $path;
1371: if ($path eq 'custom') {
1372: $pathname = &mt('Custom Path').' ->';
1373: }
1374: my $selected = '';
1375: if (ref($disallowed{$lonhost}) eq 'HASH') {
1376: if ($path eq $disallowed{$lonhost}{'serverpath'}) {
1377: $selected = 'selected="selected"';
1378: }
1379: } elsif ($path eq '') {
1380: $selected = 'selected="selected"';
1381: }
1382: $datatable .= '<option value="'.$path.'"'.$selected.'>'.$pathname.'</option>';
1383: }
1384: $datatable .= '</select></td>';
1385: my ($custom,$exempt);
1386: if (ref($disallowed{$lonhost}) eq 'HASH') {
1387: $custom = $disallowed{$lonhost}{'custompath'};
1388: $exempt = $disallowed{$lonhost}{'exempt'};
1389: }
1390: $datatable .= '<td><input type="text" name="'.$lonhost.'_custompath" size="6" value="'.$custom.'" /></td>'.
1391: '<td><input type="text" name="'.$lonhost.'_exempt" size="8" value="'.$exempt.'" /></td>'.
1392: '</tr>';
1.110 raeburn 1393: }
1394: $datatable .= '</table></td></tr>';
1395: return $datatable;
1.168 raeburn 1396: } elsif ($caller eq 'page') {
1397: my %defaultchecked = (
1398: 'coursecatalog' => 'on',
1.188 raeburn 1399: 'helpdesk' => 'on',
1.168 raeburn 1400: 'adminmail' => 'off',
1401: 'newuser' => 'off',
1402: );
1.188 raeburn 1403: my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
1.168 raeburn 1404: my (%checkedon,%checkedoff);
1.42 raeburn 1405: foreach my $item (@toggles) {
1.168 raeburn 1406: if ($defaultchecked{$item} eq 'on') {
1407: $checkedon{$item} = ' checked="checked" ';
1.42 raeburn 1408: $checkedoff{$item} = ' ';
1.168 raeburn 1409: } elsif ($defaultchecked{$item} eq 'off') {
1410: $checkedoff{$item} = ' checked="checked" ';
1.42 raeburn 1411: $checkedon{$item} = ' ';
1412: }
1.1 raeburn 1413: }
1.168 raeburn 1414: my @images = ('img','logo','domlogo','login');
1.402 raeburn 1415: my @alttext = ('img','logo','domlogo');
1.168 raeburn 1416: my @logintext = ('textcol','bgcol');
1417: my @bgs = ('pgbg','mainbg','sidebg');
1418: my @links = ('link','alink','vlink');
1419: my %designhash = &Apache::loncommon::get_domainconf($dom);
1420: my %defaultdesign = %Apache::loncommon::defaultdesign;
1421: my (%is_custom,%designs);
1422: my %defaults = (
1423: font => $defaultdesign{'login.font'},
1424: );
1.6 raeburn 1425: foreach my $item (@images) {
1.168 raeburn 1426: $defaults{$item} = $defaultdesign{'login.'.$item};
1427: $defaults{'showlogo'}{$item} = 1;
1428: }
1429: foreach my $item (@bgs) {
1430: $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};
1.6 raeburn 1431: }
1.41 raeburn 1432: foreach my $item (@logintext) {
1.168 raeburn 1433: $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item};
1.41 raeburn 1434: }
1.168 raeburn 1435: foreach my $item (@links) {
1436: $defaults{'links'}{$item} = $defaultdesign{'login.'.$item};
1.6 raeburn 1437: }
1.168 raeburn 1438: if (ref($settings) eq 'HASH') {
1439: foreach my $item (@toggles) {
1440: if ($settings->{$item} eq '1') {
1441: $checkedon{$item} = ' checked="checked" ';
1442: $checkedoff{$item} = ' ';
1443: } elsif ($settings->{$item} eq '0') {
1444: $checkedoff{$item} = ' checked="checked" ';
1445: $checkedon{$item} = ' ';
1446: }
1447: }
1448: foreach my $item (@images) {
1449: if (defined($settings->{$item})) {
1450: $designs{$item} = $settings->{$item};
1451: $is_custom{$item} = 1;
1452: }
1453: if (defined($settings->{'showlogo'}{$item})) {
1454: $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item};
1455: }
1456: }
1.402 raeburn 1457: foreach my $item (@alttext) {
1458: if (ref($settings->{'alttext'}) eq 'HASH') {
1459: if ($settings->{'alttext'}->{$item} ne '') {
1460: $designs{'alttext'}{$item} = $settings->{'alttext'}{$item};
1461: }
1462: }
1463: }
1.168 raeburn 1464: foreach my $item (@logintext) {
1465: if ($settings->{$item} ne '') {
1466: $designs{'logintext'}{$item} = $settings->{$item};
1467: $is_custom{$item} = 1;
1468: }
1469: }
1470: if ($settings->{'font'} ne '') {
1471: $designs{'font'} = $settings->{'font'};
1472: $is_custom{'font'} = 1;
1473: }
1474: foreach my $item (@bgs) {
1475: if ($settings->{$item} ne '') {
1476: $designs{'bgs'}{$item} = $settings->{$item};
1477: $is_custom{$item} = 1;
1478: }
1479: }
1480: foreach my $item (@links) {
1481: if ($settings->{$item} ne '') {
1482: $designs{'links'}{$item} = $settings->{$item};
1483: $is_custom{$item} = 1;
1484: }
1485: }
1486: } else {
1487: if ($designhash{$dom.'.login.font'} ne '') {
1488: $designs{'font'} = $designhash{$dom.'.login.font'};
1489: $is_custom{'font'} = 1;
1490: }
1491: foreach my $item (@images) {
1492: if ($designhash{$dom.'.login.'.$item} ne '') {
1493: $designs{$item} = $designhash{$dom.'.login.'.$item};
1494: $is_custom{$item} = 1;
1495: }
1496: }
1497: foreach my $item (@bgs) {
1498: if ($designhash{$dom.'.login.'.$item} ne '') {
1499: $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item};
1500: $is_custom{$item} = 1;
1501: }
1.6 raeburn 1502: }
1.168 raeburn 1503: foreach my $item (@links) {
1504: if ($designhash{$dom.'.login.'.$item} ne '') {
1505: $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item};
1506: $is_custom{$item} = 1;
1507: }
1.6 raeburn 1508: }
1509: }
1.168 raeburn 1510: my %alt_text = &Apache::lonlocal::texthash ( img => 'Log-in banner',
1511: logo => 'Institution Logo',
1512: domlogo => 'Domain Logo',
1513: login => 'Login box');
1514: my $itemcount = 1;
1515: foreach my $item (@toggles) {
1516: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1517: $datatable .=
1518: '<tr'.$css_class.'><td colspan="2">'.$choices{$item}.
1519: '</td><td>'.
1520: '<span class="LC_nobreak"><label><input type="radio" name="'.
1521: $item.'"'.$checkedon{$item}.' value="1" />'.&mt('Yes').
1522: '</label> <label><input type="radio" name="'.$item.'"'.
1523: $checkedoff{$item}.' value="0" />'.&mt('No').'</label></span></td>'.
1524: '</tr>';
1525: $itemcount ++;
1.6 raeburn 1526: }
1.168 raeburn 1527: $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext);
1528: $datatable .= '</tr></table></td></tr>';
1529: } elsif ($caller eq 'help') {
1.386 raeburn 1530: my ($defaulturl,$defaulttype,%url,%type,%langchoices);
1.168 raeburn 1531: my $itemcount = 1;
1532: $defaulturl = '/adm/loginproblems.html';
1533: $defaulttype = 'default';
1534: %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());
1535: my @currlangs;
1536: if (ref($settings) eq 'HASH') {
1537: if (ref($settings->{'helpurl'}) eq 'HASH') {
1538: foreach my $key (sort(keys(%{$settings->{'helpurl'}}))) {
1539: next if ($settings->{'helpurl'}{$key} eq '');
1540: $url{$key} = $settings->{'helpurl'}{$key}.'?inhibitmenu=yes';
1541: $type{$key} = 'custom';
1542: unless ($key eq 'nolang') {
1543: push(@currlangs,$key);
1544: }
1545: }
1546: } elsif ($settings->{'helpurl'} ne '') {
1547: $type{'nolang'} = 'custom';
1548: $url{'nolang'} = $settings->{'helpurl'}.'?inhibitmenu=yes';
1.8 raeburn 1549: }
1550: }
1.168 raeburn 1551: foreach my $lang ('nolang',sort(@currlangs)) {
1552: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
1553: $datatable .= '<tr'.$css_class.'>';
1554: if ($url{$lang} eq '') {
1555: $url{$lang} = $defaulturl;
1556: }
1557: if ($type{$lang} eq '') {
1558: $type{$lang} = $defaulttype;
1559: }
1560: $datatable .= '<td colspan="2"><span class="LC_nobreak">';
1561: if ($lang eq 'nolang') {
1562: $datatable .= &mt('Log-in help page if no specific language file: [_1]',
1563: &Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500));
1564: } else {
1565: $datatable .= &mt('Log-in help page for language: [_1] is [_2]',
1566: $langchoices{$lang},
1567: &Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500));
1568: }
1569: $datatable .= '</span></td>'."\n".
1570: '<td class="LC_left_item">';
1571: if ($type{$lang} eq 'custom') {
1572: $datatable .= '<span class="LC_nobreak"><label>'.
1573: '<input type="checkbox" name="loginhelpurl_del" value="'.$lang.'" />'.
1574: $lt{'del'}.'</label> '.$lt{'rep'}.'</span>';
1575: } else {
1576: $datatable .= $lt{'upl'};
1577: }
1578: $datatable .='<br />';
1579: if ($switchserver) {
1580: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
1581: } else {
1582: $datatable .= '<input type="file" name="loginhelpurl_'.$lang.'" />';
1.6 raeburn 1583: }
1.168 raeburn 1584: $datatable .= '</td></tr>';
1585: $itemcount ++;
1.6 raeburn 1586: }
1.168 raeburn 1587: my @addlangs;
1588: foreach my $lang (sort(keys(%langchoices))) {
1589: next if ((grep(/^\Q$lang\E$/,@currlangs)) || ($lang eq 'x_chef'));
1590: push(@addlangs,$lang);
1591: }
1592: if (@addlangs > 0) {
1593: my %toadd;
1594: map { $toadd{$_} = $langchoices{$_} ; } @addlangs;
1595: $toadd{''} = &mt('Select');
1596: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
1597: $datatable .= '<tr'.$css_class.'><td class="LC_left_item" colspan="2">'.
1598: &mt('Add log-in help page for a specific language:').' '.
1599: &Apache::loncommon::select_form('','loginhelpurl_add_lang',\%toadd).
1600: '</td><td class="LC_left_item">'.$lt{'upl'}.'<br />';
1601: if ($switchserver) {
1602: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
1603: } else {
1604: $datatable .= '<input type="file" name="loginhelpurl_add_file" />';
1.6 raeburn 1605: }
1.168 raeburn 1606: $datatable .= '</td></tr>';
1.169 raeburn 1607: $itemcount ++;
1.6 raeburn 1608: }
1.169 raeburn 1609: $datatable .= &captcha_choice('login',$settings,$itemcount);
1.256 raeburn 1610: } elsif ($caller eq 'headtag') {
1611: my %domservers = &Apache::lonnet::get_servers($dom);
1612: my $choice = $choices{'headtag'};
1613: $css_class = ' class="LC_odd_row"';
1614: $datatable .= '<tr'.$css_class.'><td colspan="2">'.$choice.'</td>'.
1.306 raeburn 1615: '<td style="text-align: left"><table><tr><th>'.$choices{'hostid'}.'</th>'.
1.256 raeburn 1616: '<th>'.$choices{'current'}.'</th>'.
1617: '<th>'.$choices{'action'}.'</th>'.
1618: '<th>'.$choices{'exempt'}.'</th></tr>'."\n";
1619: my (%currurls,%currexempt);
1620: if (ref($settings) eq 'HASH') {
1621: if (ref($settings->{'headtag'}) eq 'HASH') {
1622: foreach my $lonhost (keys(%{$settings->{'headtag'}})) {
1623: if (ref($settings->{'headtag'}{$lonhost}) eq 'HASH') {
1624: $currurls{$lonhost} = $settings->{'headtag'}{$lonhost}{'url'};
1625: $currexempt{$lonhost} = $settings->{'headtag'}{$lonhost}{'exempt'};
1626: }
1627: }
1628: }
1629: }
1630: foreach my $lonhost (sort(keys(%domservers))) {
1631: my $exempt = &check_exempt_addresses($currexempt{$lonhost});
1632: $datatable .= '<tr><td>'.$domservers{$lonhost}.'</td>';
1633: if ($currurls{$lonhost}) {
1634: $datatable .= '<td class="LC_right_item"><a href="'.
1635: "javascript:void(open('$currurls{$lonhost}?inhibitmenu=yes','Custom_HeadTag',
1636: 'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".
1637: '">'.$lt{'curr'}.'</a></td>'.
1638: '<td><span class="LC_nobreak"><label>'.
1639: '<input type="checkbox" name="loginheadtag_del" value="'.$lonhost.'" />'.
1640: $lt{'del'}.'</label> '.$lt{'rep'}.'</span>';
1641: } else {
1642: $datatable .= '<td class="LC_right_item">'.$lt{'none'}.'</td><td>'.$lt{'upl'};
1643: }
1644: $datatable .='<br />';
1645: if ($switchserver) {
1646: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
1647: } else {
1648: $datatable .= '<input type="file" name="loginheadtag_'.$lonhost.'" />';
1649: }
1.330 raeburn 1650: $datatable .= '</td><td><input type="text" name="loginheadtagexempt_'.$lonhost.'" value="'.$exempt.'" /></td></tr>';
1.256 raeburn 1651: }
1652: $datatable .= '</table></td></tr>';
1.386 raeburn 1653: } elsif ($caller eq 'saml') {
1654: my %domservers = &Apache::lonnet::get_servers($dom);
1655: $datatable .= '<tr><td colspan="3" style="text-align: left">'.
1656: '<table><tr><th>'.$choices{'hostid'}.'</th>'.
1657: '<th>'.$choices{'samllanding'}.'</th>'.
1658: '<th>'.$choices{'samloptions'}.'</th></tr>'."\n";
1.412 raeburn 1659: my (%saml,%samltext,%samlimg,%samlalt,%samlurl,%samltitle,%samlwindow,%samlnotsso,%styleon,%styleoff);
1.386 raeburn 1660: foreach my $lonhost (keys(%domservers)) {
1661: $samlurl{$lonhost} = '/adm/sso';
1662: $styleon{$lonhost} = 'display:none';
1663: $styleoff{$lonhost} = '';
1664: }
1.411 raeburn 1665: if ((ref($settings) eq 'HASH') && (ref($settings->{'saml'}) eq 'HASH')) {
1.386 raeburn 1666: foreach my $lonhost (keys(%{$settings->{'saml'}})) {
1667: if (ref($settings->{'saml'}{$lonhost}) eq 'HASH') {
1668: $saml{$lonhost} = 1;
1669: $samltext{$lonhost} = $settings->{'saml'}{$lonhost}{'text'};
1670: $samlimg{$lonhost} = $settings->{'saml'}{$lonhost}{'img'};
1671: $samlalt{$lonhost} = $settings->{'saml'}{$lonhost}{'alt'};
1672: $samlurl{$lonhost} = $settings->{'saml'}{$lonhost}{'url'};
1673: $samltitle{$lonhost} = $settings->{'saml'}{$lonhost}{'title'};
1.412 raeburn 1674: $samlwindow{$lonhost} = $settings->{'saml'}{$lonhost}{'window'};
1.386 raeburn 1675: $samlnotsso{$lonhost} = $settings->{'saml'}{$lonhost}{'notsso'};
1676: $styleon{$lonhost} = '';
1677: $styleoff{$lonhost} = 'display:none';
1678: } else {
1679: $styleon{$lonhost} = 'display:none';
1680: $styleoff{$lonhost} = '';
1681: }
1682: }
1683: }
1684: my $itemcount = 1;
1685: foreach my $lonhost (sort(keys(%domservers))) {
1686: my $samlon = ' ';
1687: my $samloff = ' checked="checked" ';
1688: if ($saml{$lonhost}) {
1689: $samlon = $samloff;
1690: $samloff = ' ';
1691: }
1.412 raeburn 1692: my $samlwinon = '';
1693: my $samlwinoff = ' checked="checked"';
1694: if ($samlwindow{$lonhost}) {
1695: $samlwinon = $samlwinoff;
1696: $samlwinoff = '';
1697: }
1.386 raeburn 1698: my $css_class = $itemcount%2?' class="LC_odd_row"':'';
1699: $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.$domservers{$lonhost}.'</span></td>'.
1700: '<td><span class="LC_nobreak"><label><input type="radio" name="saml_'.$lonhost.'"'.$samloff.
1701: 'onclick="toggleSamlOptions(this.form,'."'$lonhost'".');" value="0" />'.
1702: &mt('No').'</label>'.(' 'x2).
1703: '<label><input type="radio" name="saml_'.$lonhost.'"'.$samlon.
1704: 'onclick="toggleSamlOptions(this.form,'."'$lonhost'".');" value="1" />'.
1705: &mt('Yes').'</label></span></td>'.
1706: '<td id="samloptionson_'.$lonhost.'" style="'.$styleon{$lonhost}.'" width="100%">'.
1.412 raeburn 1707: '<table width="100%"><tr><th colspan="3" align="center">'.&mt('SSO').'</th></tr>'.
1.386 raeburn 1708: '<tr><th>'.&mt('Text').'</th><th>'.&mt('Image').'</th>'.
1.412 raeburn 1709: '<th>'.&mt('Alt Text').'</th></tr>'.
1710: '<tr'.$css_class.'><td><input type="text" name="saml_text_'.$lonhost.'" size="20" value="'.
1.386 raeburn 1711: $samltext{$lonhost}.'" /></td><td>';
1712: if ($samlimg{$lonhost}) {
1713: $datatable .= '<img src="'.$samlimg{$lonhost}.'" /><br />'.
1714: '<span class="LC_nobreak"><label>'.
1715: '<input type="checkbox" name="saml_img_del" value="'.$lonhost.'" />'.
1716: $lt{'del'}.'</label> '.$lt{'rep'}.'</span>';
1717: } else {
1718: $datatable .= $lt{'upl'};
1719: }
1720: $datatable .='<br />';
1721: if ($switchserver) {
1722: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
1723: } else {
1724: $datatable .= '<input type="file" name="saml_img_'.$lonhost.'" />';
1725: }
1726: $datatable .= '</td>'.
1.412 raeburn 1727: '<td><input type="text" name="saml_alt_'.$lonhost.'" size="25" '.
1728: 'value="'.$samlalt{$lonhost}.'" /></td></tr></table><br />'.
1729: '<table width="100%"><tr><th colspan="3" align="center">'.&mt('SSO').'</th><th align="center">'.
1730: '<span class="LC_nobreak">'.&mt('Non-SSO').'</span></th></tr>'.
1731: '<tr><th>'.&mt('URL').'</th><th>'.&mt('Tool Tip').'</th>'.
1732: '<th>'.&mt('Pop-up if iframe').'</th><th>'.&mt('Text').'</th></tr>'.
1733: '<tr'.$css_class.'>'.
1734: '<td><input type="text" name="saml_url_'.$lonhost.'" size="30" '.
1.386 raeburn 1735: 'value="'.$samlurl{$lonhost}.'" /></td>'.
1.412 raeburn 1736: '<td><textarea name="saml_title_'.$lonhost.'" rows="3" cols="20">'.
1.386 raeburn 1737: $samltitle{$lonhost}.'</textarea></td>'.
1.412 raeburn 1738: '<td><label><input type="radio" name="saml_window_'.$lonhost.'" value=""'.$samlwinoff.'>'.
1739: &mt('No').'</label>'.(' 'x2).'<label><input type="radio" '.
1740: 'name="saml_window_'.$lonhost.'" value="1"'.$samlwinon.'>'.&mt('Yes').'</label></td>'.
1741: '<td><input type="text" name="saml_notsso_'.$lonhost.'" size="12" '.
1.386 raeburn 1742: 'value="'.$samlnotsso{$lonhost}.'" /></td></tr>'.
1743: '</table></td>'.
1744: '<td id="samloptionsoff_'.$lonhost.'" style="'.$styleoff{$lonhost}.'" width="100%"> </td></tr>';
1745: $itemcount ++;
1746: }
1747: $datatable .= '</table></td></tr>';
1.1 raeburn 1748: }
1.6 raeburn 1749: return $datatable;
1750: }
1751:
1752: sub login_choices {
1753: my %choices =
1754: &Apache::lonlocal::texthash (
1.116 bisitz 1755: coursecatalog => 'Display Course/Community Catalog link?',
1.110 raeburn 1756: adminmail => "Display Administrator's E-mail Address?",
1.188 raeburn 1757: helpdesk => 'Display "Contact Helpdesk" link',
1.110 raeburn 1758: disallowlogin => "Login page requests redirected",
1759: hostid => "Server",
1.128 raeburn 1760: server => "Redirect to:",
1761: serverpath => "Path",
1762: custompath => "Custom",
1763: exempt => "Exempt IP(s)",
1.110 raeburn 1764: directlogin => "No redirect",
1765: newuser => "Link to create a user account",
1766: img => "Header",
1767: logo => "Main Logo",
1768: domlogo => "Domain Logo",
1769: login => "Log-in Header",
1770: textcol => "Text color",
1771: bgcol => "Box color",
1772: bgs => "Background colors",
1773: links => "Link colors",
1774: font => "Font color",
1775: pgbg => "Header",
1776: mainbg => "Page",
1777: sidebg => "Login box",
1778: link => "Link",
1779: alink => "Active link",
1780: vlink => "Visited link",
1.256 raeburn 1781: headtag => "Custom markup",
1782: action => "Action",
1783: current => "Current",
1.386 raeburn 1784: samllanding => "Dual login?",
1785: samloptions => "Options",
1.402 raeburn 1786: alttext => "Alt text",
1.6 raeburn 1787: );
1788: return %choices;
1789: }
1790:
1.386 raeburn 1791: sub login_file_options {
1792: return &Apache::lonlocal::texthash(
1793: del => 'Delete?',
1794: rep => 'Replace:',
1795: upl => 'Upload:',
1796: curr => 'View contents',
1797: default => 'Default',
1798: custom => 'Custom',
1799: none => 'None',
1800: );
1801: }
1802:
1.394 raeburn 1803: sub print_ipaccess {
1804: my ($dom,$settings,$rowtotal) = @_;
1805: my $css_class;
1806: my $itemcount = 0;
1807: my $datatable;
1808: my %ordered;
1809: if (ref($settings) eq 'HASH') {
1810: foreach my $item (keys(%{$settings})) {
1811: if (ref($settings->{$item}) eq 'HASH') {
1812: my $num = $settings->{$item}{'order'};
1813: if ($num eq '') {
1814: $num = scalar(keys(%{$settings}));
1815: }
1816: $ordered{$num} = $item;
1817: }
1818: }
1819: }
1820: my $maxnum = scalar(keys(%ordered));
1821: if (keys(%ordered)) {
1822: my @items = sort { $a <=> $b } keys(%ordered);
1823: for (my $i=0; $i<@items; $i++) {
1824: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1825: my $item = $ordered{$items[$i]};
1826: my ($name,$ipranges,%commblocks,%courses);
1827: if (ref($settings->{$item}) eq 'HASH') {
1828: $name = $settings->{$item}->{'name'};
1829: $ipranges = $settings->{$item}->{'ip'};
1830: if (ref($settings->{$item}->{'commblocks'}) eq 'HASH') {
1831: %commblocks = %{$settings->{$item}->{'commblocks'}};
1832: }
1833: if (ref($settings->{$item}->{'courses'}) eq 'HASH') {
1834: %courses = %{$settings->{$item}->{'courses'}};
1835: }
1836: }
1837: my $chgstr = ' onchange="javascript:reorderIPaccess(this.form,'."'ipaccess_pos_".$item."'".');"';
1838: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
1839: .'<select name="ipaccess_pos_'.$item.'"'.$chgstr.'>';
1840: for (my $k=0; $k<=$maxnum; $k++) {
1841: my $vpos = $k+1;
1842: my $selstr;
1843: if ($k == $i) {
1844: $selstr = ' selected="selected" ';
1845: }
1846: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
1847: }
1848: $datatable .= '</select>'.(' 'x2).
1849: '<label><input type="checkbox" name="ipaccess_del" value="'.$item.'" />'.
1850: &mt('Delete?').'</label></span></td>'.
1851: '<td colspan="2"><input type="hidden" name="ipaccess_id_'.$i.'" value="'.$item.'" />'.
1852: &ipaccess_options($i,$itemcount,$dom,$name,$ipranges,\%commblocks,\%courses).
1853: '</td></tr>';
1854: $itemcount ++;
1855: }
1856: }
1857: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1858: my $chgstr = ' onchange="javascript:reorderIPaccess(this.form,'."'ipaccess_pos_add'".');"';
1859: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
1860: '<input type="hidden" name="ipaccess_maxnum" value="'.$maxnum.'" />'."\n".
1861: '<select name="ipaccess_pos_add"'.$chgstr.'>';
1862: for (my $k=0; $k<$maxnum+1; $k++) {
1863: my $vpos = $k+1;
1864: my $selstr;
1865: if ($k == $maxnum) {
1866: $selstr = ' selected="selected" ';
1867: }
1868: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
1869: }
1870: $datatable .= '</select> '."\n".
1871: '<input type="checkbox" name="ipaccess_add" value="1" />'.&mt('Add').'</span></td>'."\n".
1872: '<td colspan="2">'.
1873: &ipaccess_options('add',$itemcount,$dom).
1874: '</td>'."\n".
1875: '</tr>'."\n";
1876: $$rowtotal ++;
1877: return $datatable;
1878: }
1879:
1880: sub ipaccess_options {
1881: my ($num,$itemcount,$dom,$name,$ipranges,$blocksref,$coursesref) = @_;
1882: my (%currblocks,%currcourses,$output);
1883: if (ref($blocksref) eq 'HASH') {
1884: %currblocks = %{$blocksref};
1885: }
1886: if (ref($coursesref) eq 'HASH') {
1887: %currcourses = %{$coursesref};
1888: }
1889: $output = '<fieldset><legend>'.&mt('Location(s)').'</legend>'.
1890: '<span class="LC_nobreak">'.&mt('Name').': '.
1891: '<input type="text" name="ipaccess_name_'.$num.'" value="'.$name.'" />'.
1892: '</span></fieldset>'.
1893: '<fieldset><legend>'.&mt('IP Range(s)').'</legend>'.
1894: &mt('Format for each IP range').': '.&mt('A.B.C.D/N or A.B.C.D-E.F.G.H').'<br />'.
1895: &mt('Range(s) will be stored as IP netblock(s) in CIDR notation (comma separated)').'<br />'.
1896: '<textarea name="ipaccess_range_'.$num.'" rows="3" cols="80">'.
1897: $ipranges.'</textarea></fieldset>'.
1898: '<fieldset><legend>'.&mt('Functionality Blocked?').'</legend>'.
1899: &blocker_checkboxes($num,$blocksref).'</fieldset>'.
1900: '<fieldset><legend>'.&mt('Courses/Communities allowed').'</legend>'.
1901: '<table>';
1902: foreach my $cid (sort(keys(%currcourses))) {
1903: my %courseinfo = &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
1904: $output .= '<tr><td><span class="LC_nobreak">'.
1905: '<label><input type="checkbox" name="ipaccess_course_delete_'.$num.'" value="'.$cid.'" />'.
1906: &mt('Delete?').' <span class="LC_cusr_emph">'.$courseinfo{'description'}.'</span></label></span>'.
1907: ' <span class="LC_fontsize_medium">('.$cid.')</span></td></tr>';
1908: }
1909: $output .= '<tr><td><span class="LC_nobreak">'.&mt('Add').': '.
1910: '<input type="text" name="ipaccess_cdesc_'.$num.'" value="" onfocus="this.blur();opencrsbrowser('."'display','ipaccess_cnum_$num','ipaccess_cdom_$num','ipaccess_cdesc_$num'".');" />'.
1911: &Apache::loncommon::selectcourse_link('display','ipaccess_cnum_'.$num,'ipaccess_cdom_'.$num,'ipaccess_cdesc_'.$num,$dom,undef,'Course/Community').
1912: '<input type="hidden" name="ipaccess_cnum_'.$num.'" value="" />'.
1913: '<input type="hidden" name="ipaccess_cdom_'.$num.'" value="" />'.
1914: '</span></td></tr></table>'."\n".
1915: '</fieldset>';
1916: return $output;
1917: }
1918:
1919: sub blocker_checkboxes {
1920: my ($num,$blocks) = @_;
1921: my ($typeorder,$types) = &commblocktype_text();
1922: my $numinrow = 6;
1923: my $output = '<table>';
1924: for (my $i=0; $i<@{$typeorder}; $i++) {
1925: my $block = $typeorder->[$i];
1926: my $blockstatus;
1927: if (ref($blocks) eq 'HASH') {
1928: if ($blocks->{$block} eq 'on') {
1929: $blockstatus = 'checked="checked"';
1930: }
1931: }
1932: my $rem = $i%($numinrow);
1933: if ($rem == 0) {
1934: if ($i > 0) {
1935: $output .= '</tr>';
1936: }
1937: $output .= '<tr>';
1938: }
1939: if ($i == scalar(@{$typeorder})-1) {
1940: my $colsleft = $numinrow-$rem;
1941: if ($colsleft > 1) {
1942: $output .= '<td colspan="'.$colsleft.'">';
1943: } else {
1944: $output .= '<td>';
1945: }
1946: } else {
1947: $output .= '<td>';
1948: }
1949: my $item = 'ipaccess_block_'.$num;
1950: if ($blockstatus) {
1951: $blockstatus = ' '.$blockstatus;
1952: }
1953: $output .= '<span class="LC_nobreak"><label>'."\n".
1954: '<input type="checkbox" name="'.$item.'"'.
1955: $blockstatus.' value="'.$block.'"'.' />'.
1956: $types->{$block}.'</label></span>'."\n".
1957: '<br /></td>';
1958: }
1959: $output .= '</tr></table>';
1960: return $output;
1961: }
1962:
1963: sub commblocktype_text {
1964: my %types = &Apache::lonlocal::texthash(
1965: 'com' => 'Messaging',
1966: 'chat' => 'Chat Room',
1967: 'boards' => 'Discussion',
1968: 'port' => 'Portfolio',
1969: 'groups' => 'Groups',
1970: 'blogs' => 'Blogs',
1971: 'about' => 'User Information',
1972: 'printout' => 'Printouts',
1973: 'passwd' => 'Change Password',
1974: 'grades' => 'Gradebook',
1.397 raeburn 1975: 'search' => 'Course search',
1976: 'wishlist' => 'Stored links',
1977: 'annotate' => 'Annotations',
1.394 raeburn 1978: );
1.397 raeburn 1979: my $typeorder = ['com','chat','boards','port','groups','blogs','about','wishlist','printout','grades','search','annotate','passwd'];
1.394 raeburn 1980: return ($typeorder,\%types);
1981: }
1982:
1.6 raeburn 1983: sub print_rolecolors {
1.30 raeburn 1984: my ($phase,$role,$dom,$confname,$settings,$rowtotal) = @_;
1.6 raeburn 1985: my %choices = &color_font_choices();
1986: my @bgs = ('pgbg','tabbg','sidebg');
1987: my @links = ('link','alink','vlink');
1988: my @images = ('img');
1989: my %alt_text = &Apache::lonlocal::texthash(img => "Banner for $role role");
1.7 albertel 1990: my %designhash = &Apache::loncommon::get_domainconf($dom);
1.6 raeburn 1991: my %defaultdesign = %Apache::loncommon::defaultdesign;
1992: my (%is_custom,%designs);
1.200 raeburn 1993: my %defaults = &role_defaults($role,\@bgs,\@links,\@images);
1.6 raeburn 1994: if (ref($settings) eq 'HASH') {
1995: if (ref($settings->{$role}) eq 'HASH') {
1996: if ($settings->{$role}->{'img'} ne '') {
1997: $designs{'img'} = $settings->{$role}->{'img'};
1998: $is_custom{'img'} = 1;
1999: }
2000: if ($settings->{$role}->{'font'} ne '') {
2001: $designs{'font'} = $settings->{$role}->{'font'};
2002: $is_custom{'font'} = 1;
2003: }
1.97 tempelho 2004: if ($settings->{$role}->{'fontmenu'} ne '') {
2005: $designs{'fontmenu'} = $settings->{$role}->{'fontmenu'};
2006: $is_custom{'fontmenu'} = 1;
2007: }
1.6 raeburn 2008: foreach my $item (@bgs) {
2009: if ($settings->{$role}->{$item} ne '') {
2010: $designs{'bgs'}{$item} = $settings->{$role}->{$item};
2011: $is_custom{$item} = 1;
2012: }
2013: }
2014: foreach my $item (@links) {
2015: if ($settings->{$role}->{$item} ne '') {
2016: $designs{'links'}{$item} = $settings->{$role}->{$item};
2017: $is_custom{$item} = 1;
2018: }
2019: }
2020: }
2021: } else {
2022: if ($designhash{$dom.'.'.$role.'.img'} ne '') {
2023: $designs{img} = $designhash{$dom.'.'.$role.'.img'};
2024: $is_custom{'img'} = 1;
2025: }
1.97 tempelho 2026: if ($designhash{$dom.'.'.$role.'.fontmenu'} ne '') {
2027: $designs{fontmenu} = $designhash{$dom.'.'.$role.'.fontmenu'};
2028: $is_custom{'fontmenu'} = 1;
2029: }
1.6 raeburn 2030: if ($designhash{$dom.'.'.$role.'.font'} ne '') {
2031: $designs{font} = $designhash{$dom.'.'.$role.'.font'};
2032: $is_custom{'font'} = 1;
2033: }
2034: foreach my $item (@bgs) {
2035: if ($designhash{$dom.'.'.$role.'.'.$item} ne '') {
2036: $designs{'bgs'}{$item} = $designhash{$dom.'.'.$role.'.'.$item};
2037: $is_custom{$item} = 1;
2038:
2039: }
2040: }
2041: foreach my $item (@links) {
2042: if ($designhash{$dom.'.'.$role.'.'.$item} ne '') {
2043: $designs{'links'}{$item} = $designhash{$dom.'.'.$role.'.'.$item};
2044: $is_custom{$item} = 1;
2045: }
2046: }
2047: }
2048: my $itemcount = 1;
1.30 raeburn 2049: my $datatable = &display_color_options($dom,$confname,$phase,$role,$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal);
1.6 raeburn 2050: $datatable .= '</tr></table></td></tr>';
2051: return $datatable;
2052: }
2053:
1.200 raeburn 2054: sub role_defaults {
2055: my ($role,$bgs,$links,$images,$logintext) = @_;
1.202 raeburn 2056: my %defaults;
2057: unless ((ref($bgs) eq 'ARRAY') && (ref($links) eq 'ARRAY') && (ref($images) eq 'ARRAY')) {
1.200 raeburn 2058: return %defaults;
2059: }
2060: my %defaultdesign = %Apache::loncommon::defaultdesign;
2061: if ($role eq 'login') {
2062: %defaults = (
2063: font => $defaultdesign{$role.'.font'},
2064: );
2065: if (ref($logintext) eq 'ARRAY') {
2066: foreach my $item (@{$logintext}) {
2067: $defaults{'logintext'}{$item} = $defaultdesign{$role.'.'.$item};
2068: }
2069: }
2070: foreach my $item (@{$images}) {
2071: $defaults{'showlogo'}{$item} = 1;
2072: }
2073: } else {
2074: %defaults = (
2075: img => $defaultdesign{$role.'.img'},
2076: font => $defaultdesign{$role.'.font'},
2077: fontmenu => $defaultdesign{$role.'.fontmenu'},
2078: );
2079: }
2080: foreach my $item (@{$bgs}) {
2081: $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};
2082: }
2083: foreach my $item (@{$links}) {
2084: $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};
2085: }
2086: foreach my $item (@{$images}) {
2087: $defaults{$item} = $defaultdesign{$role.'.'.$item};
2088: }
2089: return %defaults;
2090: }
2091:
1.6 raeburn 2092: sub display_color_options {
1.9 raeburn 2093: my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,
1.135 bisitz 2094: $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_;
1.159 raeburn 2095: my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
1.6 raeburn 2096: my $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.176 raeburn 2097: my $datatable = '<tr'.$css_class.'>'.
1.6 raeburn 2098: '<td>'.$choices->{'font'}.'</td>';
2099: if (!$is_custom->{'font'}) {
1.329 raeburn 2100: $datatable .= '<td>'.&mt('Default in use:').' <span class="css_default_'.$role.'_font" style="color: '.$defaults->{'font'}.';">'.$defaults->{'font'}.'</span></td>';
1.6 raeburn 2101: } else {
2102: $datatable .= '<td> </td>';
2103: }
1.174 foxr 2104: my $current_color = $designs->{'font'} ? $designs->{'font'} : $defaults->{'font'};
2105:
1.8 raeburn 2106: $datatable .= '<td><span class="LC_nobreak">'.
1.174 foxr 2107: '<input type="text" class="colorchooser" size="10" name="'.$role.'_font"'.
1.202 raeburn 2108: ' value="'.$current_color.'" /> '.
1.329 raeburn 2109: ' </span></td></tr>';
1.107 raeburn 2110: unless ($role eq 'login') {
2111: $datatable .= '<tr'.$css_class.'>'.
2112: '<td>'.$choices->{'fontmenu'}.'</td>';
2113: if (!$is_custom->{'fontmenu'}) {
1.329 raeburn 2114: $datatable .= '<td>'.&mt('Default in use:').' <span class="css_default_'.$role.'_font" style="color: '.$defaults->{'fontmenu'}.';">'.$defaults->{'fontmenu'}.'</span></td>';
1.107 raeburn 2115: } else {
2116: $datatable .= '<td> </td>';
2117: }
1.202 raeburn 2118: $current_color = $designs->{'fontmenu'} ?
1.174 foxr 2119: $designs->{'fontmenu'} : $defaults->{'fontmenu'};
1.107 raeburn 2120: $datatable .= '<td><span class="LC_nobreak">'.
1.174 foxr 2121: '<input class="colorchooser" type="text" size="10" name="'
2122: .$role.'_fontmenu"'.
2123: ' value="'.$current_color.'" /> '.
1.329 raeburn 2124: ' </span></td></tr>';
1.97 tempelho 2125: }
1.9 raeburn 2126: my $switchserver = &check_switchserver($dom,$confname);
1.6 raeburn 2127: foreach my $img (@{$images}) {
1.18 albertel 2128: $itemcount ++;
1.6 raeburn 2129: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.8 raeburn 2130: $datatable .= '<tr'.$css_class.'>'.
1.70 raeburn 2131: '<td>'.$choices->{$img};
1.402 raeburn 2132: my ($imgfile,$img_import,$login_hdr_pick,$logincolors,$alttext);
1.70 raeburn 2133: if ($role eq 'login') {
2134: if ($img eq 'login') {
2135: $login_hdr_pick =
1.135 bisitz 2136: &login_header_options($img,$role,$defaults,$is_custom,$choices);
1.70 raeburn 2137: $logincolors =
2138: &login_text_colors($img,$role,$logintext,$phase,$choices,
1.201 raeburn 2139: $designs,$defaults);
1.402 raeburn 2140: } else {
2141: if ($img ne 'domlogo') {
2142: $datatable.= &logo_display_options($img,$defaults,$designs);
2143: }
2144: if (ref($designs->{'alttext'}) eq 'HASH') {
2145: $alttext = $designs->{'alttext'}{$img};
2146: }
1.70 raeburn 2147: }
2148: }
2149: $datatable .= '</td>';
1.6 raeburn 2150: if ($designs->{$img} ne '') {
2151: $imgfile = $designs->{$img};
1.18 albertel 2152: $img_import = ($imgfile =~ m{^/adm/});
1.6 raeburn 2153: } else {
2154: $imgfile = $defaults->{$img};
2155: }
2156: if ($imgfile) {
1.9 raeburn 2157: my ($showfile,$fullsize);
2158: if ($imgfile =~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) {
1.6 raeburn 2159: my $urldir = $1;
2160: my $filename = $2;
2161: my @info = &Apache::lonnet::stat_file($designs->{$img});
2162: if (@info) {
2163: my $thumbfile = 'tn-'.$filename;
2164: my @thumb=&Apache::lonnet::stat_file($urldir.'/'.$thumbfile);
2165: if (@thumb) {
2166: $showfile = $urldir.'/'.$thumbfile;
2167: } else {
2168: $showfile = $imgfile;
2169: }
2170: } else {
2171: $showfile = '';
2172: }
2173: } elsif ($imgfile =~ m-^/(adm/[^/]+)/([^/]+)$-) {
1.16 raeburn 2174: $showfile = $imgfile;
1.6 raeburn 2175: my $imgdir = $1;
2176: my $filename = $2;
1.159 raeburn 2177: if (-e "$londocroot/$imgdir/tn-".$filename) {
1.6 raeburn 2178: $showfile = "/$imgdir/tn-".$filename;
2179: } else {
1.159 raeburn 2180: my $input = $londocroot.$imgfile;
2181: my $output = "$londocroot/$imgdir/tn-".$filename;
1.6 raeburn 2182: if (!-e $output) {
1.9 raeburn 2183: my ($width,$height) = &thumb_dimensions();
1.16 raeburn 2184: my ($fullwidth,$fullheight) = &check_dimensions($input);
2185: if ($fullwidth ne '' && $fullheight ne '') {
2186: if ($fullwidth > $width && $fullheight > $height) {
2187: my $size = $width.'x'.$height;
1.316 raeburn 2188: my @args = ('convert','-sample',$size,$input,$output);
2189: system({$args[0]} @args);
1.159 raeburn 2190: $showfile = "/$imgdir/tn-".$filename;
1.16 raeburn 2191: }
2192: }
1.6 raeburn 2193: }
2194: }
1.16 raeburn 2195: }
1.6 raeburn 2196: if ($showfile) {
1.40 raeburn 2197: if ($showfile =~ m{^/(adm|res)/}) {
2198: if ($showfile =~ m{^/res/}) {
2199: my $local_showfile =
2200: &Apache::lonnet::filelocation('',$showfile);
2201: &Apache::lonnet::repcopy($local_showfile);
2202: }
2203: $showfile = &Apache::loncommon::lonhttpdurl($showfile);
2204: }
2205: if ($imgfile) {
2206: if ($imgfile =~ m{^/(adm|res)/}) {
2207: if ($imgfile =~ m{^/res/}) {
2208: my $local_imgfile =
2209: &Apache::lonnet::filelocation('',$imgfile);
2210: &Apache::lonnet::repcopy($local_imgfile);
2211: }
2212: $fullsize = &Apache::loncommon::lonhttpdurl($imgfile);
2213: } else {
2214: $fullsize = $imgfile;
2215: }
2216: }
1.41 raeburn 2217: $datatable .= '<td>';
2218: if ($img eq 'login') {
1.135 bisitz 2219: $datatable .= $login_hdr_pick;
2220: }
1.41 raeburn 2221: $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import,
2222: $showfile,$fullsize,$role,$img,$imgfile,$logincolors);
1.6 raeburn 2223: } else {
1.201 raeburn 2224: $datatable .= '<td> </td><td class="LC_left_item">'.
2225: &mt('Upload:').'<br />';
1.6 raeburn 2226: }
2227: } else {
1.201 raeburn 2228: $datatable .= '<td> </td><td class="LC_left_item">'.
2229: &mt('Upload:').'<br />';
1.6 raeburn 2230: }
1.9 raeburn 2231: if ($switchserver) {
2232: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
2233: } else {
1.135 bisitz 2234: if ($img ne 'login') { # suppress file selection for Log-in header
2235: $datatable .=' <input type="file" name="'.$role.'_'.$img.'" />';
2236: }
1.9 raeburn 2237: }
1.402 raeburn 2238: if (($role eq 'login') && ($img ne 'login')) {
2239: $datatable .= (' ' x2).' <span class="LC_nobreak"><label>'.$choices->{'alttext'}.':'.
2240: '<input type="text" name="'.$role.'_alt_'.$img.'" size="10" value="'.$alttext.'" />'.
2241: '</label></span>';
2242: }
1.9 raeburn 2243: $datatable .= '</td></tr>';
1.6 raeburn 2244: }
2245: $itemcount ++;
2246: $css_class = $itemcount%2?' class="LC_odd_row"':'';
2247: $datatable .= '<tr'.$css_class.'>'.
2248: '<td>'.$choices->{'bgs'}.'</td>';
2249: my $bgs_def;
2250: foreach my $item (@{$bgs}) {
2251: if (!$is_custom->{$item}) {
1.329 raeburn 2252: $bgs_def .= '<td><span class="LC_nobreak">'.$choices->{$item}.'</span> <span class="css_default_'.$role.'_'.$item.'" style="background-color: '.$defaults->{'bgs'}{$item}.';"> </span><br />'.$defaults->{'bgs'}{$item}.'</td>';
1.6 raeburn 2253: }
2254: }
2255: if ($bgs_def) {
1.8 raeburn 2256: $datatable .= '<td>'.&mt('Default(s) in use:').'<br /><table border="0"><tr>'.$bgs_def.'</tr></table></td>';
1.6 raeburn 2257: } else {
2258: $datatable .= '<td> </td>';
2259: }
2260: $datatable .= '<td class="LC_right_item">'.
2261: '<table border="0"><tr>';
1.174 foxr 2262:
1.6 raeburn 2263: foreach my $item (@{$bgs}) {
1.306 raeburn 2264: $datatable .= '<td style="text-align: center">'.$choices->{$item};
1.174 foxr 2265: my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};
1.6 raeburn 2266: if ($designs->{'bgs'}{$item}) {
1.174 foxr 2267: $datatable .= ' ';
1.6 raeburn 2268: }
1.174 foxr 2269: $datatable .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
1.41 raeburn 2270: '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
1.6 raeburn 2271: }
2272: $datatable .= '</tr></table></td></tr>';
2273: $itemcount ++;
2274: $css_class = $itemcount%2?' class="LC_odd_row"':'';
2275: $datatable .= '<tr'.$css_class.'>'.
2276: '<td>'.$choices->{'links'}.'</td>';
2277: my $links_def;
2278: foreach my $item (@{$links}) {
2279: if (!$is_custom->{$item}) {
1.329 raeburn 2280: $links_def .= '<td>'.$choices->{$item}.'<br /><span class="css_default_'.$role.'_'.$item.'" style="color: '.$defaults->{'links'}{$item}.';">'.$defaults->{'links'}{$item}.'</span></td>';
1.6 raeburn 2281: }
2282: }
2283: if ($links_def) {
1.8 raeburn 2284: $datatable .= '<td>'.&mt('Default(s) in use:').'<br /><table border="0"><tr>'.$links_def.'</tr></table></td>';
1.6 raeburn 2285: } else {
2286: $datatable .= '<td> </td>';
2287: }
2288: $datatable .= '<td class="LC_right_item">'.
2289: '<table border="0"><tr>';
2290: foreach my $item (@{$links}) {
1.234 raeburn 2291: my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item};
1.306 raeburn 2292: $datatable .= '<td style="text-align: center">'.$choices->{$item}."\n";
1.6 raeburn 2293: if ($designs->{'links'}{$item}) {
1.174 foxr 2294: $datatable.=' ';
1.6 raeburn 2295: }
1.174 foxr 2296: $datatable .= '<br /><input type="text" size="8" class="colorchooser" name="'.$role.'_'.$item.'" value="'.$color.
1.6 raeburn 2297: '" /></td>';
2298: }
1.30 raeburn 2299: $$rowtotal += $itemcount;
1.3 raeburn 2300: return $datatable;
2301: }
2302:
1.70 raeburn 2303: sub logo_display_options {
2304: my ($img,$defaults,$designs) = @_;
2305: my $checkedon;
2306: if (ref($defaults) eq 'HASH') {
2307: if (ref($defaults->{'showlogo'}) eq 'HASH') {
2308: if ($defaults->{'showlogo'}{$img}) {
2309: $checkedon = 'checked="checked" ';
2310: }
2311: }
2312: }
2313: if (ref($designs) eq 'HASH') {
2314: if (ref($designs->{'showlogo'}) eq 'HASH') {
2315: if (defined($designs->{'showlogo'}{$img})) {
2316: if ($designs->{'showlogo'}{$img} == 0) {
2317: $checkedon = '';
2318: } elsif ($designs->{'showlogo'}{$img} == 1) {
2319: $checkedon = 'checked="checked" ';
2320: }
2321: }
2322: }
2323: }
2324: return '<br /><label> <input type="checkbox" name="'.
2325: 'login_showlogo_'.$img.'" value="1" '.$checkedon.'/>'.
2326: &mt('show').'</label>'."\n";
2327: }
2328:
1.41 raeburn 2329: sub login_header_options {
1.135 bisitz 2330: my ($img,$role,$defaults,$is_custom,$choices) = @_;
2331: my $output = '';
1.41 raeburn 2332: if ((!$is_custom->{'textcol'}) || (!$is_custom->{'bgcol'})) {
1.135 bisitz 2333: $output .= &mt('Text default(s):').'<br />';
1.41 raeburn 2334: if (!$is_custom->{'textcol'}) {
2335: $output .= $choices->{'textcol'}.': '.$defaults->{'logintext'}{'textcol'}.
2336: ' ';
2337: }
2338: if (!$is_custom->{'bgcol'}) {
2339: $output .= $choices->{'bgcol'}.': '.
2340: '<span id="css_'.$role.'_font" style="background-color: '.
2341: $defaults->{'logintext'}{'bgcol'}.';"> </span>';
2342: }
2343: $output .= '<br />';
2344: }
2345: $output .='<br />';
2346: return $output;
2347: }
2348:
2349: sub login_text_colors {
1.201 raeburn 2350: my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;
1.41 raeburn 2351: my $color_menu = '<table border="0"><tr>';
2352: foreach my $item (@{$logintext}) {
1.306 raeburn 2353: $color_menu .= '<td style="text-align: center">'.$choices->{$item};
1.201 raeburn 2354: my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};
2355: $color_menu .= '<br /><input type="text" class="colorchooser" size="8" name="'.$role.'_'.$item.'" value="'.$color.
2356: '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" /></td>';
1.41 raeburn 2357: }
2358: $color_menu .= '</tr></table><br />';
2359: return $color_menu;
2360: }
2361:
2362: sub image_changes {
2363: my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_;
2364: my $output;
1.135 bisitz 2365: if ($img eq 'login') {
1.331 raeburn 2366: $output = '</td><td>'.$logincolors; # suppress image for Log-in header
1.135 bisitz 2367: } elsif (!$is_custom) {
1.70 raeburn 2368: if ($img ne 'domlogo') {
1.331 raeburn 2369: $output = &mt('Default image:').'<br />';
1.41 raeburn 2370: } else {
1.331 raeburn 2371: $output = &mt('Default in use:').'<br />';
1.41 raeburn 2372: }
2373: }
1.331 raeburn 2374: if ($img ne 'login') {
1.135 bisitz 2375: if ($img_import) {
2376: $output .= '<input type="hidden" name="'.$role.'_import_'.$img.'" value="'.$imgfile.'" />';
2377: }
2378: $output .= '<a href="'.$fullsize.'" target="_blank"><img src="'.
2379: $showfile.'" alt="'.$alt_text.'" border="0" /></a></td>';
2380: if ($is_custom) {
2381: $output .= '<td>'.$logincolors.'<span class="LC_nobreak"><label>'.
2382: '<input type="checkbox" name="'.
2383: $role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
2384: '</label> '.&mt('Replace:').'</span><br />';
2385: } else {
1.306 raeburn 2386: $output .= '<td class="LC_middle">'.$logincolors.&mt('Upload:').'<br />';
1.135 bisitz 2387: }
1.41 raeburn 2388: }
2389: return $output;
2390: }
2391:
1.3 raeburn 2392: sub print_quotas {
1.86 raeburn 2393: my ($dom,$settings,$rowtotal,$action) = @_;
2394: my $context;
2395: if ($action eq 'quotas') {
2396: $context = 'tools';
2397: } else {
2398: $context = $action;
2399: }
1.197 raeburn 2400: my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations);
1.44 raeburn 2401: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.3 raeburn 2402: my $typecount = 0;
1.101 raeburn 2403: my ($css_class,%titles);
1.86 raeburn 2404: if ($context eq 'requestcourses') {
1.325 raeburn 2405: @usertools = ('official','unofficial','community','textbook','placement','lti');
1.106 raeburn 2406: @options =('norequest','approval','validate','autolimit');
1.101 raeburn 2407: %validations = &Apache::lonnet::auto_courserequest_checks($dom);
2408: %titles = &courserequest_titles();
1.163 raeburn 2409: } elsif ($context eq 'requestauthor') {
2410: @usertools = ('author');
2411: @options = ('norequest','approval','automatic');
1.210 raeburn 2412: %titles = &authorrequest_titles();
1.86 raeburn 2413: } else {
1.413 raeburn 2414: @usertools = ('aboutme','blog','webdav','portfolio','timezone');
1.101 raeburn 2415: %titles = &tool_titles();
1.86 raeburn 2416: }
1.26 raeburn 2417: if (ref($types) eq 'ARRAY') {
1.23 raeburn 2418: foreach my $type (@{$types}) {
1.197 raeburn 2419: my ($currdefquota,$currauthorquota);
1.163 raeburn 2420: unless (($context eq 'requestcourses') ||
2421: ($context eq 'requestauthor')) {
1.86 raeburn 2422: if (ref($settings) eq 'HASH') {
2423: if (ref($settings->{defaultquota}) eq 'HASH') {
1.197 raeburn 2424: $currdefquota = $settings->{defaultquota}->{$type};
1.86 raeburn 2425: } else {
2426: $currdefquota = $settings->{$type};
2427: }
1.197 raeburn 2428: if (ref($settings->{authorquota}) eq 'HASH') {
2429: $currauthorquota = $settings->{authorquota}->{$type};
2430: }
1.78 raeburn 2431: }
1.72 raeburn 2432: }
1.3 raeburn 2433: if (defined($usertypes->{$type})) {
2434: $typecount ++;
2435: $css_class = $typecount%2?' class="LC_odd_row"':'';
1.72 raeburn 2436: $datatable .= '<tr'.$css_class.'>'.
1.3 raeburn 2437: '<td>'.$usertypes->{$type}.'</td>'.
1.72 raeburn 2438: '<td class="LC_left_item">';
1.101 raeburn 2439: if ($context eq 'requestcourses') {
2440: $datatable .= '<table><tr>';
2441: }
2442: my %cell;
1.72 raeburn 2443: foreach my $item (@usertools) {
1.101 raeburn 2444: if ($context eq 'requestcourses') {
2445: my ($curroption,$currlimit);
2446: if (ref($settings) eq 'HASH') {
2447: if (ref($settings->{$item}) eq 'HASH') {
2448: $curroption = $settings->{$item}->{$type};
2449: if ($curroption =~ /^autolimit=(\d*)$/) {
2450: $currlimit = $1;
2451: }
2452: }
2453: }
2454: if (!$curroption) {
2455: $curroption = 'norequest';
2456: }
2457: $datatable .= '<th>'.$titles{$item}.'</th>';
2458: foreach my $option (@options) {
2459: my $val = $option;
2460: if ($option eq 'norequest') {
2461: $val = 0;
2462: }
2463: if ($option eq 'validate') {
2464: my $canvalidate = 0;
2465: if (ref($validations{$item}) eq 'HASH') {
2466: if ($validations{$item}{$type}) {
2467: $canvalidate = 1;
2468: }
2469: }
2470: next if (!$canvalidate);
2471: }
2472: my $checked = '';
2473: if ($option eq $curroption) {
2474: $checked = ' checked="checked"';
2475: } elsif ($option eq 'autolimit') {
2476: if ($curroption =~ /^autolimit/) {
2477: $checked = ' checked="checked"';
2478: }
2479: }
2480: $cell{$item} .= '<span class="LC_nobreak"><label>'.
2481: '<input type="radio" name="crsreq_'.$item.
2482: '_'.$type.'" value="'.$val.'"'.$checked.' />'.
1.127 raeburn 2483: $titles{$option}.'</label>';
1.101 raeburn 2484: if ($option eq 'autolimit') {
1.127 raeburn 2485: $cell{$item} .= ' <input type="text" name="crsreq_'.
1.101 raeburn 2486: $item.'_limit_'.$type.'" size="1" '.
1.103 raeburn 2487: 'value="'.$currlimit.'" />';
1.101 raeburn 2488: }
1.127 raeburn 2489: $cell{$item} .= '</span> ';
1.103 raeburn 2490: if ($option eq 'autolimit') {
1.127 raeburn 2491: $cell{$item} .= $titles{'unlimited'};
1.103 raeburn 2492: }
1.101 raeburn 2493: }
1.163 raeburn 2494: } elsif ($context eq 'requestauthor') {
2495: my $curroption;
2496: if (ref($settings) eq 'HASH') {
2497: $curroption = $settings->{$type};
2498: }
2499: if (!$curroption) {
2500: $curroption = 'norequest';
2501: }
2502: foreach my $option (@options) {
2503: my $val = $option;
2504: if ($option eq 'norequest') {
2505: $val = 0;
2506: }
2507: my $checked = '';
2508: if ($option eq $curroption) {
2509: $checked = ' checked="checked"';
2510: }
2511: $datatable .= '<span class="LC_nobreak"><label>'.
2512: '<input type="radio" name="authorreq_'.$type.
2513: '" value="'.$val.'"'.$checked.' />'.
2514: $titles{$option}.'</label></span> ';
2515: }
1.101 raeburn 2516: } else {
2517: my $checked = 'checked="checked" ';
1.413 raeburn 2518: if ($item eq 'timezone') {
2519: $checked = '';
2520: }
1.101 raeburn 2521: if (ref($settings) eq 'HASH') {
2522: if (ref($settings->{$item}) eq 'HASH') {
1.413 raeburn 2523: if (!$settings->{$item}->{$type}) {
1.101 raeburn 2524: $checked = '';
2525: } elsif ($settings->{$item}->{$type} == 1) {
2526: $checked = 'checked="checked" ';
2527: }
1.78 raeburn 2528: }
1.72 raeburn 2529: }
1.101 raeburn 2530: $datatable .= '<span class="LC_nobreak"><label>'.
2531: '<input type="checkbox" name="'.$context.'_'.$item.
2532: '" value="'.$type.'" '.$checked.'/>'.$titles{$item}.
2533: '</label></span> ';
1.72 raeburn 2534: }
1.101 raeburn 2535: }
2536: if ($context eq 'requestcourses') {
2537: $datatable .= '</tr><tr>';
2538: foreach my $item (@usertools) {
1.106 raeburn 2539: $datatable .= '<td style="vertical-align: top">'.$cell{$item}.'</td>';
1.101 raeburn 2540: }
2541: $datatable .= '</tr></table>';
1.72 raeburn 2542: }
1.86 raeburn 2543: $datatable .= '</td>';
1.163 raeburn 2544: unless (($context eq 'requestcourses') ||
2545: ($context eq 'requestauthor')) {
1.86 raeburn 2546: $datatable .=
1.197 raeburn 2547: '<td class="LC_right_item">'.
2548: '<span class="LC_nobreak">'.&mt('Portfolio').': '.
1.3 raeburn 2549: '<input type="text" name="quota_'.$type.
1.72 raeburn 2550: '" value="'.$currdefquota.
1.197 raeburn 2551: '" size="5" /></span>'.(' ' x 2).
2552: '<span class="LC_nobreak">'.&mt('Authoring').': '.
2553: '<input type="text" name="authorquota_'.$type.
2554: '" value="'.$currauthorquota.
2555: '" size="5" /></span></td>';
1.86 raeburn 2556: }
2557: $datatable .= '</tr>';
1.3 raeburn 2558: }
2559: }
2560: }
1.163 raeburn 2561: unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
1.86 raeburn 2562: $defaultquota = '20';
1.197 raeburn 2563: $authorquota = '500';
1.86 raeburn 2564: if (ref($settings) eq 'HASH') {
2565: if (ref($settings->{'defaultquota'}) eq 'HASH') {
2566: $defaultquota = $settings->{'defaultquota'}->{'default'};
2567: } elsif (defined($settings->{'default'})) {
2568: $defaultquota = $settings->{'default'};
2569: }
1.197 raeburn 2570: if (ref($settings->{'authorquota'}) eq 'HASH') {
2571: $authorquota = $settings->{'authorquota'}->{'default'};
2572: }
1.3 raeburn 2573: }
2574: }
2575: $typecount ++;
2576: $css_class = $typecount%2?' class="LC_odd_row"':'';
2577: $datatable .= '<tr'.$css_class.'>'.
1.26 raeburn 2578: '<td>'.$othertitle.'</td>'.
1.72 raeburn 2579: '<td class="LC_left_item">';
1.101 raeburn 2580: if ($context eq 'requestcourses') {
2581: $datatable .= '<table><tr>';
2582: }
2583: my %defcell;
1.72 raeburn 2584: foreach my $item (@usertools) {
1.101 raeburn 2585: if ($context eq 'requestcourses') {
2586: my ($curroption,$currlimit);
2587: if (ref($settings) eq 'HASH') {
2588: if (ref($settings->{$item}) eq 'HASH') {
2589: $curroption = $settings->{$item}->{'default'};
2590: if ($curroption =~ /^autolimit=(\d*)$/) {
2591: $currlimit = $1;
2592: }
2593: }
2594: }
2595: if (!$curroption) {
2596: $curroption = 'norequest';
2597: }
2598: $datatable .= '<th>'.$titles{$item}.'</th>';
2599: foreach my $option (@options) {
2600: my $val = $option;
2601: if ($option eq 'norequest') {
2602: $val = 0;
2603: }
2604: if ($option eq 'validate') {
2605: my $canvalidate = 0;
2606: if (ref($validations{$item}) eq 'HASH') {
2607: if ($validations{$item}{'default'}) {
2608: $canvalidate = 1;
2609: }
2610: }
2611: next if (!$canvalidate);
2612: }
2613: my $checked = '';
2614: if ($option eq $curroption) {
2615: $checked = ' checked="checked"';
2616: } elsif ($option eq 'autolimit') {
2617: if ($curroption =~ /^autolimit/) {
2618: $checked = ' checked="checked"';
2619: }
2620: }
2621: $defcell{$item} .= '<span class="LC_nobreak"><label>'.
2622: '<input type="radio" name="crsreq_'.$item.
2623: '_default" value="'.$val.'"'.$checked.' />'.
2624: $titles{$option}.'</label>';
2625: if ($option eq 'autolimit') {
1.127 raeburn 2626: $defcell{$item} .= ' <input type="text" name="crsreq_'.
1.101 raeburn 2627: $item.'_limit_default" size="1" '.
2628: 'value="'.$currlimit.'" />';
2629: }
1.127 raeburn 2630: $defcell{$item} .= '</span> ';
1.104 raeburn 2631: if ($option eq 'autolimit') {
1.127 raeburn 2632: $defcell{$item} .= $titles{'unlimited'};
1.104 raeburn 2633: }
1.101 raeburn 2634: }
1.163 raeburn 2635: } elsif ($context eq 'requestauthor') {
2636: my $curroption;
2637: if (ref($settings) eq 'HASH') {
1.172 raeburn 2638: $curroption = $settings->{'default'};
1.163 raeburn 2639: }
2640: if (!$curroption) {
2641: $curroption = 'norequest';
2642: }
2643: foreach my $option (@options) {
2644: my $val = $option;
2645: if ($option eq 'norequest') {
2646: $val = 0;
2647: }
2648: my $checked = '';
2649: if ($option eq $curroption) {
2650: $checked = ' checked="checked"';
2651: }
2652: $datatable .= '<span class="LC_nobreak"><label>'.
2653: '<input type="radio" name="authorreq_default"'.
2654: ' value="'.$val.'"'.$checked.' />'.
2655: $titles{$option}.'</label></span> ';
2656: }
1.101 raeburn 2657: } else {
2658: my $checked = 'checked="checked" ';
2659: if (ref($settings) eq 'HASH') {
2660: if (ref($settings->{$item}) eq 'HASH') {
2661: if ($settings->{$item}->{'default'} == 0) {
2662: $checked = '';
2663: } elsif ($settings->{$item}->{'default'} == 1) {
2664: $checked = 'checked="checked" ';
2665: }
1.78 raeburn 2666: }
1.72 raeburn 2667: }
1.101 raeburn 2668: $datatable .= '<span class="LC_nobreak"><label>'.
2669: '<input type="checkbox" name="'.$context.'_'.$item.
2670: '" value="default" '.$checked.'/>'.$titles{$item}.
2671: '</label></span> ';
2672: }
2673: }
2674: if ($context eq 'requestcourses') {
2675: $datatable .= '</tr><tr>';
2676: foreach my $item (@usertools) {
1.106 raeburn 2677: $datatable .= '<td style="vertical-align: top">'.$defcell{$item}.'</td>';
1.72 raeburn 2678: }
1.101 raeburn 2679: $datatable .= '</tr></table>';
1.72 raeburn 2680: }
1.86 raeburn 2681: $datatable .= '</td>';
1.163 raeburn 2682: unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
1.197 raeburn 2683: $datatable .= '<td class="LC_right_item">'.
2684: '<span class="LC_nobreak">'.&mt('Portfolio').': '.
1.86 raeburn 2685: '<input type="text" name="defaultquota" value="'.
1.197 raeburn 2686: $defaultquota.'" size="5" /></span>'.(' ' x2).
2687: '<span class="LC_nobreak">'.&mt('Authoring').': '.
2688: '<input type="text" name="authorquota" value="'.
2689: $authorquota.'" size="5" /></span></td>';
1.86 raeburn 2690: }
2691: $datatable .= '</tr>';
1.72 raeburn 2692: $typecount ++;
2693: $css_class = $typecount%2?' class="LC_odd_row"':'';
2694: $datatable .= '<tr'.$css_class.'>'.
1.197 raeburn 2695: '<td>'.&mt('LON-CAPA Advanced Users').'<br />';
1.104 raeburn 2696: if ($context eq 'requestcourses') {
1.109 raeburn 2697: $datatable .= &mt('(overrides affiliation, if set)').
2698: '</td>'.
2699: '<td class="LC_left_item">'.
2700: '<table><tr>';
1.101 raeburn 2701: } else {
1.109 raeburn 2702: $datatable .= &mt('(overrides affiliation, if checked)').
2703: '</td>'.
2704: '<td class="LC_left_item" colspan="2">'.
2705: '<br />';
1.101 raeburn 2706: }
2707: my %advcell;
1.72 raeburn 2708: foreach my $item (@usertools) {
1.101 raeburn 2709: if ($context eq 'requestcourses') {
2710: my ($curroption,$currlimit);
2711: if (ref($settings) eq 'HASH') {
2712: if (ref($settings->{$item}) eq 'HASH') {
2713: $curroption = $settings->{$item}->{'_LC_adv'};
2714: if ($curroption =~ /^autolimit=(\d*)$/) {
2715: $currlimit = $1;
2716: }
2717: }
2718: }
2719: $datatable .= '<th>'.$titles{$item}.'</th>';
1.104 raeburn 2720: my $checked = '';
2721: if ($curroption eq '') {
2722: $checked = ' checked="checked"';
2723: }
2724: $advcell{$item} .= '<span class="LC_nobreak"><label>'.
2725: '<input type="radio" name="crsreq_'.$item.
2726: '__LC_adv" value=""'.$checked.' />'.
2727: &mt('No override set').'</label></span> ';
1.101 raeburn 2728: foreach my $option (@options) {
2729: my $val = $option;
2730: if ($option eq 'norequest') {
2731: $val = 0;
2732: }
2733: if ($option eq 'validate') {
2734: my $canvalidate = 0;
2735: if (ref($validations{$item}) eq 'HASH') {
2736: if ($validations{$item}{'_LC_adv'}) {
2737: $canvalidate = 1;
2738: }
2739: }
2740: next if (!$canvalidate);
2741: }
2742: my $checked = '';
1.104 raeburn 2743: if ($val eq $curroption) {
1.101 raeburn 2744: $checked = ' checked="checked"';
2745: } elsif ($option eq 'autolimit') {
2746: if ($curroption =~ /^autolimit/) {
2747: $checked = ' checked="checked"';
2748: }
2749: }
2750: $advcell{$item} .= '<span class="LC_nobreak"><label>'.
2751: '<input type="radio" name="crsreq_'.$item.
2752: '__LC_adv" value="'.$val.'"'.$checked.' />'.
2753: $titles{$option}.'</label>';
2754: if ($option eq 'autolimit') {
1.127 raeburn 2755: $advcell{$item} .= ' <input type="text" name="crsreq_'.
1.101 raeburn 2756: $item.'_limit__LC_adv" size="1" '.
2757: 'value="'.$currlimit.'" />';
2758: }
1.127 raeburn 2759: $advcell{$item} .= '</span> ';
1.104 raeburn 2760: if ($option eq 'autolimit') {
1.127 raeburn 2761: $advcell{$item} .= $titles{'unlimited'};
1.104 raeburn 2762: }
1.101 raeburn 2763: }
1.163 raeburn 2764: } elsif ($context eq 'requestauthor') {
2765: my $curroption;
2766: if (ref($settings) eq 'HASH') {
2767: $curroption = $settings->{'_LC_adv'};
2768: }
2769: my $checked = '';
2770: if ($curroption eq '') {
2771: $checked = ' checked="checked"';
2772: }
2773: $datatable .= '<span class="LC_nobreak"><label>'.
2774: '<input type="radio" name="authorreq__LC_adv"'.
2775: ' value=""'.$checked.' />'.
2776: &mt('No override set').'</label></span> ';
2777: foreach my $option (@options) {
2778: my $val = $option;
2779: if ($option eq 'norequest') {
2780: $val = 0;
2781: }
2782: my $checked = '';
2783: if ($val eq $curroption) {
2784: $checked = ' checked="checked"';
2785: }
2786: $datatable .= '<span class="LC_nobreak"><label>'.
1.173 raeburn 2787: '<input type="radio" name="authorreq__LC_adv"'.
2788: ' value="'.$val.'"'.$checked.' />'.
1.163 raeburn 2789: $titles{$option}.'</label></span> ';
2790: }
1.101 raeburn 2791: } else {
2792: my $checked = 'checked="checked" ';
2793: if (ref($settings) eq 'HASH') {
2794: if (ref($settings->{$item}) eq 'HASH') {
2795: if ($settings->{$item}->{'_LC_adv'} == 0) {
2796: $checked = '';
2797: } elsif ($settings->{$item}->{'_LC_adv'} == 1) {
2798: $checked = 'checked="checked" ';
2799: }
1.79 raeburn 2800: }
1.72 raeburn 2801: }
1.101 raeburn 2802: $datatable .= '<span class="LC_nobreak"><label>'.
2803: '<input type="checkbox" name="'.$context.'_'.$item.
2804: '" value="_LC_adv" '.$checked.'/>'.$titles{$item}.
2805: '</label></span> ';
2806: }
2807: }
2808: if ($context eq 'requestcourses') {
2809: $datatable .= '</tr><tr>';
2810: foreach my $item (@usertools) {
1.106 raeburn 2811: $datatable .= '<td style="vertical-align: top">'.$advcell{$item}.'</td>';
1.72 raeburn 2812: }
1.101 raeburn 2813: $datatable .= '</tr></table>';
1.72 raeburn 2814: }
1.98 raeburn 2815: $datatable .= '</td></tr>';
1.30 raeburn 2816: $$rowtotal += $typecount;
1.3 raeburn 2817: return $datatable;
2818: }
2819:
1.163 raeburn 2820: sub print_requestmail {
1.305 raeburn 2821: my ($dom,$action,$settings,$rowtotal,$customcss,$rowstyle) = @_;
1.208 raeburn 2822: my ($now,$datatable,%currapp);
1.102 raeburn 2823: $now = time;
2824: if (ref($settings) eq 'HASH') {
2825: if (ref($settings->{'notify'}) eq 'HASH') {
2826: if ($settings->{'notify'}{'approval'} ne '') {
1.224 raeburn 2827: map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'});
1.102 raeburn 2828: }
2829: }
2830: }
1.191 raeburn 2831: my $numinrow = 2;
1.224 raeburn 2832: my $css_class;
1.305 raeburn 2833: if ($$rowtotal%2) {
2834: $css_class = 'LC_odd_row';
2835: }
2836: if ($customcss) {
2837: $css_class .= " $customcss";
2838: }
2839: $css_class =~ s/^\s+//;
2840: if ($css_class) {
2841: $css_class = ' class="'.$css_class.'"';
2842: }
2843: if ($rowstyle) {
2844: $css_class .= ' style="'.$rowstyle.'"';
2845: }
1.163 raeburn 2846: my $text;
2847: if ($action eq 'requestcourses') {
2848: $text = &mt('Receive notification of course requests requiring approval');
1.224 raeburn 2849: } elsif ($action eq 'requestauthor') {
2850: $text = &mt('Receive notification of Authoring Space requests requiring approval');
1.163 raeburn 2851: } else {
1.224 raeburn 2852: $text = &mt('Receive notification of queued requests for self-created user accounts requiring approval');
1.163 raeburn 2853: }
1.224 raeburn 2854: $datatable = '<tr'.$css_class.'>'.
1.163 raeburn 2855: ' <td>'.$text.'</td>'.
1.102 raeburn 2856: ' <td class="LC_left_item">';
1.191 raeburn 2857: my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',
1.224 raeburn 2858: $action.'notifyapproval',%currapp);
1.191 raeburn 2859: if ($numdc > 0) {
2860: $datatable .= $table;
1.102 raeburn 2861: } else {
2862: $datatable .= &mt('There are no active Domain Coordinators');
2863: }
2864: $datatable .='</td></tr>';
2865: return $datatable;
2866: }
2867:
1.216 raeburn 2868: sub print_studentcode {
2869: my ($settings,$rowtotal) = @_;
2870: my $rownum = 0;
1.218 raeburn 2871: my ($output,%current);
1.325 raeburn 2872: my @crstypes = ('official','unofficial','community','textbook','placement','lti');
1.248 raeburn 2873: if (ref($settings) eq 'HASH') {
2874: if (ref($settings->{'uniquecode'}) eq 'HASH') {
2875: foreach my $type (@crstypes) {
2876: $current{$type} = $settings->{'uniquecode'}{$type};
2877: }
1.218 raeburn 2878: }
2879: }
2880: $output .= '<tr>'.
2881: '<td class="LC_left_item">'.&mt('Generate unique six character code as course identifier?').'</td>'.
2882: '<td class="LC_left_item">';
2883: foreach my $type (@crstypes) {
2884: my $check = ' ';
2885: if ($current{$type}) {
2886: $check = ' checked="checked" ';
2887: }
2888: $output .= '<span class="LC_nobreak"><label>'.
2889: '<input type="checkbox" name="uniquecode" value="'.$type.'"'.$check.'/>'.
2890: &mt($type).'</label></span>'.(' 'x2).' ';
2891: }
2892: $output .= '</td></tr>';
2893: $$rowtotal ++;
2894: return $output;
1.216 raeburn 2895: }
2896:
2897: sub print_textbookcourses {
1.242 raeburn 2898: my ($dom,$type,$settings,$rowtotal) = @_;
1.216 raeburn 2899: my $rownum = 0;
2900: my $css_class;
2901: my $itemcount = 1;
2902: my $maxnum = 0;
2903: my $bookshash;
2904: if (ref($settings) eq 'HASH') {
1.242 raeburn 2905: $bookshash = $settings->{$type};
1.216 raeburn 2906: }
2907: my %ordered;
2908: if (ref($bookshash) eq 'HASH') {
2909: foreach my $item (keys(%{$bookshash})) {
2910: if (ref($bookshash->{$item}) eq 'HASH') {
2911: my $num = $bookshash->{$item}{'order'};
2912: $ordered{$num} = $item;
2913: }
2914: }
2915: }
2916: my $confname = $dom.'-domainconfig';
2917: my $switchserver = &check_switchserver($dom,$confname);
1.242 raeburn 2918: my $maxnum = scalar(keys(%ordered));
2919: my $datatable;
1.216 raeburn 2920: if (keys(%ordered)) {
2921: my @items = sort { $a <=> $b } keys(%ordered);
2922: for (my $i=0; $i<@items; $i++) {
2923: $css_class = $itemcount%2?' class="LC_odd_row"':'';
2924: my $key = $ordered{$items[$i]};
2925: my %coursehash=&Apache::lonnet::coursedescription($key);
2926: my $coursetitle = $coursehash{'description'};
1.243 raeburn 2927: my ($subject,$title,$author,$publisher,$image,$imgsrc,$cdom,$cnum);
1.216 raeburn 2928: if (ref($bookshash->{$key}) eq 'HASH') {
2929: $subject = $bookshash->{$key}->{'subject'};
2930: $title = $bookshash->{$key}->{'title'};
1.242 raeburn 2931: if ($type eq 'textbooks') {
1.243 raeburn 2932: $publisher = $bookshash->{$key}->{'publisher'};
1.242 raeburn 2933: $author = $bookshash->{$key}->{'author'};
2934: $image = $bookshash->{$key}->{'image'};
2935: if ($image ne '') {
2936: my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$});
2937: my $imagethumb = "$path/tn-".$imagefile;
2938: $imgsrc = '<img src="'.$imagethumb.'" alt="'.&mt('Textbook image').'" />';
2939: }
1.216 raeburn 2940: }
2941: }
1.242 raeburn 2942: my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type".'_'."$key','$type'".');"';
1.216 raeburn 2943: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
1.242 raeburn 2944: .'<select name="'.$type.'_'.$key.'"'.$chgstr.'>';
1.216 raeburn 2945: for (my $k=0; $k<=$maxnum; $k++) {
2946: my $vpos = $k+1;
2947: my $selstr;
2948: if ($k == $i) {
2949: $selstr = ' selected="selected" ';
2950: }
2951: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
2952: }
2953: $datatable .= '</select>'.(' 'x2).
1.242 raeburn 2954: '<label><input type="checkbox" name="'.$type.'_del" value="'.$key.'" />'.
1.216 raeburn 2955: &mt('Delete?').'</label></span></td>'.
2956: '<td colspan="2">'.
1.242 raeburn 2957: '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_subject_'.$i.'" value="'.$subject.'" /></span> '.
1.216 raeburn 2958: (' 'x2).
1.242 raeburn 2959: '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_title_'.$i.'" value="'.$title.'" /></span> ';
2960: if ($type eq 'textbooks') {
2961: $datatable .= (' 'x2).
1.243 raeburn 2962: '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_publisher_'.$i.'" value="'.$publisher.'" /></span> '.
2963: (' 'x2).
1.242 raeburn 2964: '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_author_'.$i.'" value="'.$author.'" /></span> '.
2965: (' 'x2).
2966: '<span class="LC_nobreak">'.&mt('Thumbnail:');
2967: if ($image) {
1.267 raeburn 2968: $datatable .= $imgsrc.
1.242 raeburn 2969: '<label><input type="checkbox" name="'.$type.'_image_del"'.
2970: ' value="'.$key.'" />'.&mt('Delete?').'</label></span> '.
2971: '<span class="LC_nobreak"> '.&mt('Replace:').' ';
2972: }
2973: if ($switchserver) {
2974: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
2975: } else {
2976: $datatable .= '<input type="file" name="'.$type.'_image_'.$i.'" value="" />';
2977: }
1.216 raeburn 2978: }
1.242 raeburn 2979: $datatable .= '<input type="hidden" name="'.$type.'_id_'.$i.'" value="'.$type.'_'.$key.'" /></span> '.
1.216 raeburn 2980: '<span class="LC_nobreak">'.&mt('LON-CAPA course:').' '.
2981: $coursetitle.'</span></td></tr>'."\n";
2982: $itemcount ++;
2983: }
2984: }
2985: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.242 raeburn 2986: my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type"."_addbook_pos','$type'".');"';
1.216 raeburn 2987: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
1.242 raeburn 2988: '<input type="hidden" name="'.$type.'_maxnum" value="'.$maxnum.'" />'."\n".
2989: '<select name="'.$type.'_addbook_pos"'.$chgstr.'>';
1.216 raeburn 2990: for (my $k=0; $k<$maxnum+1; $k++) {
2991: my $vpos = $k+1;
2992: my $selstr;
2993: if ($k == $maxnum) {
2994: $selstr = ' selected="selected" ';
2995: }
2996: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
2997: }
2998: $datatable .= '</select> '."\n".
1.334 raeburn 2999: '<input type="checkbox" name="'.$type.'_addbook" value="1" />'.&mt('Add').'</span></td>'."\n".
1.216 raeburn 3000: '<td colspan="2">'.
1.242 raeburn 3001: '<span class="LC_nobreak">'.&mt('Subject:').'<input type="text" size="15" name="'.$type.'_addbook_subject" value="" /></span> '."\n".
1.216 raeburn 3002: (' 'x2).
1.242 raeburn 3003: '<span class="LC_nobreak">'.&mt('Title:').'<input type="text" size="30" name="'.$type.'_addbook_title" value="" /></span> '."\n".
3004: (' 'x2);
3005: if ($type eq 'textbooks') {
1.243 raeburn 3006: $datatable .= '<span class="LC_nobreak">'.&mt('Publisher:').'<input type="text" size="10" name="'.$type.'_addbook_publisher" value="" /></span> '."\n".
3007: (' 'x2).
3008: '<span class="LC_nobreak">'.&mt('Author(s):').'<input type="text" size="25" name="'.$type.'_addbook_author" value="" /></span> '."\n".
1.242 raeburn 3009: (' 'x2).
3010: '<span class="LC_nobreak">'.&mt('Image:').' ';
3011: if ($switchserver) {
3012: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
3013: } else {
3014: $datatable .= '<input type="file" name="'.$type.'_addbook_image" value="" />';
3015: }
1.334 raeburn 3016: $datatable .= '</span>'."\n";
1.216 raeburn 3017: }
1.334 raeburn 3018: $datatable .= '<span class="LC_nobreak">'.&mt('LON-CAPA course:').' '.
1.242 raeburn 3019: &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').
3020: '<input type="text" size="25" name="'.$type.'_addbook_cnum" value="" />'.
1.216 raeburn 3021: &Apache::loncommon::selectcourse_link
1.334 raeburn 3022: ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course').
1.216 raeburn 3023: '</span></td>'."\n".
3024: '</tr>'."\n";
3025: $itemcount ++;
3026: return $datatable;
3027: }
3028:
1.217 raeburn 3029: sub textbookcourses_javascript {
1.242 raeburn 3030: my ($settings) = @_;
3031: return unless(ref($settings) eq 'HASH');
3032: my (%ordered,%total,%jstext);
3033: foreach my $type ('textbooks','templates') {
3034: $total{$type} = 0;
3035: if (ref($settings->{$type}) eq 'HASH') {
3036: foreach my $item (keys(%{$settings->{$type}})) {
3037: if (ref($settings->{$type}->{$item}) eq 'HASH') {
3038: my $num = $settings->{$type}->{$item}{'order'};
3039: $ordered{$type}{$num} = $item;
3040: }
3041: }
3042: $total{$type} = scalar(keys(%{$settings->{$type}}));
3043: }
3044: my @jsarray = ();
3045: foreach my $item (sort {$a <=> $b } (keys(%{$ordered{$type}}))) {
3046: push(@jsarray,$ordered{$type}{$item});
3047: }
3048: $jstext{$type} = ' var '.$type.' = Array('."'".join("','",@jsarray)."'".');'."\n";
1.217 raeburn 3049: }
3050: return <<"ENDSCRIPT";
3051: <script type="text/javascript">
3052: // <![CDATA[
1.242 raeburn 3053: function reorderBooks(form,item,caller) {
1.217 raeburn 3054: var changedVal;
1.242 raeburn 3055: $jstext{'textbooks'};
3056: $jstext{'templates'};
3057: var newpos;
3058: var maxh;
3059: if (caller == 'textbooks') {
3060: newpos = 'textbooks_addbook_pos';
3061: maxh = 1 + $total{'textbooks'};
3062: } else {
3063: newpos = 'templates_addbook_pos';
3064: maxh = 1 + $total{'templates'};
3065: }
1.217 raeburn 3066: var current = new Array;
3067: var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
3068: if (item == newpos) {
3069: changedVal = newitemVal;
3070: } else {
3071: changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
3072: current[newitemVal] = newpos;
3073: }
1.242 raeburn 3074: if (caller == 'textbooks') {
3075: for (var i=0; i<textbooks.length; i++) {
3076: var elementName = 'textbooks_'+textbooks[i];
3077: if (elementName != item) {
3078: if (form.elements[elementName]) {
3079: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
3080: current[currVal] = elementName;
3081: }
3082: }
3083: }
3084: }
3085: if (caller == 'templates') {
3086: for (var i=0; i<templates.length; i++) {
3087: var elementName = 'templates_'+templates[i];
3088: if (elementName != item) {
3089: if (form.elements[elementName]) {
3090: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
3091: current[currVal] = elementName;
3092: }
1.217 raeburn 3093: }
3094: }
3095: }
3096: var oldVal;
3097: for (var j=0; j<maxh; j++) {
3098: if (current[j] == undefined) {
3099: oldVal = j;
3100: }
3101: }
3102: if (oldVal < changedVal) {
3103: for (var k=oldVal+1; k<=changedVal ; k++) {
3104: var elementName = current[k];
3105: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
3106: }
3107: } else {
3108: for (var k=changedVal; k<oldVal; k++) {
3109: var elementName = current[k];
3110: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
3111: }
3112: }
3113: return;
3114: }
3115:
3116: // ]]>
3117: </script>
3118:
3119: ENDSCRIPT
3120: }
3121:
1.267 raeburn 3122: sub ltitools_javascript {
3123: my ($settings) = @_;
1.319 raeburn 3124: my $togglejs = <itools_toggle_js();
3125: unless (ref($settings) eq 'HASH') {
3126: return $togglejs;
3127: }
1.267 raeburn 3128: my (%ordered,$total,%jstext);
3129: $total = 0;
3130: foreach my $item (keys(%{$settings})) {
3131: if (ref($settings->{$item}) eq 'HASH') {
3132: my $num = $settings->{$item}{'order'};
3133: $ordered{$num} = $item;
3134: }
3135: }
3136: $total = scalar(keys(%{$settings}));
3137: my @jsarray = ();
3138: foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
3139: push(@jsarray,$ordered{$item});
3140: }
3141: my $jstext = ' var ltitools = Array('."'".join("','",@jsarray)."'".');'."\n";
3142: return <<"ENDSCRIPT";
3143: <script type="text/javascript">
3144: // <![CDATA[
1.319 raeburn 3145: function reorderLTITools(form,item) {
1.267 raeburn 3146: var changedVal;
3147: $jstext
3148: var newpos = 'ltitools_add_pos';
3149: var maxh = 1 + $total;
3150: var current = new Array;
3151: var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
3152: if (item == newpos) {
3153: changedVal = newitemVal;
3154: } else {
3155: changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
3156: current[newitemVal] = newpos;
3157: }
3158: for (var i=0; i<ltitools.length; i++) {
3159: var elementName = 'ltitools_'+ltitools[i];
3160: if (elementName != item) {
3161: if (form.elements[elementName]) {
3162: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
3163: current[currVal] = elementName;
3164: }
3165: }
3166: }
3167: var oldVal;
3168: for (var j=0; j<maxh; j++) {
3169: if (current[j] == undefined) {
3170: oldVal = j;
3171: }
3172: }
3173: if (oldVal < changedVal) {
3174: for (var k=oldVal+1; k<=changedVal ; k++) {
3175: var elementName = current[k];
3176: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
3177: }
3178: } else {
3179: for (var k=changedVal; k<oldVal; k++) {
3180: var elementName = current[k];
3181: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
3182: }
3183: }
3184: return;
3185: }
3186:
3187: // ]]>
3188: </script>
3189:
1.319 raeburn 3190: $togglejs
3191:
3192: ENDSCRIPT
3193: }
3194:
3195: sub ltitools_toggle_js {
3196: return <<"ENDSCRIPT";
3197: <script type="text/javascript">
3198: // <![CDATA[
3199:
3200: function toggleLTITools(form,setting,item) {
3201: var radioname = '';
3202: var divid = '';
3203: if ((setting == 'passback') || (setting == 'roster')) {
3204: radioname = 'ltitools_'+setting+'_'+item;
3205: divid = 'ltitools_'+setting+'time_'+item;
3206: var num = form.elements[radioname].length;
3207: if (num) {
3208: var setvis = '';
3209: for (var i=0; i<num; i++) {
3210: if (form.elements[radioname][i].checked) {
3211: if (form.elements[radioname][i].value == '1') {
3212: if (document.getElementById(divid)) {
3213: document.getElementById(divid).style.display = 'inline-block';
3214: }
3215: setvis = 1;
3216: }
3217: break;
3218: }
3219: }
3220: }
3221: if (!setvis) {
3222: if (document.getElementById(divid)) {
3223: document.getElementById(divid).style.display = 'none';
3224: }
3225: }
3226: }
1.324 raeburn 3227: if (setting == 'user') {
3228: divid = 'ltitools_'+setting+'_div_'+item;
3229: var checkid = 'ltitools_'+setting+'_field_'+item;
3230: if (document.getElementById(divid)) {
3231: if (document.getElementById(checkid)) {
3232: if (document.getElementById(checkid).checked) {
3233: document.getElementById(divid).style.display = 'inline-block';
3234: } else {
3235: document.getElementById(divid).style.display = 'none';
3236: }
3237: }
3238: }
3239: }
1.319 raeburn 3240: return;
3241: }
3242: // ]]>
3243: </script>
3244:
1.267 raeburn 3245: ENDSCRIPT
3246: }
3247:
1.381 raeburn 3248: sub wafproxy_javascript {
3249: my ($dom) = @_;
3250: return <<"ENDSCRIPT";
3251: <script type="text/javascript">
3252: // <![CDATA[
3253: function updateWAF() {
3254: if (document.getElementById('wafproxy_remoteip')) {
3255: var wafremote = 0;
3256: if (document.display.wafproxy_remoteip.options[document.display.wafproxy_remoteip.selectedIndex].value == 'h') {
3257: wafremote = 1;
3258: }
3259: var fields = new Array('header','trust');
3260: for (var i=0; i<fields.length; i++) {
3261: if (document.getElementById('wafproxy_'+fields[i])) {
3262: if (wafremote == 1) {
3263: document.getElementById('wafproxy_'+fields[i]).style.display = 'table-row';
3264: }
3265: else {
3266: document.getElementById('wafproxy_'+fields[i]).style.display = 'none';
3267: }
3268: }
3269: }
3270: if (document.getElementById('wafproxyranges_$dom')) {
3271: if (wafremote == 1) {
3272: document.getElementById('wafproxyranges_$dom').style.display = 'inline-block';
3273: } else {
3274: for (var i=0; i<document.display.wafproxy_vpnaccess.length; i++) {
3275: if (document.display.wafproxy_vpnaccess[i].checked) {
3276: if (document.display.wafproxy_vpnaccess[i].value == 0) {
3277: document.getElementById('wafproxyranges_$dom').style.display = 'none';
3278: }
3279: }
3280: }
3281: }
3282: }
3283: }
3284: return;
3285: }
3286:
3287: function checkWAF() {
3288: if (document.getElementById('wafproxy_remoteip')) {
3289: var wafvpn = 0;
3290: for (var i=0; i<document.display.wafproxy_vpnaccess.length; i++) {
3291: if (document.display.wafproxy_vpnaccess[i].checked) {
3292: if (document.display.wafproxy_vpnaccess[i].value == 1) {
3293: wafvpn = 1;
3294: }
3295: break;
3296: }
3297: }
3298: var vpn = new Array('vpnint','vpnext');
3299: for (var i=0; i<vpn.length; i++) {
3300: if (document.getElementById('wafproxy_show_'+vpn[i])) {
3301: if (wafvpn == 1) {
3302: document.getElementById('wafproxy_show_'+vpn[i]).style.display = 'table-row';
3303: }
3304: else {
3305: document.getElementById('wafproxy_show_'+vpn[i]).style.display = 'none';
3306: }
3307: }
3308: }
3309: if (document.getElementById('wafproxyranges_$dom')) {
3310: if (wafvpn == 1) {
3311: document.getElementById('wafproxyranges_$dom').style.display = 'inline-block';
3312: }
3313: else if (document.display.wafproxy_remoteip.options[document.display.wafproxy_remoteip.selectedIndex].value != 'h') {
3314: document.getElementById('wafproxyranges_$dom').style.display = 'none';
3315: }
3316: }
3317: }
3318: return;
3319: }
3320:
3321: function toggleWAF() {
3322: if (document.getElementById('wafproxy_table')) {
3323: var wafproxy = 0;
3324: for (var i=0; i<document.display.wafproxy_${dom}.length; i++) {
3325: if (document.display.wafproxy_${dom}[i].checked) {
3326: if (document.display.wafproxy_${dom}[i].value == 1) {
3327: wafproxy = 1;
3328: break;
3329: }
3330: }
3331: }
3332: if (wafproxy == 1) {
3333: document.getElementById('wafproxy_table').style.display='inline';
3334: }
3335: else {
3336: document.getElementById('wafproxy_table').style.display='none';
3337: }
3338: if (document.getElementById('wafproxyrow_${dom}')) {
3339: if (wafproxy == 1) {
3340: document.getElementById('wafproxyrow_${dom}').style.display = 'table-row';
3341: }
3342: else {
3343: document.getElementById('wafproxyrow_${dom}').style.display = 'none';
3344: }
3345: }
3346: if (document.getElementById('nowafproxyrow_$dom')) {
3347: if (wafproxy == 1) {
3348: document.getElementById('nowafproxyrow_${dom}').style.display = 'none';
3349: }
3350: else {
3351: document.getElementById('nowafproxyrow_${dom}').style.display = 'table-row';
3352: }
3353: }
3354: }
3355: return;
3356: }
3357: // ]]>
3358: </script>
3359:
3360: ENDSCRIPT
3361: }
3362:
1.372 raeburn 3363: sub proctoring_javascript {
3364: my ($settings) = @_;
3365: my (%ordered,$total,%jstext);
3366: $total = 0;
3367: if (ref($settings) eq 'HASH') {
3368: foreach my $item (keys(%{$settings})) {
3369: if (ref($settings->{$item}) eq 'HASH') {
3370: my $num = $settings->{$item}{'order'};
3371: $ordered{$num} = $item;
3372: }
3373: }
3374: $total = scalar(keys(%{$settings}));
3375: } else {
3376: %ordered = (
3377: 0 => 'proctorio',
3378: 1 => 'examity',
3379: );
3380: $total = 2;
3381: }
3382: my @jsarray = ();
3383: foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
3384: push(@jsarray,$ordered{$item});
3385: }
3386: my $jstext = ' var proctors = Array('."'".join("','",@jsarray)."'".');'."\n";
3387: return <<"ENDSCRIPT";
3388: <script type="text/javascript">
3389: // <![CDATA[
3390: function reorderProctoring(form,item) {
3391: var changedVal;
3392: $jstext
3393: var maxh = $total;
3394: var current = new Array;
3395: var changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
3396: for (var i=0; i<proctors.length; i++) {
3397: var elementName = 'proctoring_pos_'+proctors[i];
3398: if (elementName != item) {
3399: if (form.elements[elementName]) {
3400: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
3401: current[currVal] = elementName;
3402: }
3403: }
3404: }
3405: var oldVal;
3406: for (var j=0; j<maxh; j++) {
3407: if (current[j] == undefined) {
3408: oldVal = j;
3409: }
3410: }
3411: if (oldVal < changedVal) {
3412: for (var k=oldVal+1; k<=changedVal ; k++) {
3413: var elementName = current[k];
3414: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
3415: }
3416: } else {
3417: for (var k=changedVal; k<oldVal; k++) {
3418: var elementName = current[k];
3419: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
3420: }
3421: }
3422: return;
3423: }
3424:
3425: function toggleProctoring(form,item) {
3426: var fieldsets = document.getElementsByClassName('proctoring_'+item);
3427: if (fieldsets.length) {
3428: var radioname = 'proctoring_available_'+item;
3429: var num = form.elements[radioname].length;
3430: if (num) {
3431: var setvis = '';
3432: for (var i=0; i<num; i++) {
3433: if (form.elements[radioname][i].checked) {
3434: if (form.elements[radioname][i].value == '1') {
3435: setvis = 1;
3436: break;
3437: }
3438: }
3439: }
3440: for (var j=0; j<fieldsets.length; j++) {
3441: if (setvis) {
3442: fieldsets[j].style.display = 'block';
3443: } else {
3444: fieldsets[j].style.display = 'none';
3445: }
3446: }
3447: }
3448: }
3449: return;
3450: }
3451:
3452: // ]]>
3453: </script>
3454:
3455: ENDSCRIPT
3456: }
3457:
3458:
1.320 raeburn 3459: sub lti_javascript {
1.405 raeburn 3460: my ($dom,$settings) = @_;
3461: my $togglejs = <i_toggle_js($dom);
1.419 raeburn 3462: my $linkprot_js = &Apache::courseprefs::linkprot_javascript();
1.320 raeburn 3463: unless (ref($settings) eq 'HASH') {
1.419 raeburn 3464: return $togglejs.'
3465: <script type="text/javascript">
3466: // <![CDATA[
3467:
3468: '.$linkprot_js.'
3469:
3470: // ]]>
3471: </script>
3472: ';
1.320 raeburn 3473: }
3474: my (%ordered,$total,%jstext);
1.390 raeburn 3475: $total = scalar(keys(%{$settings}));
1.320 raeburn 3476: foreach my $item (keys(%{$settings})) {
3477: if (ref($settings->{$item}) eq 'HASH') {
3478: my $num = $settings->{$item}{'order'};
1.390 raeburn 3479: if ($num eq '') {
3480: $num = $total - 1;
3481: }
1.320 raeburn 3482: $ordered{$num} = $item;
3483: }
3484: }
3485: my @jsarray = ();
3486: foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
3487: push(@jsarray,$ordered{$item});
3488: }
3489: my $jstext = ' var lti = Array('."'".join("','",@jsarray)."'".');'."\n";
3490: return <<"ENDSCRIPT";
3491: <script type="text/javascript">
3492: // <![CDATA[
3493: function reorderLTI(form,item) {
3494: var changedVal;
3495: $jstext
3496: var newpos = 'lti_pos_add';
3497: var maxh = 1 + $total;
3498: var current = new Array;
3499: var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
3500: if (item == newpos) {
3501: changedVal = newitemVal;
3502: } else {
3503: changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
3504: current[newitemVal] = newpos;
3505: }
3506: for (var i=0; i<lti.length; i++) {
3507: var elementName = 'lti_pos_'+lti[i];
3508: if (elementName != item) {
3509: if (form.elements[elementName]) {
3510: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
3511: current[currVal] = elementName;
3512: }
3513: }
3514: }
3515: var oldVal;
3516: for (var j=0; j<maxh; j++) {
3517: if (current[j] == undefined) {
3518: oldVal = j;
3519: }
3520: }
3521: if (oldVal < changedVal) {
3522: for (var k=oldVal+1; k<=changedVal ; k++) {
3523: var elementName = current[k];
3524: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
3525: }
3526: } else {
3527: for (var k=changedVal; k<oldVal; k++) {
3528: var elementName = current[k];
3529: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
3530: }
3531: }
3532: return;
3533: }
1.406 raeburn 3534:
3535: $linkprot_js
3536:
1.320 raeburn 3537: // ]]>
3538: </script>
3539:
3540: $togglejs
3541:
3542: ENDSCRIPT
3543: }
3544:
3545: sub lti_toggle_js {
1.405 raeburn 3546: my ($dom) = @_;
1.325 raeburn 3547: my %lcauthparmtext = &Apache::lonlocal::texthash (
3548: localauth => 'Local auth argument',
3549: krb => 'Kerberos domain',
3550: );
1.391 raeburn 3551: my $crsincalert = &mt('"User\'s identity sent" needs to be set to "Yes" first,[_1] before setting "Course\'s identity sent" to "Yes"',"\n");
3552: &js_escape(\$crsincalert);
1.405 raeburn 3553: my %servers = &Apache::lonnet::get_servers($dom,'library');
3554: my $primary = &Apache::lonnet::domain($dom,'primary');
3555: my $course_servers = "'".join("','",keys(%servers))."'";
1.320 raeburn 3556: return <<"ENDSCRIPT";
3557: <script type="text/javascript">
3558: // <![CDATA[
3559:
3560: function toggleLTI(form,setting,item) {
1.391 raeburn 3561: if ((setting == 'requser') || (setting == 'crsinc')) {
3562: var usrfieldsets = document.getElementsByClassName('ltioption_usr_'+item);
3563: var setvis = '';
3564: var radioname = 'lti_requser_'+item;
3565: var num = form.elements[radioname].length;
3566: if (num) {
3567: for (var i=0; i<num; i++) {
3568: if (form.elements[radioname][i].checked) {
3569: if (form.elements[radioname][i].value == '1') {
3570: setvis = 1;
3571: break;
3572: }
3573: }
3574: }
3575: }
3576: if (usrfieldsets.length) {
3577: for (var j=0; j<usrfieldsets.length; j++) {
3578: if (setvis) {
3579: usrfieldsets[j].style.display = 'block';
3580: } else {
3581: usrfieldsets[j].style.display = 'none';
3582: }
3583: }
3584: }
3585: var crsfieldsets = document.getElementsByClassName('ltioption_crs_'+item);
3586: if (crsfieldsets.length) {
3587: radioname = 'lti_crsinc_'+item;
1.345 raeburn 3588: var num = form.elements[radioname].length;
3589: if (num) {
1.391 raeburn 3590: var crsvis = '';
1.345 raeburn 3591: for (var i=0; i<num; i++) {
3592: if (form.elements[radioname][i].checked) {
3593: if (form.elements[radioname][i].value == '1') {
1.391 raeburn 3594: if (setvis == '') {
3595: if (setting == 'crsinc'){
3596: alert("$crsincalert");
3597: form.elements[radioname][0].checked = true;
3598: }
3599: } else {
3600: crsvis = 1;
3601: }
3602: break;
1.345 raeburn 3603: }
3604: }
3605: }
1.391 raeburn 3606: setvis = crsvis;
3607: }
3608: for (var j=0; j<crsfieldsets.length; j++) {
3609: if (setvis) {
3610: crsfieldsets[j].style.display = 'block';
3611: } else {
3612: crsfieldsets[j].style.display = 'none';
1.345 raeburn 3613: }
3614: }
3615: }
1.363 raeburn 3616: } else if ((setting == 'user') || (setting == 'crs') || (setting == 'passback') || (setting == 'callback')) {
1.320 raeburn 3617: var radioname = '';
3618: var divid = '';
3619: if (setting == 'user') {
3620: radioname = 'lti_mapuser_'+item;
3621: divid = 'lti_userfield_'+item;
1.343 raeburn 3622: } else if (setting == 'crs') {
1.320 raeburn 3623: radioname = 'lti_mapcrs_'+item;
3624: divid = 'lti_crsfield_'+item;
1.363 raeburn 3625: } else if (setting == 'callback') {
3626: radioname = 'lti_callback_'+item;
3627: divid = 'lti_callbackfield_'+item;
1.337 raeburn 3628: } else {
1.351 raeburn 3629: radioname = 'lti_passback_'+item;
1.337 raeburn 3630: divid = 'lti_passback_'+item;
1.320 raeburn 3631: }
3632: var num = form.elements[radioname].length;
3633: if (num) {
3634: var setvis = '';
3635: for (var i=0; i<num; i++) {
3636: if (form.elements[radioname][i].checked) {
1.363 raeburn 3637: if ((setting == 'passback') || (setting == 'callback')) {
1.337 raeburn 3638: if (form.elements[radioname][i].value == '1') {
3639: if (document.getElementById(divid)) {
3640: document.getElementById(divid).style.display = 'inline-block';
3641: }
3642: setvis = 1;
3643: break;
3644: }
3645: } else {
3646: if (form.elements[radioname][i].value == 'other') {
3647: if (document.getElementById(divid)) {
3648: document.getElementById(divid).style.display = 'inline-block';
3649: }
3650: setvis = 1;
3651: break;
1.320 raeburn 3652: }
3653: }
1.425 raeburn 3654: }
1.320 raeburn 3655: }
3656: if (!setvis) {
3657: if (document.getElementById(divid)) {
3658: document.getElementById(divid).style.display = 'none';
3659: }
3660: }
3661: }
3662: } else if ((setting == 'sec') || (setting == 'secsrc')) {
3663: var numsec = form.elements['lti_crssec_'+item].length;
3664: if (numsec) {
3665: var setvis = '';
3666: for (var i=0; i<numsec; i++) {
3667: if (form.elements['lti_crssec_'+item][i].checked) {
3668: if (form.elements['lti_crssec_'+item][i].value == '1') {
3669: if (document.getElementById('lti_crssecfield_'+item)) {
3670: document.getElementById('lti_crssecfield_'+item).style.display = 'inline-block';
3671: setvis = 1;
3672: var numsrcsec = form.elements['lti_crssecsrc_'+item].length;
3673: if (numsrcsec) {
3674: var setsrcvis = '';
3675: for (var j=0; j<numsrcsec; j++) {
3676: if (form.elements['lti_crssecsrc_'+item][j].checked) {
3677: if (form.elements['lti_crssecsrc_'+item][j].value == 'other') {
3678: if (document.getElementById('lti_secsrcfield_'+item)) {
3679: document.getElementById('lti_secsrcfield_'+item).style.display = 'inline-block';
3680: setsrcvis = 1;
3681: }
3682: }
3683: }
3684: }
3685: if (!setsrcvis) {
3686: if (document.getElementById('lti_secsrcfield_'+item)) {
3687: document.getElementById('lti_secsrcfield_'+item).style.display = 'none';
3688: }
3689: }
3690: }
3691: }
3692: }
3693: }
3694: }
3695: if (!setvis) {
3696: if (document.getElementById('lti_crssecfield_'+item)) {
3697: document.getElementById('lti_crssecfield_'+item).style.display = 'none';
3698: }
3699: if (document.getElementById('lti_secsrcfield_'+item)) {
3700: document.getElementById('lti_secsrcfield_'+item).style.display = 'none';
3701: }
3702: }
3703: }
1.325 raeburn 3704: } else if (setting == 'lcauth') {
3705: var numauth = form.elements['lti_lcauth_'+item].length;
3706: if (numauth) {
3707: for (var i=0; i<numauth; i++) {
3708: if (form.elements['lti_lcauth_'+item][i].checked) {
3709: if (document.getElementById('lti_'+setting+'_parmrow_'+item)) {
3710: if ((form.elements['lti_'+setting+'_'+item][i].value == 'internal') || (form.elements['lti_'+setting+'_'+item][i].value == 'lti')) {
3711: document.getElementById('lti_'+setting+'_parmrow_'+item).style.display = 'none';
3712: } else {
3713: document.getElementById('lti_'+setting+'_parmrow_'+item).style.display = 'table-row';
3714: if (document.getElementById('lti_'+setting+'_parmtext_'+item)) {
3715: if (form.elements['lti_'+setting+'_'+item][i].value == 'localauth') {
3716: document.getElementById('lti_'+setting+'_parmtext_'+item).innerHTML = "$lcauthparmtext{'localauth'}";
3717: } else {
3718: document.getElementById('lti_'+setting+'_parmtext_'+item).innerHTML = "$lcauthparmtext{'krb'}";
3719: }
3720: }
3721: }
3722: }
3723: }
3724: }
3725: }
1.326 raeburn 3726: } else if (setting == 'lcmenu') {
3727: var menus = new Array('lti_topmenu_'+item,'lti_inlinemenu_'+item);
3728: var divid = 'lti_menufield_'+item;
3729: var setvis = '';
3730: for (var i=0; i<menus.length; i++) {
1.425 raeburn 3731: var radioname = menus[i];
1.326 raeburn 3732: var num = form.elements[radioname].length;
3733: if (num) {
3734: for (var j=0; j<num; j++) {
3735: if (form.elements[radioname][j].checked) {
3736: if (form.elements[radioname][j].value == '1') {
3737: if (document.getElementById(divid)) {
3738: document.getElementById(divid).style.display = 'inline-block';
3739: }
3740: setvis = 1;
3741: break;
3742: }
3743: }
3744: }
3745: }
3746: if (setvis == 1) {
3747: break;
3748: }
3749: }
3750: if (!setvis) {
3751: if (document.getElementById(divid)) {
3752: document.getElementById(divid).style.display = 'none';
3753: }
3754: }
1.320 raeburn 3755: }
3756: return;
3757: }
1.405 raeburn 3758:
1.320 raeburn 3759: // ]]>
3760: </script>
3761:
3762: ENDSCRIPT
3763: }
3764:
1.385 raeburn 3765: sub autoupdate_javascript {
3766: return <<"ENDSCRIPT";
3767: <script type="text/javascript">
3768: // <![CDATA[
3769: function toggleLastActiveDays(form) {
3770: var radioname = 'lastactive';
3771: var divid = 'lastactive_div';
3772: var num = form.elements[radioname].length;
3773: if (num) {
3774: var setvis = '';
3775: for (var i=0; i<num; i++) {
3776: if (form.elements[radioname][i].checked) {
3777: if (form.elements[radioname][i].value == '1') {
3778: if (document.getElementById(divid)) {
3779: document.getElementById(divid).style.display = 'inline-block';
3780: }
3781: setvis = 1;
3782: }
3783: break;
3784: }
3785: }
3786: if (!setvis) {
3787: if (document.getElementById(divid)) {
3788: document.getElementById(divid).style.display = 'none';
3789: }
3790: }
3791: }
3792: return;
3793: }
3794: // ]]>
3795: </script>
3796:
3797: ENDSCRIPT
3798: }
3799:
1.399 raeburn 3800: sub autoenroll_javascript {
3801: return <<"ENDSCRIPT";
3802: <script type="text/javascript">
3803: // <![CDATA[
3804: function toggleFailsafe(form) {
3805: var radioname = 'autoenroll_failsafe';
3806: var divid = 'autoenroll_failsafe_div';
3807: var num = form.elements[radioname].length;
3808: if (num) {
3809: var setvis = '';
3810: for (var i=0; i<num; i++) {
3811: if (form.elements[radioname][i].checked) {
3812: if ((form.elements[radioname][i].value == 'zero') || (form.elements[radioname][i].value == 'any')) {
3813: if (document.getElementById(divid)) {
3814: document.getElementById(divid).style.display = 'inline-block';
3815: }
3816: setvis = 1;
3817: }
3818: break;
3819: }
3820: }
3821: if (!setvis) {
3822: if (document.getElementById(divid)) {
3823: document.getElementById(divid).style.display = 'none';
3824: }
3825: }
3826: }
3827: return;
3828: }
3829: // ]]>
3830: </script>
3831:
3832: ENDSCRIPT
3833: }
3834:
1.386 raeburn 3835: sub saml_javascript {
3836: return <<"ENDSCRIPT";
3837: <script type="text/javascript">
3838: // <![CDATA[
1.425 raeburn 3839: function toggleSamlOptions(form,hostid) {
1.386 raeburn 3840: var radioname = 'saml_'+hostid;
3841: var tablecellon = 'samloptionson_'+hostid;
3842: var tablecelloff = 'samloptionsoff_'+hostid;
3843: var num = form.elements[radioname].length;
3844: if (num) {
1.425 raeburn 3845: var setvis = '';
1.386 raeburn 3846: for (var i=0; i<num; i++) {
3847: if (form.elements[radioname][i].checked) {
1.425 raeburn 3848: if (form.elements[radioname][i].value == '1') {
1.386 raeburn 3849: if (document.getElementById(tablecellon)) {
3850: document.getElementById(tablecellon).style.display='';
3851: }
3852: if (document.getElementById(tablecelloff)) {
3853: document.getElementById(tablecelloff).style.display='none';
3854: }
3855: setvis = 1;
3856: }
3857: break;
3858: }
3859: }
3860: if (!setvis) {
3861: if (document.getElementById(tablecellon)) {
3862: document.getElementById(tablecellon).style.display='none';
3863: }
3864: if (document.getElementById(tablecelloff)) {
3865: document.getElementById(tablecelloff).style.display='';
3866: }
3867: }
3868: }
3869: return;
3870: }
3871: // ]]>
3872: </script>
3873:
3874: ENDSCRIPT
3875: }
3876:
1.394 raeburn 3877: sub ipaccess_javascript {
3878: my ($settings) = @_;
3879: my (%ordered,$total,%jstext);
3880: $total = 0;
3881: if (ref($settings) eq 'HASH') {
3882: foreach my $item (keys(%{$settings})) {
3883: if (ref($settings->{$item}) eq 'HASH') {
3884: my $num = $settings->{$item}{'order'};
3885: $ordered{$num} = $item;
3886: }
3887: }
3888: $total = scalar(keys(%{$settings}));
3889: }
3890: my @jsarray = ();
3891: foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
3892: push(@jsarray,$ordered{$item});
3893: }
3894: my $jstext = ' var ipaccess = Array('."'".join("','",@jsarray)."'".');'."\n";
3895: return <<"ENDSCRIPT";
3896: <script type="text/javascript">
3897: // <![CDATA[
3898: function reorderIPaccess(form,item) {
3899: var changedVal;
3900: $jstext
3901: var newpos = 'ipaccess_pos_add';
3902: var maxh = 1 + $total;
3903: var current = new Array;
3904: var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
3905: if (item == newpos) {
3906: changedVal = newitemVal;
3907: } else {
3908: changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
3909: current[newitemVal] = newpos;
3910: }
3911: for (var i=0; i<ipaccess.length; i++) {
3912: var elementName = 'ipaccess_pos_'+ipaccess[i];
3913: if (elementName != item) {
3914: if (form.elements[elementName]) {
3915: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
3916: current[currVal] = elementName;
3917: }
3918: }
3919: }
3920: var oldVal;
3921: for (var j=0; j<maxh; j++) {
3922: if (current[j] == undefined) {
3923: oldVal = j;
3924: }
3925: }
3926: if (oldVal < changedVal) {
3927: for (var k=oldVal+1; k<=changedVal ; k++) {
3928: var elementName = current[k];
3929: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
3930: }
3931: } else {
3932: for (var k=changedVal; k<oldVal; k++) {
3933: var elementName = current[k];
3934: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
3935: }
3936: }
3937: return;
3938: }
3939: // ]]>
3940: </script>
3941:
3942: ENDSCRIPT
3943: }
3944:
1.3 raeburn 3945: sub print_autoenroll {
1.30 raeburn 3946: my ($dom,$settings,$rowtotal) = @_;
1.3 raeburn 3947: my $autorun = &Apache::lonnet::auto_run(undef,$dom),
1.399 raeburn 3948: my ($defdom,$runon,$runoff,$coownerson,$coownersoff,
3949: $failsafe,$autofailsafe,$failsafesty,%failsafechecked);
3950: $failsafesty = 'none';
3951: %failsafechecked = (
3952: off => ' checked="checked"',
3953: );
1.3 raeburn 3954: if (ref($settings) eq 'HASH') {
3955: if (exists($settings->{'run'})) {
3956: if ($settings->{'run'} eq '0') {
3957: $runoff = ' checked="checked" ';
3958: $runon = ' ';
3959: } else {
3960: $runon = ' checked="checked" ';
3961: $runoff = ' ';
3962: }
3963: } else {
3964: if ($autorun) {
3965: $runon = ' checked="checked" ';
3966: $runoff = ' ';
3967: } else {
3968: $runoff = ' checked="checked" ';
3969: $runon = ' ';
3970: }
3971: }
1.129 raeburn 3972: if (exists($settings->{'co-owners'})) {
3973: if ($settings->{'co-owners'} eq '0') {
3974: $coownersoff = ' checked="checked" ';
3975: $coownerson = ' ';
3976: } else {
3977: $coownerson = ' checked="checked" ';
3978: $coownersoff = ' ';
3979: }
3980: } else {
3981: $coownersoff = ' checked="checked" ';
3982: $coownerson = ' ';
3983: }
1.3 raeburn 3984: if (exists($settings->{'sender_domain'})) {
3985: $defdom = $settings->{'sender_domain'};
3986: }
1.399 raeburn 3987: if (exists($settings->{'failsafe'})) {
3988: $failsafe = $settings->{'failsafe'};
3989: if ($failsafe eq 'zero') {
1.400 raeburn 3990: $failsafechecked{'zero'} = ' checked="checked"';
1.399 raeburn 3991: $failsafechecked{'off'} = '';
3992: $failsafesty = 'inline-block';
3993: } elsif ($failsafe eq 'any') {
3994: $failsafechecked{'any'} = ' checked="checked"';
3995: $failsafechecked{'off'} = '';
3996: }
3997: $autofailsafe = $settings->{'autofailsafe'};
3998: } elsif (exists($settings->{'autofailsafe'})) {
3999: $autofailsafe = $settings->{'autofailsafe'};
4000: if ($autofailsafe ne '') {
4001: $failsafechecked{'zero'} = ' checked="checked"';
4002: $failsafe = 'zero';
1.400 raeburn 4003: $failsafechecked{'off'} = '';
1.399 raeburn 4004: }
1.274 raeburn 4005: }
1.14 raeburn 4006: } else {
4007: if ($autorun) {
4008: $runon = ' checked="checked" ';
4009: $runoff = ' ';
4010: } else {
4011: $runoff = ' checked="checked" ';
4012: $runon = ' ';
4013: }
1.3 raeburn 4014: }
4015: my $domform = &Apache::loncommon::select_dom_form($defdom,'sender_domain',1);
1.39 raeburn 4016: my $notif_sender;
4017: if (ref($settings) eq 'HASH') {
4018: $notif_sender = $settings->{'sender_uname'};
4019: }
1.3 raeburn 4020: my $datatable='<tr class="LC_odd_row">'.
4021: '<td>'.&mt('Auto-enrollment active?').'</td>'.
1.8 raeburn 4022: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
1.3 raeburn 4023: '<input type="radio" name="autoenroll_run"'.
1.8 raeburn 4024: $runon.' value="1" />'.&mt('Yes').'</label> '.
4025: '<label><input type="radio" name="autoenroll_run"'.
1.14 raeburn 4026: $runoff.' value="0" />'.&mt('No').'</label></span></td>'.
1.3 raeburn 4027: '</tr><tr>'.
4028: '<td>'.&mt('Notification messages - sender').
1.8 raeburn 4029: '</td><td class="LC_right_item"><span class="LC_nobreak">'.
1.3 raeburn 4030: &mt('username').': '.
4031: '<input type="text" name="sender_uname" value="'.
1.39 raeburn 4032: $notif_sender.'" size="10" /> '.&mt('domain').
1.129 raeburn 4033: ': '.$domform.'</span></td></tr>'.
4034: '<tr class="LC_odd_row">'.
4035: '<td>'.&mt('Automatically assign co-ownership').'</td>'.
4036: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
4037: '<input type="radio" name="autoassign_coowners"'.
4038: $coownerson.' value="1" />'.&mt('Yes').'</label> '.
4039: '<label><input type="radio" name="autoassign_coowners"'.
4040: $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
1.274 raeburn 4041: '</tr><tr>'.
4042: '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.
1.400 raeburn 4043: '<td class="LC_left_item"><span class="LC_nobreak">'.
4044: '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="off" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'off'}.' />'.&mt('Not in use').'</label></span> '.
4045: '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="zero" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'zero'}.' />'.&mt('Retrieved section enrollment is zero').'</label></span><br />'.
4046: '<span class="LC_nobreak"><label><input type="radio" name="autoenroll_failsafe" value="any" onclick="toggleFailsafe(this.form)"'.$failsafechecked{'any'}.' />'.&mt('Retrieved section enrollment is zero or greater').'</label></span>'.
1.399 raeburn 4047: '<div class="LC_floatleft" style="display:'.$failsafesty.';" id="autoenroll_failsafe_div">'.
4048: '<span class="LC_nobreak">'.
4049: &mt('Threshold for number of students in section to drop: [_1]',
4050: '<input type="text" name="autoenroll_autofailsafe" value="'.$autofailsafe.'" size="4" />').
4051: '</span></div></td></tr>';
1.274 raeburn 4052: $$rowtotal += 4;
1.3 raeburn 4053: return $datatable;
4054: }
4055:
4056: sub print_autoupdate {
1.30 raeburn 4057: my ($position,$dom,$settings,$rowtotal) = @_;
1.385 raeburn 4058: my ($enable,$datatable);
1.3 raeburn 4059: if ($position eq 'top') {
1.385 raeburn 4060: my %choices = &Apache::lonlocal::texthash (
4061: run => 'Auto-update active?',
4062: classlists => 'Update information in classlists?',
4063: unexpired => 'Skip updates for users without active or future roles?',
4064: lastactive => 'Skip updates for inactive users?',
4065: );
4066: my $itemcount = 0;
1.3 raeburn 4067: my $updateon = ' ';
4068: my $updateoff = ' checked="checked" ';
4069: if (ref($settings) eq 'HASH') {
4070: if ($settings->{'run'} eq '1') {
4071: $updateon = $updateoff;
4072: $updateoff = ' ';
4073: }
4074: }
1.385 raeburn 4075: $enable = '<tr class="LC_odd_row">'.
4076: '<td>'.$choices{'run'}.'</td>'.
4077: '<td class="LC_left_item"><span class="LC_nobreak"><label>'.
1.3 raeburn 4078: '<input type="radio" name="autoupdate_run"'.
1.397 raeburn 4079: $updateoff.'value="0" />'.&mt('No').'</label> '.
1.8 raeburn 4080: '<label><input type="radio" name="autoupdate_run"'.
1.385 raeburn 4081: $updateon.'value="1" />'.&mt('Yes').'</label></span></td>'.
1.3 raeburn 4082: '</tr>';
1.385 raeburn 4083: my @toggles = ('classlists','unexpired');
4084: my %defaultchecked = ('classlists' => 'off',
4085: 'unexpired' => 'off'
4086: );
4087: $$rowtotal ++;
4088: ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
4089: \%choices,$itemcount,'','','left','no');
4090: $datatable = $enable.$datatable;
4091: $$rowtotal += $itemcount;
4092: my $lastactiveon = ' ';
4093: my $lastactiveoff = ' checked="checked" ';
4094: my $lastactivestyle = 'none';
4095: my $lastactivedays;
4096: my $onclick = ' onclick="javascript:toggleLastActiveDays(this.form);"';
4097: if (ref($settings) eq 'HASH') {
4098: if ($settings->{'lastactive'} =~ /^\d+$/) {
4099: $lastactiveon = $lastactiveoff;
4100: $lastactiveoff = ' ';
4101: $lastactivestyle = 'inline-block';
4102: $lastactivedays = $settings->{'lastactive'};
4103: }
4104: }
4105: my $css_class = $itemcount%2?' class="LC_odd_row"':'';
4106: $datatable .= '<tr'.$css_class.'>'.
4107: '<td>'.$choices{'lastactive'}.'</td>'.
4108: '<td class="LC_left_item"><span class="LC_nobreak"><label>'.
4109: '<input type="radio" name="lastactive"'.
4110: $lastactiveoff.'value="0"'.$onclick.' />'.&mt('No').'</label>'.
4111: ' <label>'.
4112: '<input type="radio" name="lastactive"'.
4113: $lastactiveon.' value="1"'.$onclick.' />'.&mt('Yes').'</label>'.
4114: '<div id="lastactive_div" style="display:'.$lastactivestyle.';">'.
4115: ': '.&mt('inactive = no activity in last [_1] days',
4116: '<input type="text" size="5" name="lastactivedays" value="'.
4117: $lastactivedays.'" />').
4118: '</span></td>'.
4119: '</tr>';
4120: $$rowtotal ++;
1.131 raeburn 4121: } elsif ($position eq 'middle') {
4122: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
4123: my $numinrow = 3;
4124: my $locknamesettings;
4125: $datatable .= &insttypes_row($settings,$types,$usertypes,
4126: $dom,$numinrow,$othertitle,
1.305 raeburn 4127: 'lockablenames',$rowtotal);
1.131 raeburn 4128: $$rowtotal ++;
1.3 raeburn 4129: } else {
1.44 raeburn 4130: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.132 raeburn 4131: my @fields = ('lastname','firstname','middlename','generation',
1.20 raeburn 4132: 'permanentemail','id');
1.33 raeburn 4133: my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
1.3 raeburn 4134: my $numrows = 0;
1.26 raeburn 4135: if (ref($types) eq 'ARRAY') {
4136: if (@{$types} > 0) {
4137: $datatable =
4138: &usertype_update_row($settings,$usertypes,\%fieldtitles,
4139: \@fields,$types,\$numrows);
1.30 raeburn 4140: $$rowtotal += @{$types};
1.26 raeburn 4141: }
1.3 raeburn 4142: }
4143: $datatable .=
4144: &usertype_update_row($settings,{'default' => $othertitle},
4145: \%fieldtitles,\@fields,['default'],
4146: \$numrows);
1.30 raeburn 4147: $$rowtotal ++;
1.3 raeburn 4148: }
4149: return $datatable;
4150: }
4151:
1.125 raeburn 4152: sub print_autocreate {
4153: my ($dom,$settings,$rowtotal) = @_;
1.191 raeburn 4154: my (%createon,%createoff,%currhash);
1.125 raeburn 4155: my @types = ('xml','req');
4156: if (ref($settings) eq 'HASH') {
4157: foreach my $item (@types) {
4158: $createoff{$item} = ' checked="checked" ';
4159: $createon{$item} = ' ';
4160: if (exists($settings->{$item})) {
4161: if ($settings->{$item}) {
4162: $createon{$item} = ' checked="checked" ';
4163: $createoff{$item} = ' ';
4164: }
4165: }
4166: }
1.210 raeburn 4167: if ($settings->{'xmldc'} ne '') {
1.191 raeburn 4168: $currhash{$settings->{'xmldc'}} = 1;
4169: }
1.125 raeburn 4170: } else {
4171: foreach my $item (@types) {
4172: $createoff{$item} = ' checked="checked" ';
4173: $createon{$item} = ' ';
4174: }
4175: }
4176: $$rowtotal += 2;
1.191 raeburn 4177: my $numinrow = 2;
1.125 raeburn 4178: my $datatable='<tr class="LC_odd_row">'.
4179: '<td>'.&mt('Create pending official courses from XML files').'</td>'.
4180: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
4181: '<input type="radio" name="autocreate_xml"'.
4182: $createon{'xml'}.' value="1" />'.&mt('Yes').'</label> '.
4183: '<label><input type="radio" name="autocreate_xml"'.
1.143 raeburn 4184: $createoff{'xml'}.' value="0" />'.&mt('No').'</label></span>'.
4185: '</td></tr><tr>'.
4186: '<td>'.&mt('Create pending requests for official courses (if validated)').'</td>'.
4187: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
4188: '<input type="radio" name="autocreate_req"'.
4189: $createon{'req'}.' value="1" />'.&mt('Yes').'</label> '.
4190: '<label><input type="radio" name="autocreate_req"'.
4191: $createoff{'req'}.' value="0" />'.&mt('No').'</label></span>';
1.191 raeburn 4192: my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
4193: 'autocreate_xmldc',%currhash);
1.247 raeburn 4194: $datatable .= '</td></tr><tr class="LC_odd_row"><td>';
1.125 raeburn 4195: if ($numdc > 1) {
1.247 raeburn 4196: $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)').
4197: '</td><td class="LC_left_item">';
1.125 raeburn 4198: } else {
1.247 raeburn 4199: $datatable .= &mt('Course creation processed as:').
4200: '</td><td class="LC_right_item">';
1.125 raeburn 4201: }
1.247 raeburn 4202: $datatable .= $dctable.'</td></tr>';
1.191 raeburn 4203: $$rowtotal += $rows;
1.125 raeburn 4204: return $datatable;
4205: }
4206:
1.23 raeburn 4207: sub print_directorysrch {
1.277 raeburn 4208: my ($position,$dom,$settings,$rowtotal) = @_;
4209: my $datatable;
4210: if ($position eq 'top') {
4211: my $instsrchon = ' ';
4212: my $instsrchoff = ' checked="checked" ';
4213: my ($exacton,$containson,$beginson);
4214: my $instlocalon = ' ';
4215: my $instlocaloff = ' checked="checked" ';
4216: if (ref($settings) eq 'HASH') {
4217: if ($settings->{'available'} eq '1') {
4218: $instsrchon = $instsrchoff;
4219: $instsrchoff = ' ';
4220: }
4221: if ($settings->{'localonly'} eq '1') {
4222: $instlocalon = $instlocaloff;
4223: $instlocaloff = ' ';
4224: }
4225: if (ref($settings->{'searchtypes'}) eq 'ARRAY') {
4226: foreach my $type (@{$settings->{'searchtypes'}}) {
4227: if ($type eq 'exact') {
4228: $exacton = ' checked="checked" ';
4229: } elsif ($type eq 'contains') {
4230: $containson = ' checked="checked" ';
4231: } elsif ($type eq 'begins') {
4232: $beginson = ' checked="checked" ';
4233: }
4234: }
4235: } else {
4236: if ($settings->{'searchtypes'} eq 'exact') {
4237: $exacton = ' checked="checked" ';
4238: } elsif ($settings->{'searchtypes'} eq 'contains') {
4239: $containson = ' checked="checked" ';
4240: } elsif ($settings->{'searchtypes'} eq 'specify') {
1.25 raeburn 4241: $exacton = ' checked="checked" ';
4242: $containson = ' checked="checked" ';
4243: }
4244: }
1.277 raeburn 4245: }
4246: my ($searchtitles,$titleorder) = &sorted_searchtitles();
4247: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
4248:
4249: my $numinrow = 4;
4250: my $cansrchrow = 0;
4251: $datatable='<tr class="LC_odd_row">'.
4252: '<td colspan="2"><span class ="LC_nobreak">'.&mt('Institutional directory search available?').'</span></td>'.
4253: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
4254: '<input type="radio" name="dirsrch_available"'.
4255: $instsrchon.' value="1" />'.&mt('Yes').'</label> '.
4256: '<label><input type="radio" name="dirsrch_available"'.
4257: $instsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.
4258: '</tr><tr>'.
4259: '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search institution?').'</span></td>'.
4260: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
4261: '<input type="radio" name="dirsrch_instlocalonly"'.
4262: $instlocaloff.' value="0" />'.&mt('Yes').'</label> '.
4263: '<label><input type="radio" name="dirsrch_instlocalonly"'.
4264: $instlocalon.' value="1" />'.&mt('No').'</label></span></td>'.
4265: '</tr>';
4266: $$rowtotal += 2;
4267: if (ref($usertypes) eq 'HASH') {
4268: if (keys(%{$usertypes}) > 0) {
4269: $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
1.305 raeburn 4270: $numinrow,$othertitle,'cansearch',
4271: $rowtotal);
1.277 raeburn 4272: $cansrchrow = 1;
1.25 raeburn 4273: }
1.23 raeburn 4274: }
1.277 raeburn 4275: if ($cansrchrow) {
4276: $$rowtotal ++;
4277: $datatable .= '<tr>';
4278: } else {
4279: $datatable .= '<tr class="LC_odd_row">';
1.26 raeburn 4280: }
1.277 raeburn 4281: $datatable .= '<td><span class ="LC_nobreak">'.&mt('Supported search methods').
4282: '</span></td><td class="LC_left_item" colspan="2"><table><tr>';
4283: foreach my $title (@{$titleorder}) {
4284: if (defined($searchtitles->{$title})) {
4285: my $check = ' ';
4286: if (ref($settings) eq 'HASH') {
4287: if (ref($settings->{'searchby'}) eq 'ARRAY') {
4288: if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) {
4289: $check = ' checked="checked" ';
4290: }
1.39 raeburn 4291: }
1.25 raeburn 4292: }
1.277 raeburn 4293: $datatable .= '<td class="LC_left_item">'.
4294: '<span class="LC_nobreak"><label>'.
4295: '<input type="checkbox" name="searchby" '.
4296: 'value="'.$title.'"'.$check.'/>'.
4297: $searchtitles->{$title}.'</label></span></td>';
1.25 raeburn 4298: }
4299: }
1.277 raeburn 4300: $datatable .= '</tr></table></td></tr>';
4301: $$rowtotal ++;
4302: if ($cansrchrow) {
4303: $datatable .= '<tr class="LC_odd_row">';
4304: } else {
4305: $datatable .= '<tr>';
4306: }
4307: $datatable .= '<td><span class ="LC_nobreak">'.&mt('Search latitude').'</span></td>'.
4308: '<td class="LC_left_item" colspan="2">'.
4309: '<span class="LC_nobreak"><label>'.
4310: '<input type="checkbox" name="searchtypes" '.
4311: $exacton.' value="exact" />'.&mt('Exact match').
4312: '</label> '.
4313: '<label><input type="checkbox" name="searchtypes" '.
4314: $beginson.' value="begins" />'.&mt('Begins with').
4315: '</label> '.
4316: '<label><input type="checkbox" name="searchtypes" '.
4317: $containson.' value="contains" />'.&mt('Contains').
4318: '</label></span></td></tr>';
4319: $$rowtotal ++;
1.26 raeburn 4320: } else {
1.277 raeburn 4321: my $domsrchon = ' checked="checked" ';
4322: my $domsrchoff = ' ';
4323: my $domlocalon = ' ';
4324: my $domlocaloff = ' checked="checked" ';
4325: if (ref($settings) eq 'HASH') {
4326: if ($settings->{'lclocalonly'} eq '1') {
4327: $domlocalon = $domlocaloff;
4328: $domlocaloff = ' ';
4329: }
4330: if ($settings->{'lcavailable'} eq '0') {
4331: $domsrchoff = $domsrchon;
4332: $domsrchon = ' ';
4333: }
4334: }
4335: $datatable='<tr class="LC_odd_row">'.
4336: '<td colspan="2"><span class ="LC_nobreak">'.&mt('LON-CAPA directory search available?').'</span></td>'.
4337: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
4338: '<input type="radio" name="dirsrch_domavailable"'.
4339: $domsrchon.' value="1" />'.&mt('Yes').'</label> '.
4340: '<label><input type="radio" name="dirsrch_domavailable"'.
4341: $domsrchoff.' value="0" />'.&mt('No').'</label></span></td>'.
4342: '</tr><tr>'.
4343: '<td colspan="2"><span class ="LC_nobreak">'.&mt('Other domains can search LON-CAPA domain?').'</span></td>'.
4344: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
4345: '<input type="radio" name="dirsrch_domlocalonly"'.
4346: $domlocaloff.' value="0" />'.&mt('Yes').'</label> '.
4347: '<label><input type="radio" name="dirsrch_domlocalonly"'.
4348: $domlocalon.' value="1" />'.&mt('No').'</label></span></td>'.
4349: '</tr>';
4350: $$rowtotal += 2;
1.26 raeburn 4351: }
1.25 raeburn 4352: return $datatable;
4353: }
4354:
1.28 raeburn 4355: sub print_contacts {
1.286 raeburn 4356: my ($position,$dom,$settings,$rowtotal) = @_;
1.28 raeburn 4357: my $datatable;
4358: my @contacts = ('adminemail','supportemail');
1.286 raeburn 4359: my (%checked,%to,%otheremails,%bccemails,%includestr,%includeloc,%currfield,
1.340 raeburn 4360: $maxsize,$fields,$fieldtitles,$fieldoptions,$possoptions,@mailings,%lonstatus);
1.286 raeburn 4361: if ($position eq 'top') {
4362: if (ref($settings) eq 'HASH') {
4363: foreach my $item (@contacts) {
4364: if (exists($settings->{$item})) {
4365: $to{$item} = $settings->{$item};
4366: }
4367: }
4368: }
4369: } elsif ($position eq 'middle') {
4370: @mailings = ('errormail','packagesmail','lonstatusmail','requestsmail',
1.350 raeburn 4371: 'updatesmail','idconflictsmail','hostipmail');
1.288 raeburn 4372: foreach my $type (@mailings) {
4373: $otheremails{$type} = '';
4374: }
1.340 raeburn 4375: } elsif ($position eq 'lower') {
4376: if (ref($settings) eq 'HASH') {
4377: if (ref($settings->{'lonstatus'}) eq 'HASH') {
4378: %lonstatus = %{$settings->{'lonstatus'}};
4379: }
4380: }
1.286 raeburn 4381: } else {
4382: @mailings = ('helpdeskmail','otherdomsmail');
1.288 raeburn 4383: foreach my $type (@mailings) {
4384: $otheremails{$type} = '';
4385: }
1.286 raeburn 4386: $bccemails{'helpdeskmail'} = '';
4387: $bccemails{'otherdomsmail'} = '';
4388: $includestr{'helpdeskmail'} = '';
4389: $includestr{'otherdomsmail'} = '';
4390: ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
4391: }
1.28 raeburn 4392: if (ref($settings) eq 'HASH') {
1.340 raeburn 4393: unless (($position eq 'top') || ($position eq 'lower')) {
1.286 raeburn 4394: foreach my $type (@mailings) {
4395: if (exists($settings->{$type})) {
4396: if (ref($settings->{$type}) eq 'HASH') {
4397: foreach my $item (@contacts) {
4398: if ($settings->{$type}{$item}) {
4399: $checked{$type}{$item} = ' checked="checked" ';
4400: }
4401: }
4402: $otheremails{$type} = $settings->{$type}{'others'};
4403: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
4404: $bccemails{$type} = $settings->{$type}{'bcc'};
4405: if ($settings->{$type}{'include'} ne '') {
4406: ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);
4407: $includestr{$type} = &unescape($includestr{$type});
4408: }
4409: }
4410: }
4411: } elsif ($type eq 'lonstatusmail') {
4412: $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
4413: }
1.28 raeburn 4414: }
4415: }
1.286 raeburn 4416: if ($position eq 'bottom') {
4417: foreach my $type (@mailings) {
4418: $bccemails{$type} = $settings->{$type}{'bcc'};
4419: if ($settings->{$type}{'include'} ne '') {
4420: ($includeloc{$type},$includestr{$type}) = split(/:/,$settings->{$type}{'include'},2);
4421: $includestr{$type} = &unescape($includestr{$type});
4422: }
4423: }
4424: if (ref($settings->{'helpform'}) eq 'HASH') {
4425: if (ref($fields) eq 'ARRAY') {
4426: foreach my $field (@{$fields}) {
4427: $currfield{$field} = $settings->{'helpform'}{$field};
1.28 raeburn 4428: }
1.286 raeburn 4429: }
4430: if (exists($settings->{'helpform'}{'maxsize'})) {
4431: $maxsize = $settings->{'helpform'}{'maxsize'};
4432: } else {
1.289 raeburn 4433: $maxsize = '1.0';
1.286 raeburn 4434: }
4435: } else {
4436: if (ref($fields) eq 'ARRAY') {
4437: foreach my $field (@{$fields}) {
4438: $currfield{$field} = 'yes';
1.134 raeburn 4439: }
1.28 raeburn 4440: }
1.286 raeburn 4441: $maxsize = '1.0';
1.28 raeburn 4442: }
4443: }
4444: } else {
1.286 raeburn 4445: if ($position eq 'top') {
4446: $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
4447: $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
4448: $checked{'errormail'}{'adminemail'} = ' checked="checked" ';
4449: $checked{'packagesmail'}{'adminemail'} = ' checked="checked" ';
1.289 raeburn 4450: $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" ';
1.286 raeburn 4451: $checked{'requestsmail'}{'adminemail'} = ' checked="checked" ';
4452: $checked{'updatesmail'}{'adminemail'} = ' checked="checked" ';
4453: $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" ';
1.350 raeburn 4454: $checked{'hostipmail'}{'adminemail'} = ' checked="checked" ';
1.286 raeburn 4455: } elsif ($position eq 'bottom') {
4456: $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" ';
4457: $checked{'otherdomsmail'}{'supportemail'} = ' checked="checked" ';
4458: if (ref($fields) eq 'ARRAY') {
4459: foreach my $field (@{$fields}) {
4460: $currfield{$field} = 'yes';
4461: }
4462: }
4463: $maxsize = '1.0';
4464: }
1.28 raeburn 4465: }
4466: my ($titles,$short_titles) = &contact_titles();
4467: my $rownum = 0;
4468: my $css_class;
1.286 raeburn 4469: if ($position eq 'top') {
4470: foreach my $item (@contacts) {
4471: $css_class = $rownum%2?' class="LC_odd_row"':'';
4472: $datatable .= '<tr'.$css_class.'>'.
4473: '<td><span class="LC_nobreak">'.$titles->{$item}.
4474: '</span></td><td class="LC_right_item">'.
4475: '<input type="text" name="'.$item.'" value="'.
4476: $to{$item}.'" /></td></tr>';
4477: $rownum ++;
4478: }
1.315 raeburn 4479: } elsif ($position eq 'bottom') {
4480: $css_class = $rownum%2?' class="LC_odd_row"':'';
4481: $datatable .= '<tr'.$css_class.'>'.
4482: '<td>'.&mt('Extra helpdesk form fields:').'<br />'.
4483: &mt('(e-mail, subject, and description always shown)').
4484: '</td><td class="LC_left_item">';
4485: if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&
4486: (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {
4487: $datatable .= '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Status').'</th></tr>';
4488: foreach my $field (@{$fields}) {
4489: $datatable .= '<tr><td>'.$fieldtitles->{$field};
4490: if (($field eq 'screenshot') || ($field eq 'cc')) {
4491: $datatable .= ' '.&mt('(logged-in users)');
4492: }
4493: $datatable .='</td><td>';
4494: my $clickaction;
4495: if ($field eq 'screenshot') {
4496: $clickaction = ' onclick="screenshotSize(this);"';
4497: }
4498: if (ref($possoptions->{$field}) eq 'ARRAY') {
4499: foreach my $option (@{$possoptions->{$field}}) {
4500: my $checked;
4501: if ($currfield{$field} eq $option) {
4502: $checked = ' checked="checked"';
4503: }
4504: $datatable .= '<span class="LC_nobreak"><label>'.
4505: '<input type="radio" name="helpform_'.$field.'" '.
4506: 'value="'.$option.'"'.$checked.$clickaction.' />'.$fieldoptions->{$option}.
4507: '</label></span>'.(' 'x2);
4508: }
4509: }
4510: if ($field eq 'screenshot') {
4511: my $display;
4512: if ($currfield{$field} eq 'no') {
4513: $display = ' style="display:none"';
4514: }
1.334 raeburn 4515: $datatable .= '</td></tr><tr id="help_screenshotsize"'.$display.'>'.
1.315 raeburn 4516: '<td>'.&mt('Maximum size for upload (MB)').'</td><td>'.
4517: '<input type="text" size="5" name="helpform_maxsize" value="'.$maxsize.'" />';
4518: }
4519: $datatable .= '</td></tr>';
4520: }
4521: $datatable .= '</table>';
4522: }
4523: $datatable .= '</td></tr>'."\n";
4524: $rownum ++;
4525: }
1.340 raeburn 4526: unless (($position eq 'top') || ($position eq 'lower')) {
1.286 raeburn 4527: foreach my $type (@mailings) {
4528: $css_class = $rownum%2?' class="LC_odd_row"':'';
4529: $datatable .= '<tr'.$css_class.'>'.
4530: '<td><span class="LC_nobreak">'.
4531: $titles->{$type}.': </span></td>'.
4532: '<td class="LC_left_item">';
4533: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
4534: $datatable .= '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>';
4535: }
4536: $datatable .= '<span class="LC_nobreak">';
4537: foreach my $item (@contacts) {
4538: $datatable .= '<label>'.
4539: '<input type="checkbox" name="'.$type.'"'.
4540: $checked{$type}{$item}.
4541: ' value="'.$item.'" />'.$short_titles->{$item}.
4542: '</label> ';
4543: }
4544: $datatable .= '</span><br />'.&mt('Others').': '.
4545: '<input type="text" name="'.$type.'_others" '.
4546: 'value="'.$otheremails{$type}.'" />';
4547: my %locchecked;
4548: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
4549: foreach my $loc ('s','b') {
4550: if ($includeloc{$type} eq $loc) {
4551: $locchecked{$loc} = ' checked="checked"';
4552: last;
4553: }
4554: }
4555: $datatable .= '<br />'.&mt('Bcc:').(' 'x6).
4556: '<input type="text" name="'.$type.'_bcc" '.
4557: 'value="'.$bccemails{$type}.'" /></fieldset>'.
4558: '<fieldset><legend>'.&mt('Optional added text').'</legend>'.
4559: &mt('Text automatically added to e-mail:').' '.
1.334 raeburn 4560: '<input type="text" name="'.$type.'_includestr" value="'.$includestr{$type}.'" /><br />'.
1.286 raeburn 4561: '<span class="LC_nobreak">'.&mt('Location:').' '.
4562: '<label><input type="radio" name="'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.
4563: (' 'x2).
4564: '<label><input type="radio" name="'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.
4565: '</span></fieldset>';
4566: }
4567: $datatable .= '</td></tr>'."\n";
4568: $rownum ++;
4569: }
1.28 raeburn 4570: }
1.286 raeburn 4571: if ($position eq 'middle') {
4572: my %choices;
1.340 raeburn 4573: my $corelink = &core_link_msu();
4574: $choices{'reporterrors'} = &mt('E-mail error reports to [_1]',$corelink);
1.286 raeburn 4575: $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]',
1.340 raeburn 4576: $corelink);
4577: $choices{'reportstatus'} = &mt('E-mail status if errors above threshold to [_1]',$corelink);
4578: my @toggles = ('reporterrors','reportupdates','reportstatus');
1.286 raeburn 4579: my %defaultchecked = ('reporterrors' => 'on',
1.340 raeburn 4580: 'reportupdates' => 'on',
4581: 'reportstatus' => 'on');
1.286 raeburn 4582: (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
4583: \%choices,$rownum);
4584: $datatable .= $reports;
1.340 raeburn 4585: } elsif ($position eq 'lower') {
1.378 raeburn 4586: my (%current,%excluded,%weights);
1.340 raeburn 4587: my ($defaults,$names) = &Apache::loncommon::lon_status_items();
4588: if ($lonstatus{'threshold'} =~ /^\d+$/) {
1.378 raeburn 4589: $current{'errorthreshold'} = $lonstatus{'threshold'};
1.340 raeburn 4590: } else {
1.378 raeburn 4591: $current{'errorthreshold'} = $defaults->{'threshold'};
1.340 raeburn 4592: }
4593: if ($lonstatus{'sysmail'} =~ /^\d+$/) {
1.378 raeburn 4594: $current{'errorsysmail'} = $lonstatus{'sysmail'};
1.340 raeburn 4595: } else {
1.378 raeburn 4596: $current{'errorsysmail'} = $defaults->{'sysmail'};
1.340 raeburn 4597: }
4598: if (ref($lonstatus{'weights'}) eq 'HASH') {
1.341 raeburn 4599: foreach my $type ('E','W','N','U') {
1.340 raeburn 4600: if ($lonstatus{'weights'}{$type} =~ /^\d+$/) {
4601: $weights{$type} = $lonstatus{'weights'}{$type};
4602: } else {
4603: $weights{$type} = $defaults->{$type};
4604: }
4605: }
4606: } else {
1.341 raeburn 4607: foreach my $type ('E','W','N','U') {
1.340 raeburn 4608: $weights{$type} = $defaults->{$type};
4609: }
4610: }
4611: if (ref($lonstatus{'excluded'}) eq 'ARRAY') {
4612: if (@{$lonstatus{'excluded'}} > 0) {
4613: map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};
4614: }
4615: }
1.425 raeburn 4616: foreach my $item ('errorthreshold','errorsysmail') {
1.378 raeburn 4617: $css_class = $rownum%2?' class="LC_odd_row"':'';
4618: $datatable .= '<tr'.$css_class.'>'.
4619: '<td class="LC_left_item"><span class="LC_nobreak">'.
4620: $titles->{$item}.
4621: '</span></td><td class="LC_left_item">'.
4622: '<input type="text" name="'.$item.'" value="'.
4623: $current{$item}.'" size="5" /></td></tr>';
4624: $rownum ++;
4625: }
1.340 raeburn 4626: $css_class = $rownum%2?' class="LC_odd_row"':'';
4627: $datatable .= '<tr'.$css_class.'>'.
4628: '<td class="LC_left_item">'.
4629: '<span class="LC_nobreak">'.$titles->{'errorweights'}.
4630: '</span></td><td class="LC_left_item"><table><tr>';
1.341 raeburn 4631: foreach my $type ('E','W','N','U') {
1.340 raeburn 4632: $datatable .= '<td>'.$names->{$type}.'<br />'.
4633: '<input type="text" name="errorweights_'.$type.'" value="'.
4634: $weights{$type}.'" size="5" /></td>';
4635: }
4636: $datatable .= '</tr></table></tr>';
4637: $rownum ++;
4638: $css_class = $rownum%2?' class="LC_odd_row"':'';
4639: $datatable .= '<tr'.$css_class.'><td class="LC_left_item">'.
4640: $titles->{'errorexcluded'}.'</td>'.
4641: '<td class="LC_left_item"><table>';
4642: my $numinrow = 4;
4643: my @ids = sort(values(%Apache::lonnet::serverhomeIDs));
4644: for (my $i=0; $i<@ids; $i++) {
4645: my $rem = $i%($numinrow);
4646: if ($rem == 0) {
4647: if ($i > 0) {
4648: $datatable .= '</tr>';
4649: }
4650: $datatable .= '<tr>';
4651: }
4652: my $check;
4653: if ($excluded{$ids[$i]}) {
4654: $check = ' checked="checked" ';
4655: }
4656: $datatable .= '<td class="LC_left_item">'.
4657: '<span class="LC_nobreak"><label>'.
4658: '<input type="checkbox" name="errorexcluded" '.
4659: 'value="'.$ids[$i].'"'.$check.' />'.
4660: $ids[$i].'</label></span></td>';
4661: }
4662: my $colsleft = $numinrow - @ids%($numinrow);
4663: if ($colsleft > 1 ) {
4664: $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
4665: ' </td>';
4666: } elsif ($colsleft == 1) {
4667: $datatable .= '<td class="LC_left_item"> </td>';
4668: }
4669: $datatable .= '</tr></table></td></tr>';
4670: $rownum ++;
1.286 raeburn 4671: } elsif ($position eq 'bottom') {
1.315 raeburn 4672: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
4673: my (@posstypes,%usertypeshash);
4674: if (ref($types) eq 'ARRAY') {
4675: @posstypes = @{$types};
4676: }
4677: if (@posstypes) {
4678: if (ref($usertypes) eq 'HASH') {
4679: %usertypeshash = %{$usertypes};
4680: }
4681: my @overridden;
4682: my $numinrow = 4;
4683: if (ref($settings) eq 'HASH') {
4684: if (ref($settings->{'overrides'}) eq 'HASH') {
4685: foreach my $key (sort(keys(%{$settings->{'overrides'}}))) {
4686: if (ref($settings->{'overrides'}{$key}) eq 'HASH') {
4687: push(@overridden,$key);
4688: foreach my $item (@contacts) {
4689: if ($settings->{'overrides'}{$key}{$item}) {
4690: $checked{'override_'.$key}{$item} = ' checked="checked" ';
4691: }
4692: }
4693: $otheremails{'override_'.$key} = $settings->{'overrides'}{$key}{'others'};
4694: $bccemails{'override_'.$key} = $settings->{'overrides'}{$key}{'bcc'};
4695: $includeloc{'override_'.$key} = '';
4696: $includestr{'override_'.$key} = '';
4697: if ($settings->{'overrides'}{$key}{'include'} ne '') {
1.425 raeburn 4698: ($includeloc{'override_'.$key},$includestr{'override_'.$key}) =
1.315 raeburn 4699: split(/:/,$settings->{'overrides'}{$key}{'include'},2);
4700: $includestr{'override_'.$key} = &unescape($includestr{'override_'.$key});
4701: }
1.286 raeburn 4702: }
4703: }
4704: }
1.315 raeburn 4705: }
4706: my $customclass = 'LC_helpdesk_override';
4707: my $optionsprefix = 'LC_options_helpdesk_';
4708:
4709: my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";
4710: $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
4711: $numinrow,$othertitle,'overrides',
4712: \$rownum,$onclicktypes,$customclass);
4713: $rownum ++;
4714: $usertypeshash{'default'} = $othertitle;
4715: foreach my $status (@posstypes) {
4716: my $css_class;
4717: if ($rownum%2) {
4718: $css_class = 'LC_odd_row ';
4719: }
4720: $css_class .= $customclass;
4721: my $rowid = $optionsprefix.$status;
4722: my $hidden = 1;
4723: my $currstyle = 'display:none';
4724: if (grep(/^\Q$status\E$/,@overridden)) {
4725: $currstyle = 'display:table-row';
4726: $hidden = 0;
4727: }
4728: my $key = 'override_'.$status;
4729: $datatable .= &overridden_helpdesk($checked{$key},$otheremails{$key},$bccemails{$key},
4730: $includeloc{$key},$includestr{$key},$status,$rowid,
4731: $usertypeshash{$status},$css_class,$currstyle,
4732: \@contacts,$short_titles);
4733: unless ($hidden) {
4734: $rownum ++;
1.286 raeburn 4735: }
4736: }
1.134 raeburn 4737: }
1.28 raeburn 4738: }
1.30 raeburn 4739: $$rowtotal += $rownum;
1.28 raeburn 4740: return $datatable;
4741: }
4742:
1.340 raeburn 4743: sub core_link_msu {
4744: return &Apache::loncommon::modal_link('http://loncapa.org/core.html',
4745: &mt('LON-CAPA core group - MSU'),600,500);
4746: }
4747:
1.315 raeburn 4748: sub overridden_helpdesk {
4749: my ($checked,$otheremails,$bccemails,$includeloc,$includestr,$type,$rowid,
4750: $typetitle,$css_class,$rowstyle,$contacts,$short_titles) = @_;
4751: my $class = 'LC_left_item';
4752: if ($css_class) {
4753: $css_class = ' class="'.$css_class.'"';
4754: }
4755: if ($rowid) {
4756: $rowid = ' id="'.$rowid.'"';
4757: }
4758: if ($rowstyle) {
4759: $rowstyle = ' style="'.$rowstyle.'"';
4760: }
4761: my ($output,$description);
4762: $description = &mt('Helpdesk requests from: [_1] in this domain (overrides default)',"<b>$typetitle</b>");
4763: $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.
4764: "<td>$description</td>\n".
4765: '<td class="'.$class.'" colspan="2">'.
4766: '<fieldset><legend>'.&mt('E-mail recipient(s)').'</legend>'.
4767: '<span class="LC_nobreak">';
4768: if (ref($contacts) eq 'ARRAY') {
4769: foreach my $item (@{$contacts}) {
4770: my $check;
4771: if (ref($checked) eq 'HASH') {
4772: $check = $checked->{$item};
4773: }
4774: my $title;
4775: if (ref($short_titles) eq 'HASH') {
1.425 raeburn 4776: $title = $short_titles->{$item};
1.315 raeburn 4777: }
4778: $output .= '<label>'.
4779: '<input type="checkbox" name="override_'.$type.'"'.$check.
4780: ' value="'.$item.'" />'.$title.'</label> ';
4781: }
4782: }
4783: $output .= '</span><br />'.&mt('Others').': '.
4784: '<input type="text" name="override_'.$type.'_others" '.
4785: 'value="'.$otheremails.'" />';
4786: my %locchecked;
4787: foreach my $loc ('s','b') {
4788: if ($includeloc eq $loc) {
4789: $locchecked{$loc} = ' checked="checked"';
4790: last;
4791: }
4792: }
4793: $output .= '<br />'.&mt('Bcc:').(' 'x6).
4794: '<input type="text" name="override_'.$type.'_bcc" '.
4795: 'value="'.$bccemails.'" /></fieldset>'.
4796: '<fieldset><legend>'.&mt('Optional added text').'</legend>'.
4797: &mt('Text automatically added to e-mail:').' '.
1.334 raeburn 4798: '<input type="text" name="override_'.$type.'_includestr" value="'.$includestr.'" /><br />'.
1.315 raeburn 4799: '<span class="LC_nobreak">'.&mt('Location:').' '.
4800: '<label><input type="radio" name="override_'.$type.'_includeloc" value="s"'.$locchecked{'s'}.' />'.&mt('in subject').'</label>'.
4801: (' 'x2).
4802: '<label><input type="radio" name="override_'.$type.'_includeloc" value="b"'.$locchecked{'b'}.' />'.&mt('in body').'</label>'.
4803: '</span></fieldset>'.
4804: '</td></tr>'."\n";
4805: return $output;
4806: }
4807:
1.286 raeburn 4808: sub contacts_javascript {
4809: return <<"ENDSCRIPT";
4810:
4811: <script type="text/javascript">
4812: // <![CDATA[
4813:
4814: function screenshotSize(field) {
4815: if (document.getElementById('help_screenshotsize')) {
4816: if (field.value == 'no') {
1.289 raeburn 4817: document.getElementById('help_screenshotsize').style.display="none";
1.286 raeburn 4818: } else {
4819: document.getElementById('help_screenshotsize').style.display="";
4820: }
4821: }
4822: return;
4823: }
4824:
1.315 raeburn 4825: function toggleHelpdeskRow(form,checkbox,target,prefix,docount) {
4826: if (form.elements[checkbox].length != undefined) {
4827: var count = 0;
4828: if (docount) {
4829: for (var i=0; i<form.elements[checkbox].length; i++) {
4830: if (form.elements[checkbox][i].checked) {
4831: count ++;
4832: }
4833: }
4834: }
4835: for (var i=0; i<form.elements[checkbox].length; i++) {
4836: var type = form.elements[checkbox][i].value;
4837: if (document.getElementById(prefix+type)) {
4838: if (form.elements[checkbox][i].checked) {
4839: document.getElementById(prefix+type).style.display = 'table-row';
4840: if (count % 2 == 1) {
4841: document.getElementById(prefix+type).className = target+' LC_odd_row';
4842: } else {
4843: document.getElementById(prefix+type).className = target;
4844: }
4845: count ++;
4846: } else {
4847: document.getElementById(prefix+type).style.display = 'none';
4848: }
4849: }
4850: }
4851: }
4852: return;
4853: }
4854:
1.286 raeburn 4855: // ]]>
4856: </script>
4857:
4858: ENDSCRIPT
4859: }
4860:
1.118 jms 4861: sub print_helpsettings {
1.282 raeburn 4862: my ($position,$dom,$settings,$rowtotal) = @_;
4863: my $confname = $dom.'-domainconfig';
1.285 raeburn 4864: my $formname = 'display';
1.168 raeburn 4865: my ($datatable,$itemcount);
1.282 raeburn 4866: if ($position eq 'top') {
4867: $itemcount = 1;
4868: my (%choices,%defaultchecked,@toggles);
4869: $choices{'submitbugs'} = &mt('Display link to: [_1]?',
4870: &Apache::loncommon::modal_link('http://bugs.loncapa.org',
4871: &mt('LON-CAPA bug tracker'),600,500));
4872: %defaultchecked = ('submitbugs' => 'on');
4873: @toggles = ('submitbugs');
4874: ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
4875: \%choices,$itemcount);
4876: $$rowtotal ++;
4877: } else {
4878: my $css_class;
4879: my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
1.285 raeburn 4880: my (%customroles,%ordered,%current);
1.301 raeburn 4881: if (ref($settings) eq 'HASH') {
4882: if (ref($settings->{'adhoc'}) eq 'HASH') {
4883: %current = %{$settings->{'adhoc'}};
4884: }
1.285 raeburn 4885: }
4886: my $count = 0;
4887: foreach my $key (sort(keys(%existing))) {
1.282 raeburn 4888: if ($key=~/^rolesdef\_(\w+)$/) {
4889: my $rolename = $1;
1.285 raeburn 4890: my (%privs,$order);
1.282 raeburn 4891: ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});
4892: $customroles{$rolename} = \%privs;
1.285 raeburn 4893: if (ref($current{$rolename}) eq 'HASH') {
4894: $order = $current{$rolename}{'order'};
4895: }
4896: if ($order eq '') {
4897: $order = $count;
4898: }
4899: $ordered{$order} = $rolename;
4900: $count++;
4901: }
4902: }
4903: my $maxnum = scalar(keys(%ordered));
4904: my @roles_by_num = ();
4905: foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
4906: push(@roles_by_num,$item);
4907: }
4908: my $context = 'domprefs';
4909: my $crstype = 'Course';
4910: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.292 raeburn 4911: my @accesstypes = ('all','dh','da','none');
1.285 raeburn 4912: my ($numstatustypes,@jsarray);
4913: if (ref($types) eq 'ARRAY') {
4914: if (@{$types} > 0) {
4915: $numstatustypes = scalar(@{$types});
4916: push(@accesstypes,'status');
4917: @jsarray = ('bystatus');
1.282 raeburn 4918: }
4919: }
1.290 raeburn 4920: my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);
1.285 raeburn 4921: if (keys(%domhelpdesk)) {
4922: push(@accesstypes,('inc','exc'));
4923: push(@jsarray,('notinc','notexc'));
4924: }
4925: my $hiddenstr = join("','",@jsarray);
1.282 raeburn 4926: my $context = 'domprefs';
4927: my $crstype = 'Course';
1.285 raeburn 4928: my $prefix = 'helproles_';
4929: my $add_class = 'LC_hidden';
4930: foreach my $num (@roles_by_num) {
4931: my $role = $ordered{$num};
4932: my ($desc,$access,@statuses);
4933: if (ref($current{$role}) eq 'HASH') {
4934: $desc = $current{$role}{'desc'};
4935: $access = $current{$role}{'access'};
4936: if (ref($current{$role}{'insttypes'}) eq 'ARRAY') {
4937: @statuses = @{$current{$role}{'insttypes'}};
4938: }
4939: }
4940: if ($desc eq '') {
4941: $desc = $role;
4942: }
4943: my $identifier = 'custhelp'.$num;
1.282 raeburn 4944: my %full=();
4945: my %levels= (
4946: course => {},
4947: domain => {},
4948: system => {},
4949: );
4950: my %levelscurrent=(
4951: course => {},
4952: domain => {},
4953: system => {},
4954: );
4955: &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent);
4956: my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
4957: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.285 raeburn 4958: my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';
1.306 raeburn 4959: $datatable .= '<tr '.$css_class.'><td style="vertical-align: top"><b>'.$role.'</b><br />'.
1.285 raeburn 4960: '<select name="helproles_'.$num.'_pos"'.$chgstr.'>';
4961: for (my $k=0; $k<=$maxnum; $k++) {
4962: my $vpos = $k+1;
4963: my $selstr;
4964: if ($k == $num) {
4965: $selstr = ' selected="selected" ';
4966: }
4967: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
4968: }
4969: $datatable .= '</select>'.(' 'x2).
4970: '<input type="hidden" name="helproles_'.$num.'" value="'.$role.'" />'.
4971: '</td>'.
4972: '<td><fieldset><legend>'.&mt('Role name').'</legend>'.
4973: &mt('Name shown to users:').
4974: '<input type="text" name="helproles_'.$num.'_desc" value="'.$desc.'" />'.
4975: '</fieldset>'.
4976: &helpdeskroles_access($dom,$prefix,$num,$add_class,$current{$role},\@accesstypes,
4977: $othertitle,$usertypes,$types,\%domhelpdesk).
4978: '<fieldset>'.
4979: '<legend>'.&mt('Role privileges').&adhocbutton($prefix,$num,'privs','show').'</legend>'.
1.282 raeburn 4980: &Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels,
1.285 raeburn 4981: \%levelscurrent,$identifier,
4982: 'LC_hidden',$prefix.$num.'_privs').
4983: '</fieldset></td>';
1.282 raeburn 4984: $itemcount ++;
4985: }
4986: $css_class = $itemcount%2?' class="LC_odd_row"':'';
4987: my $newcust = 'custhelp'.$count;
4988: my (%privs,%levelscurrent);
4989: my %full=();
4990: my %levels= (
4991: course => {},
4992: domain => {},
4993: system => {},
4994: );
4995: &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
4996: my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
1.285 raeburn 4997: my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';
1.306 raeburn 4998: $datatable .= '<tr '.$css_class.'><td style="vertical-align: top"><span class="LC_nobreak"><label>'.
1.285 raeburn 4999: '<input type="hidden" name="helproles_maxnum" value="'.$maxnum.'" />'."\n".
5000: '<select name="helproles_'.$count.'_pos"'.$chgstr.'>';
5001: for (my $k=0; $k<$maxnum+1; $k++) {
5002: my $vpos = $k+1;
5003: my $selstr;
5004: if ($k == $maxnum) {
5005: $selstr = ' selected="selected" ';
5006: }
5007: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
5008: }
5009: $datatable .= '</select> '."\n".
1.282 raeburn 5010: '<input type="checkbox" name="newcusthelp" value="'.$count.'" />'. &mt('Add').
5011: '</label></span></td>'.
1.285 raeburn 5012: '<td><fieldset><legend>'.&mt('Role name').'</legend>'.
5013: '<span class="LC_nobreak">'.
5014: &mt('Internal name:').
5015: '<input type="text" size="10" name="custhelpname'.$count.'" value="" />'.
5016: '</span>'.(' 'x4).
5017: '<span class="LC_nobreak">'.
5018: &mt('Name shown to users:').
5019: '<input type="text" size="20" name="helproles_'.$count.'_desc" value="" />'.
5020: '</span></fieldset>'.
5021: &helpdeskroles_access($dom,$prefix,$count,'',undef,\@accesstypes,$othertitle,
5022: $usertypes,$types,\%domhelpdesk).
5023: '<fieldset><legend>'.&mt('Role privileges').'</legend>'.
1.282 raeburn 5024: &Apache::lonuserutils::custom_role_header($context,$crstype,
5025: \@templateroles,$newcust).
5026: &Apache::lonuserutils::custom_role_table('Course',\%full,\%levels,
5027: \%levelscurrent,$newcust).
1.334 raeburn 5028: '</fieldset>'.
5029: &helpsettings_javascript(\@roles_by_num,$maxnum,$hiddenstr,$formname).
5030: '</td></tr>';
1.282 raeburn 5031: $count ++;
5032: $$rowtotal += $count;
5033: }
1.166 raeburn 5034: return $datatable;
1.121 raeburn 5035: }
5036:
1.285 raeburn 5037: sub adhocbutton {
5038: my ($prefix,$num,$field,$visibility) = @_;
5039: my %lt = &Apache::lonlocal::texthash(
5040: show => 'Show details',
5041: hide => 'Hide details',
5042: );
5043: return '<span style="text-decoration:line-through; font-weight: normal;">'.(' 'x10).
5044: '</span>'.(' 'x2).'<input type="button" id="'.$prefix.$num.'_'.$field.'_vis"'.
5045: ' value="'.$lt{$visibility}.'" style="height:20px;" '.
5046: 'onclick="toggleHelpdeskItem('."'$num','$field'".');" />'.(' 'x2);
5047: }
5048:
5049: sub helpsettings_javascript {
5050: my ($roles_by_num,$total,$hiddenstr,$formname) = @_;
5051: return unless(ref($roles_by_num) eq 'ARRAY');
5052: my %html_js_lt = &Apache::lonlocal::texthash(
5053: show => 'Show details',
5054: hide => 'Hide details',
5055: );
5056: &html_escape(\%html_js_lt);
5057: my $jstext = ' var helproles = Array('."'".join("','",@{$roles_by_num})."'".');'."\n";
5058: return <<"ENDSCRIPT";
5059: <script type="text/javascript">
5060: // <![CDATA[
5061:
5062: function reorderHelpRoles(form,item) {
5063: var changedVal;
5064: $jstext
5065: var newpos = 'helproles_${total}_pos';
5066: var maxh = 1 + $total;
5067: var current = new Array();
5068: var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
5069: if (item == newpos) {
5070: changedVal = newitemVal;
5071: } else {
5072: changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
5073: current[newitemVal] = newpos;
5074: }
5075: for (var i=0; i<helproles.length; i++) {
5076: var elementName = 'helproles_'+helproles[i]+'_pos';
5077: if (elementName != item) {
5078: if (form.elements[elementName]) {
5079: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
5080: current[currVal] = elementName;
5081: }
5082: }
5083: }
5084: var oldVal;
5085: for (var j=0; j<maxh; j++) {
5086: if (current[j] == undefined) {
5087: oldVal = j;
5088: }
5089: }
5090: if (oldVal < changedVal) {
5091: for (var k=oldVal+1; k<=changedVal ; k++) {
5092: var elementName = current[k];
5093: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
5094: }
5095: } else {
5096: for (var k=changedVal; k<oldVal; k++) {
5097: var elementName = current[k];
5098: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
5099: }
5100: }
5101: return;
5102: }
5103:
5104: function helpdeskAccess(num) {
5105: var curraccess = null;
5106: if (document.$formname.elements['helproles_'+num+'_access'].length) {
5107: for (var i=0; i<document.$formname.elements['helproles_'+num+'_access'].length; i++) {
5108: if (document.$formname.elements['helproles_'+num+'_access'][i].checked) {
5109: curraccess = document.$formname.elements['helproles_'+num+'_access'][i].value;
5110: }
5111: }
5112: }
5113: var shown = Array();
5114: var hidden = Array();
5115: if (curraccess == 'none') {
5116: hidden = Array('$hiddenstr');
5117: } else {
5118: if (curraccess == 'status') {
5119: shown = Array('bystatus');
5120: hidden = Array('notinc','notexc');
5121: } else {
5122: if (curraccess == 'exc') {
5123: shown = Array('notexc');
5124: hidden = Array('notinc','bystatus');
5125: }
5126: if (curraccess == 'inc') {
5127: shown = Array('notinc');
5128: hidden = Array('notexc','bystatus');
5129: }
1.293 raeburn 5130: if ((curraccess == 'all') || (curraccess == 'dh') || (curraccess == 'da')) {
1.285 raeburn 5131: hidden = Array('notinc','notexc','bystatus');
5132: }
5133: }
5134: }
5135: if (hidden.length > 0) {
5136: for (var i=0; i<hidden.length; i++) {
5137: if (document.getElementById('helproles_'+num+'_'+hidden[i])) {
5138: document.getElementById('helproles_'+num+'_'+hidden[i]).style.display = 'none';
5139: }
5140: }
5141: }
5142: if (shown.length > 0) {
5143: for (var i=0; i<shown.length; i++) {
5144: if (document.getElementById('helproles_'+num+'_'+shown[i])) {
5145: if (shown[i] == 'privs') {
5146: document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'block';
5147: } else {
5148: document.getElementById('helproles_'+num+'_'+shown[i]).style.display = 'inline-block';
5149: }
5150: }
5151: }
5152: }
5153: return;
5154: }
5155:
5156: function toggleHelpdeskItem(num,field) {
5157: if (document.getElementById('helproles_'+num+'_'+field)) {
5158: if (document.getElementById('helproles_'+num+'_'+field).className.match(/(?:^|\\s)LC_hidden(?!\\S)/)) {
1.289 raeburn 5159: document.getElementById('helproles_'+num+'_'+field).className =
1.285 raeburn 5160: document.getElementById('helproles_'+num+'_'+field).className.replace(/(?:^|\\s)LC_hidden(?!\\S)/g ,'');
5161: if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {
5162: document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{hide}';
5163: }
5164: } else {
5165: document.getElementById('helproles_'+num+'_'+field).className += ' LC_hidden';
5166: if (document.getElementById('helproles_'+num+'_'+field+'_vis')) {
5167: document.getElementById('helproles_'+num+'_'+field+'_vis').value = '$html_js_lt{show}';
5168: }
5169: }
5170: }
5171: return;
5172: }
5173:
5174: // ]]>
5175: </script>
5176:
5177: ENDSCRIPT
5178: }
5179:
5180: sub helpdeskroles_access {
5181: my ($dom,$prefix,$num,$add_class,$current,$accesstypes,$othertitle,
5182: $usertypes,$types,$domhelpdesk) = @_;
5183: return unless ((ref($accesstypes) eq 'ARRAY') && (ref($domhelpdesk) eq 'HASH'));
5184: my %lt = &Apache::lonlocal::texthash(
5185: 'rou' => 'Role usage',
5186: 'whi' => 'Which helpdesk personnel may use this role?',
1.292 raeburn 5187: 'all' => 'All with domain helpdesk or helpdesk assistant role',
5188: 'dh' => 'All with domain helpdesk role',
5189: 'da' => 'All with domain helpdesk assistant role',
1.285 raeburn 5190: 'none' => 'None',
5191: 'status' => 'Determined based on institutional status',
5192: 'inc' => 'Include all, but exclude specific personnel',
5193: 'exc' => 'Exclude all, but include specific personnel',
5194: );
5195: my %usecheck = (
5196: all => ' checked="checked"',
5197: );
5198: my %displaydiv = (
5199: status => 'none',
5200: inc => 'none',
5201: exc => 'none',
5202: priv => 'block',
5203: );
5204: my $output;
5205: if (ref($current) eq 'HASH') {
5206: if (($current->{'access'} ne '') && ($current->{'access'} ne 'all')) {
5207: if (grep(/^\Q$current->{access}\E$/,@{$accesstypes})) {
5208: $usecheck{$current->{access}} = $usecheck{'all'};
5209: delete($usecheck{'all'});
5210: if ($current->{access} =~ /^(status|inc|exc)$/) {
5211: my $access = $1;
5212: $displaydiv{$access} = 'inline';
5213: } elsif ($current->{access} eq 'none') {
5214: $displaydiv{'priv'} = 'none';
5215: }
5216: }
5217: }
5218: }
5219: $output = '<fieldset id="'.$prefix.$num.'_usage"><legend>'.$lt{'rou'}.'</legend>'.
5220: '<p>'.$lt{'whi'}.'</p>';
5221: foreach my $access (@{$accesstypes}) {
5222: $output .= '<p><label><input type="radio" name="'.$prefix.$num.'_access" value="'.$access.'" '.$usecheck{$access}.
5223: ' onclick="helpdeskAccess('."'$num'".');" />'.
5224: $lt{$access}.'</label>';
5225: if ($access eq 'status') {
5226: $output .= '<div id="'.$prefix.$num.'_bystatus" style="display:'.$displaydiv{$access}.'">'.
5227: &Apache::lonuserutils::adhoc_status_types($dom,$prefix,$num,$current->{$access},
5228: $othertitle,$usertypes,$types).
5229: '</div>';
5230: } elsif (($access eq 'inc') && (keys(%{$domhelpdesk}) > 0)) {
5231: $output .= '<div id="'.$prefix.$num.'_notinc" style="display:'.$displaydiv{$access}.'">'.
5232: &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).
5233: '</div>';
5234: } elsif (($access eq 'exc') && (keys(%{$domhelpdesk}) > 0)) {
5235: $output .= '<div id="'.$prefix.$num.'_notexc" style="display:'.$displaydiv{$access}.'">'.
5236: &Apache::lonuserutils::adhoc_staff($access,$prefix,$num,$current->{$access},$domhelpdesk).
5237: '</div>';
5238: }
5239: $output .= '</p>';
5240: }
5241: $output .= '</fieldset>';
5242: return $output;
5243: }
5244:
1.121 raeburn 5245: sub radiobutton_prefs {
1.192 raeburn 5246: my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick,
1.385 raeburn 5247: $additional,$align,$firstval) = @_;
1.121 raeburn 5248: return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') &&
5249: (ref($choices) eq 'HASH'));
5250:
1.170 raeburn 5251: my (%checkedon,%checkedoff,$datatable,$css_class);
1.121 raeburn 5252:
5253: foreach my $item (@{$toggles}) {
5254: if ($defaultchecked->{$item} eq 'on') {
1.118 jms 5255: $checkedon{$item} = ' checked="checked" ';
5256: $checkedoff{$item} = ' ';
1.121 raeburn 5257: } elsif ($defaultchecked->{$item} eq 'off') {
1.118 jms 5258: $checkedoff{$item} = ' checked="checked" ';
5259: $checkedon{$item} = ' ';
5260: }
5261: }
5262: if (ref($settings) eq 'HASH') {
1.121 raeburn 5263: foreach my $item (@{$toggles}) {
1.118 jms 5264: if ($settings->{$item} eq '1') {
5265: $checkedon{$item} = ' checked="checked" ';
5266: $checkedoff{$item} = ' ';
5267: } elsif ($settings->{$item} eq '0') {
5268: $checkedoff{$item} = ' checked="checked" ';
5269: $checkedon{$item} = ' ';
5270: }
5271: }
1.121 raeburn 5272: }
1.192 raeburn 5273: if ($onclick) {
5274: $onclick = ' onclick="'.$onclick.'"';
5275: }
1.121 raeburn 5276: foreach my $item (@{$toggles}) {
1.118 jms 5277: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.121 raeburn 5278: $datatable .=
1.306 raeburn 5279: '<tr'.$css_class.'><td style="vertical-align: top">'.
1.192 raeburn 5280: '<span class="LC_nobreak">'.$choices->{$item}.
1.257 raeburn 5281: '</span></td>';
5282: if ($align eq 'left') {
5283: $datatable .= '<td class="LC_left_item">';
5284: } else {
5285: $datatable .= '<td class="LC_right_item">';
5286: }
1.385 raeburn 5287: $datatable .= '<span class="LC_nobreak">';
5288: if ($firstval eq 'no') {
5289: $datatable .=
5290: '<label><input type="radio" name="'.
5291: $item.'" '.$checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').
5292: '</label> <label><input type="radio" name="'.$item.'" '.
5293: $checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').'</label>';
5294: } else {
5295: $datatable .=
5296: '<label><input type="radio" name="'.
5297: $item.'" '.$checkedon{$item}.' value="1"'.$onclick.' />'.&mt('Yes').
5298: '</label> <label><input type="radio" name="'.$item.'" '.
5299: $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').'</label>';
5300: }
5301: $datatable .= '</span>'.$additional.'</td></tr>';
1.118 jms 5302: $itemcount ++;
1.121 raeburn 5303: }
5304: return ($datatable,$itemcount);
5305: }
5306:
1.267 raeburn 5307: sub print_ltitools {
1.421 raeburn 5308: my ($position,$dom,$settings,$rowtotal) = @_;
5309: my (%rules,%encrypt,%privkeys,%linkprot);
1.267 raeburn 5310: if (ref($settings) eq 'HASH') {
1.421 raeburn 5311: if ($position eq 'top') {
5312: if (exists($settings->{'encrypt'})) {
5313: if (ref($settings->{'encrypt'}) eq 'HASH') {
5314: foreach my $key (keys(%{$settings->{'encrypt'}})) {
5315: $encrypt{'toolsec_'.$key} = $settings->{'encrypt'}{$key};
1.324 raeburn 5316: }
5317: }
1.267 raeburn 5318: }
1.421 raeburn 5319: if (exists($settings->{'private'})) {
5320: if (ref($settings->{'private'}) eq 'HASH') {
5321: if (ref($settings->{'private'}) eq 'HASH') {
5322: if (ref($settings->{'private'}{'keys'}) eq 'ARRAY') {
5323: map { $privkeys{$_} = 1; } (@{$settings->{'private'}{'keys'}});
1.267 raeburn 5324: }
5325: }
5326: }
5327: }
1.421 raeburn 5328: } elsif ($position eq 'middle') {
5329: if (exists($settings->{'rules'})) {
5330: if (ref($settings->{'rules'}) eq 'HASH') {
5331: %rules = %{$settings->{'rules'}};
1.273 raeburn 5332: }
5333: }
1.421 raeburn 5334: } else {
5335: foreach my $key ('encrypt','private','rules') {
5336: if (exists($settings->{$key})) {
5337: delete($settings->{$key});
1.267 raeburn 5338: }
5339: }
5340: }
5341: }
1.421 raeburn 5342: my $datatable;
5343: my $itemcount = 1;
5344: if ($position eq 'top') {
5345: $datatable = &secrets_form($dom,'toolsec',\%encrypt,\%privkeys,$rowtotal);
5346: } elsif ($position eq 'middle') {
5347: $datatable = &password_rules('toolsecrets',\$itemcount,\%rules);
5348: $$rowtotal += $itemcount;
5349: } else {
5350: $datatable = &Apache::courseprefs::print_ltitools($dom,'',$settings,\$rowtotal,'','','domain');
1.267 raeburn 5351: }
5352: return $datatable;
5353: }
5354:
5355: sub ltitools_names {
5356: my %lt = &Apache::lonlocal::texthash(
1.296 raeburn 5357: 'title' => 'Title',
5358: 'version' => 'Version',
5359: 'msgtype' => 'Message Type',
1.323 raeburn 5360: 'sigmethod' => 'Signature Method',
1.296 raeburn 5361: 'url' => 'URL',
5362: 'key' => 'Key',
1.322 raeburn 5363: 'lifetime' => 'Nonce lifetime (s)',
1.296 raeburn 5364: 'secret' => 'Secret',
1.425 raeburn 5365: 'icon' => 'Icon',
1.324 raeburn 5366: 'user' => 'User',
1.296 raeburn 5367: 'fullname' => 'Full Name',
5368: 'firstname' => 'First Name',
5369: 'lastname' => 'Last Name',
5370: 'email' => 'E-mail',
5371: 'roles' => 'Role',
1.298 raeburn 5372: 'window' => 'Window',
5373: 'tab' => 'Tab',
1.296 raeburn 5374: 'iframe' => 'iFrame',
5375: 'height' => 'Height',
5376: 'width' => 'Width',
5377: 'linktext' => 'Default Link Text',
5378: 'explanation' => 'Default Explanation',
5379: 'passback' => 'Tool can return grades:',
5380: 'roster' => 'Tool can retrieve roster:',
5381: 'crstarget' => 'Display target',
5382: 'crslabel' => 'Course label',
1.425 raeburn 5383: 'crstitle' => 'Course title',
1.296 raeburn 5384: 'crslinktext' => 'Link Text',
5385: 'crsexplanation' => 'Explanation',
1.318 raeburn 5386: 'crsappend' => 'Provider URL',
1.267 raeburn 5387: );
5388: return %lt;
5389: }
5390:
1.421 raeburn 5391: sub secrets_form {
5392: my ($dom,$context,$encrypt,$privkeys,$rowtotal) = @_;
5393: my @ids=&Apache::lonnet::current_machine_ids();
5394: my %servers = &Apache::lonnet::get_servers($dom,'library');
5395: my $primary = &Apache::lonnet::domain($dom,'primary');
5396: my ($css_class,$extra,$numshown,$itemcount,$output);
5397: $itemcount = 0;
5398: foreach my $hostid (sort(keys(%servers))) {
5399: my ($showextra,$divsty,$switch);
5400: if ($hostid eq $primary) {
5401: if ($context eq 'ltisec') {
5402: if (($encrypt->{'ltisec_consumers'}) || ($encrypt->{'ltisec_domlinkprot'})) {
5403: $showextra = 1;
5404: }
5405: if ($encrypt->{'ltisec_crslinkprot'}) {
5406: $showextra = 1;
5407: }
5408: } else {
5409: if (($encrypt->{'toolsec_crs'}) || ($encrypt->{'toolsec_dom'})) {
5410: $showextra = 1;
5411: }
5412: }
5413: unless (grep(/^\Q$hostid\E$/,@ids)) {
5414: $switch = 1;
5415: }
5416: if ($showextra) {
5417: $numshown ++;
5418: $divsty = 'display:inline-block';
5419: } else {
5420: $divsty = 'display:none';
5421: }
5422: $extra .= '<fieldset id="'.$context.'_info_'.$hostid.'" style="'.$divsty.'">'.
5423: '<legend>'.$hostid.'</legend>';
5424: if ($switch) {
5425: my $switchserver = '<a href="/adm/switchserver?otherserver='.$hostid.'&role='.
5426: &HTML::Entities::encode($env{'request.role'},'\'<>"&').
5427: '&destinationurl=/adm/domainprefs">'.&mt('Switch Server').'</a>';
5428: if (exists($privkeys->{$hostid})) {
5429: $extra .= '<div id="'.$context.'_divcurrprivkey_'.$hostid.'" style="display:inline-block" />'.
5430: '<span class="LC_nobreak">'.
5431: &mt('Encryption Key').': ['.&mt('not shown').'] '.(' 'x2).'</span></div>'.
5432: '<span class="LC_nobreak">'.&mt('Change?').
5433: '<label><input type="radio" value="0" name="'.$context.'_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$context','$hostid'".');" checked="checked" />'.&mt('No').'</label>'.
5434: (' 'x2).
5435: '<label><input type="radio" value="1" name="'.$context.'_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$context','$hostid'".');" />'.&mt('Yes').
5436: '</label> </span><div id="'.$context.'_divchgprivkey_'.$hostid.'" style="display:none" />'.
5437: '<span class="LC_nobreak"> - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).
5438: '</span></div>';
5439: } else {
5440: $extra .= '<span class="LC_nobreak">'.
5441: &mt('Key required').' - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).
5442: '</span>'."\n";
5443: }
5444: } elsif (exists($privkeys->{$hostid})) {
5445: $extra .= '<div id="'.$context.'_divcurrprivkey_'.$hostid.'" style="display:inline-block" /><span class="LC_nobreak">'.
5446: &mt('Encryption Key').': ['.&mt('not shown').'] '.(' 'x2).'</span></div>'.
5447: '<span class="LC_nobreak">'.&mt('Change?').
5448: '<label><input type="radio" value="0" name="'.$context.'_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$context','$hostid'".');" checked="checked" />'.&mt('No').'</label>'.
5449: (' 'x2).
5450: '<label><input type="radio" value="1" name="'.$context.'_changeprivkey_'.$hostid.'" onclick="javascript:togglePrivKey(this.form,'."'$context','$hostid'".');" />'.&mt('Yes').
5451: '</label> </span><div id="'.$context.'_divchgprivkey_'.$hostid.'" style="display:none" />'.
5452: '<span class="LC_nobreak">'.&mt('New Key').':'.
5453: '<input type="password" size="20" name="'.$context.'_privkey_'.$hostid.'" value="" autocomplete="new-password" />'.
5454: '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.'.$context.'_privkey_'.$hostid.'.type='."'text'".' } else { this.form.'.$context.'_privkey_'.$hostid.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.
5455: '</span></div>';
5456: } else {
5457: $extra .= '<span class="LC_nobreak">'.&mt('Encryption Key').':'.
5458: '<input type="password" size="20" name="'.$context.'_privkey_'.$hostid.'" value="" autocomplete="new-password" />'.
5459: '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.'.$context.'_privkey_'.$hostid.'.type='."'text'".' } else { this.form.'.$context.'_privkey_'.$hostid.'.type='."'password'".' }" />'.&mt('Visible input').'</label>';
5460: }
5461: $extra .= '</fieldset>';
5462: }
5463: }
5464: my (%choices,@toggles,%defaultchecked);
5465: if ($context eq 'ltisec') {
5466: %choices = &Apache::lonlocal::texthash (
5467: ltisec_crslinkprot => 'Encrypt stored link protection secrets defined in courses',
5468: ltisec_domlinkprot => 'Encrypt stored link protection secrets defined in domain',
5469: ltisec_consumers => 'Encrypt stored consumer secrets defined in domain',
5470: );
5471: @toggles = qw(ltisec_crslinkprot ltisec_domlinkprot ltisec_consumers);
5472: %defaultchecked = (
5473: 'ltisec_crslinkprot' => 'off',
5474: 'ltisec_domlinkprot' => 'off',
5475: 'ltisec_consumers' => 'off',
5476: );
5477: } else {
5478: %choices = &Apache::lonlocal::texthash (
5479: toolsec_crs => 'Encrypt stored external tool secrets defined in courses',
5480: toolsec_dom => 'Encrypt stored external tool secrets defined in domain',
5481: );
5482: @toggles = qw(toolsec_crs toolsec_dom);
5483: %defaultchecked = (
5484: 'toolsec_crs' => 'off',
5485: 'toolsec_dom' => 'off',
5486: );
5487: }
5488: my ($onclick,$itemcount);
5489: $onclick = 'javascript:toggleLTIEncKey(this.form,'."'$context'".');';
5490: ($output,$itemcount) = &radiobutton_prefs($encrypt,\@toggles,\%defaultchecked,
5491: \%choices,$itemcount,$onclick,'','left','no');
5492:
5493: $css_class = $itemcount%2?' class="LC_odd_row"':'';
5494: my $noprivkeysty = 'display:inline-block';
5495: if ($numshown) {
5496: $noprivkeysty = 'display:none';
5497: }
5498: $output .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.&mt('Encryption Key(s)').'</td>'.
5499: '<td><div id="'.$context.'_noprivkey" style="'.$noprivkeysty.'" >'.
5500: '<span class="LC_nobreak">'.&mt('Not in use').'</span></div>'.
5501: $extra.
5502: '</td></tr>';
5503: $itemcount ++;
5504: $$rowtotal += $itemcount;
5505: return $output;
5506: }
5507:
1.372 raeburn 5508: sub print_proctoring {
5509: my ($dom,$settings,$rowtotal) = @_;
5510: my $itemcount = 1;
5511: my (%ordered,%providernames,%current,%currentdef);
5512: my $confname = $dom.'-domainconfig';
5513: my $switchserver = &check_switchserver($dom,$confname);
5514: if (ref($settings) eq 'HASH') {
5515: foreach my $item (keys(%{$settings})) {
5516: if (ref($settings->{$item}) eq 'HASH') {
5517: my $num = $settings->{$item}{'order'};
5518: $ordered{$num} = $item;
5519: }
5520: }
5521: } else {
5522: %ordered = (
5523: 1 => 'proctorio',
5524: 2 => 'examity',
5525: );
5526: }
5527: %providernames = &proctoring_providernames();
5528: my $maxnum = scalar(keys(%ordered));
5529: my (%requserfields,%optuserfields,%defaults,%extended,%crsconf,@courseroles,@ltiroles);
5530: my ($requref,$opturef,$defref,$extref,$crsref,$rolesref,$ltiref) = &proctoring_data();
5531: if (ref($requref) eq 'HASH') {
5532: %requserfields = %{$requref};
5533: }
5534: if (ref($opturef) eq 'HASH') {
5535: %optuserfields = %{$opturef};
5536: }
5537: if (ref($defref) eq 'HASH') {
5538: %defaults = %{$defref};
5539: }
5540: if (ref($extref) eq 'HASH') {
5541: %extended = %{$extref};
5542: }
5543: if (ref($crsref) eq 'HASH') {
5544: %crsconf = %{$crsref};
5545: }
5546: if (ref($rolesref) eq 'ARRAY') {
5547: @courseroles = @{$rolesref};
5548: }
5549: if (ref($ltiref) eq 'ARRAY') {
5550: @ltiroles = @{$ltiref};
5551: }
5552: my $datatable;
5553: my $css_class;
5554: if (keys(%ordered)) {
5555: my @items = sort { $a <=> $b } keys(%ordered);
5556: for (my $i=0; $i<@items; $i++) {
5557: $css_class = $itemcount%2?' class="LC_odd_row"':'';
5558: my $provider = $ordered{$items[$i]};
5559: my $optionsty = 'none';
5560: my ($available,$version,$lifetime,$imgsrc,$userincdom,$showroles,
5561: %checkedfields,%rolemaps,%inuse,%crsconfig,%current);
5562: if (ref($settings) eq 'HASH') {
5563: if (ref($settings->{$provider}) eq 'HASH') {
5564: %current = %{$settings->{$provider}};
5565: if ($current{'available'}) {
5566: $optionsty = 'block';
5567: $available = 1;
5568: }
5569: if ($current{'lifetime'} =~ /^\d+$/) {
5570: $lifetime = $current{'lifetime'};
5571: }
5572: if ($current{'version'} =~ /^\d+\.\d+$/) {
5573: $version = $current{'version'};
5574: }
5575: if ($current{'image'} ne '') {
5576: $imgsrc = '<img src="'.$current{'image'}.'" alt="'.&mt('Proctoring service icon').'" />';
5577: }
5578: if (ref($current{'fields'}) eq 'ARRAY') {
5579: map { $checkedfields{$_} = 1; } @{$current{'fields'}};
5580: }
5581: $userincdom = $current{'incdom'};
5582: if (ref($current{'roles'}) eq 'HASH') {
5583: %rolemaps = %{$current{'roles'}};
5584: $checkedfields{'roles'} = 1;
5585: }
5586: if (ref($current{'defaults'}) eq 'ARRAY') {
5587: foreach my $val (@{$current{'defaults'}}) {
5588: if (grep(/^\Q$val\E$/,@{$defaults{$provider}})) {
5589: $inuse{$val} = 1;
5590: } else {
5591: foreach my $poss (keys(%{$extended{$provider}})) {
5592: if (ref($extended{$provider}{$poss}) eq 'ARRAY') {
5593: if (grep(/^\Q$val\E$/,@{$extended{$provider}{$poss}})) {
5594: $inuse{$poss} = $val;
5595: last;
5596: }
5597: }
5598: }
5599: }
5600: }
5601: } elsif (ref($current{'defaults'}) eq 'HASH') {
5602: foreach my $key (keys(%{$current{'defaults'}})) {
5603: my $currval = $current{'defaults'}{$key};
5604: if (grep(/^\Q$key\E$/,@{$defaults{$provider}})) {
5605: $inuse{$key} = 1;
5606: } else {
5607: my $match;
5608: foreach my $poss (keys(%{$extended{$provider}})) {
5609: if (ref($extended{$provider}{$poss}) eq 'ARRAY') {
5610: if (grep(/^\Q$key\E$/,@{$extended{$provider}{$poss}})) {
5611: $inuse{$poss} = $key;
5612: last;
5613: }
5614: } elsif (ref($extended{$provider}{$poss}) eq 'HASH') {
5615: foreach my $inner (sort(keys(%{$extended{$provider}{$poss}}))) {
5616: if (ref($extended{$provider}{$poss}{$inner}) eq 'ARRAY') {
5617: if (grep(/^\Q$currval\E$/,@{$extended{$provider}{$poss}{$inner}})) {
5618: $currentdef{$inner} = $currval;
5619: $match = 1;
5620: last;
5621: }
5622: } elsif ($inner eq $key) {
5623: $currentdef{$key} = $currval;
5624: $match = 1;
5625: last;
5626: }
5627: }
5628: }
5629: last if ($match);
5630: }
5631: }
5632: }
5633: }
5634: if (ref($current{'crsconf'}) eq 'ARRAY') {
5635: map { $crsconfig{$_} = 1; } @{$current{'crsconf'}};
5636: }
5637: }
5638: }
5639: my %lt = &proctoring_titles($provider);
5640: my %fieldtitles = &proctoring_fieldtitles($provider);
5641: my $onclickavailable = ' onclick="toggleProctoring(this.form,'."'$provider'".');"';
5642: my %checkedavailable = (
5643: yes => '',
5644: no => ' checked="checked"',
5645: );
5646: if ($available) {
5647: $checkedavailable{'yes'} = $checkedavailable{'no'};
5648: $checkedavailable{'no'} = '';
5649: }
5650: my $chgstr = ' onchange="javascript:reorderProctoring(this.form,'."'proctoring_pos_".$provider."'".');"';
5651: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
5652: .'<select name="proctoring_pos_'.$provider.'"'.$chgstr.'>';
5653: for (my $k=0; $k<$maxnum; $k++) {
5654: my $vpos = $k+1;
5655: my $selstr;
5656: if ($k == $i) {
5657: $selstr = ' selected="selected" ';
5658: }
5659: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
5660: }
5661: if ($version eq '') {
5662: if ($provider eq 'proctorio') {
5663: $version = '1.0';
5664: } elsif ($provider eq 'examity') {
5665: $version = '1.1';
5666: }
5667: }
5668: if ($lifetime eq '') {
5669: $lifetime = '300';
5670: }
5671: $datatable .=
5672: '</select>'.(' 'x2).'<b>'.$providernames{$provider}.'</b></span><br />'.
5673: '<span class="LC_nobreak">'.$lt{'avai'}.' '.
5674: '<label><input type="radio" name="proctoring_available_'.$provider.'" value="1"'.$onclickavailable.$checkedavailable{yes}.' />'.&mt('Yes').'</label> '."\n".
5675: '<label><input type="radio" name="proctoring_available_'.$provider.'" value="0"'.$onclickavailable.$checkedavailable{no}.' />'.&mt('No').'</label></span>'."\n".
5676: '</td>'.
5677: '<td colspan="2">'.
5678: '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'base'}.'</legend>'.
5679: '<span class="LC_nobreak">'.$lt{'version'}.':<select name="proctoring_'.$provider.'_version">'.
5680: '<option value="'.$version.'" selected="selected">'.$version.'</option></select></span> '."\n".
5681: (' 'x2).
5682: '<span class="LC_nobreak">'.$lt{'sigmethod'}.':<select name="proctoring_'.$provider.'_sigmethod">'.
5683: '<option value="HMAC-SHA1" selected="selected">HMAC-SHA1</option>'.
5684: '<option value="HMAC-SHA256">HMAC-SHA256</option></select></span>'.
5685: (' 'x2).
5686: '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="5" name="proctoring_'.$provider.'_lifetime" value="'.$lifetime.'" /></span> '."\n".
5687: '<br />'.
5688: '<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="40" name="proctoring_'.$provider.'_url" value="'.$current{'url'}.'" /></span> '."\n".
5689: '<br />'.
5690: '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="proctoring_'.$provider.'_key" value="'.$current{'key'}.'" /></span> '."\n".
5691: (' 'x2).
5692: '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="proctoring_'.$provider.'_secret" value="'.$current{'secret'}.'" />'.
5693: '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.proctoring_'.$provider.'_secret.type='."'text'".' } else { this.form.proctoring_'.$provider.'_secret.type='."'password'".' }" />'.$lt{'visible'}.'</label></span><br />'."\n";
5694: $datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.': ';
5695: if ($imgsrc) {
5696: $datatable .= $imgsrc.
5697: '<label><input type="checkbox" name="proctoring_image_del"'.
5698: ' value="'.$provider.'" />'.&mt('Delete?').'</label></span> '.
5699: '<span class="LC_nobreak"> '.&mt('Replace:');
5700: }
5701: $datatable .= ' ';
5702: if ($switchserver) {
5703: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
5704: } else {
5705: $datatable .= '<input type="file" name="proctoring_image_'.$provider.'" value="" />';
5706: }
5707: unless ($imgsrc) {
5708: $datatable .= '<br />('.&mt('if larger than 21x21 pixels, image will be scaled').')';
5709: }
5710: $datatable .= '</fieldset>'."\n";
5711: if (ref($requserfields{$provider}) eq 'ARRAY') {
5712: if (@{$requserfields{$provider}} > 0) {
5713: $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'requ'}.'</legend>';
5714: foreach my $field (@{$requserfields{$provider}}) {
5715: $datatable .= '<span class="LC_nobreak">'.
5716: '<label><input type="checkbox" name="proctoring_reqd_'.$provider.'" value="'.$field.'" checked="checked" disabled="disabled" />'.
5717: $lt{$field}.'</label>';
5718: if ($field eq 'user') {
5719: my $seluserdom = '';
5720: my $unseluserdom = ' selected="selected"';
5721: if ($userincdom) {
5722: $seluserdom = $unseluserdom;
5723: $unseluserdom = '';
5724: }
5725: $datatable .= ': '.
5726: '<select name="proctoring_userincdom_'.$provider.'">'.
5727: '<option value="0"'.$unseluserdom.'>'.$lt{'username'}.'</option>'.
5728: '<option value="1"'.$seluserdom.'>'.$lt{'uname:dom'}.'</option>'.
5729: '</select> ';
5730: } else {
5731: $datatable .= ' ';
5732: if ($field eq 'roles') {
5733: $showroles = 1;
5734: }
5735: }
5736: $datatable .= '</span> ';
5737: }
5738: }
5739: $datatable .= '</fieldset>'."\n";
5740: }
5741: if (ref($optuserfields{$provider}) eq 'ARRAY') {
5742: if (@{$optuserfields{$provider}} > 0) {
5743: $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'optu'}.'</legend>';
5744: foreach my $field (@{$optuserfields{$provider}}) {
5745: my $checked;
5746: if ($checkedfields{$field}) {
5747: $checked = ' checked="checked"';
5748: }
5749: $datatable .= '<span class="LC_nobreak">'.
5750: '<label><input type="checkbox" name="proctoring_optional_'.$provider.'" value="'.$field.'"'.$checked.' />'.$lt{$field}.'</label></span> ';
5751: }
5752: $datatable .= '</fieldset>'."\n";
5753: }
5754: }
5755: if (ref($defaults{$provider}) eq 'ARRAY') {
5756: if (@{$defaults{$provider}}) {
5757: my (%options,@selectboxes);
5758: if (ref($extended{$provider}) eq 'HASH') {
5759: %options = %{$extended{$provider}};
5760: }
5761: $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'defa'}.'</legend>';
5762: my ($rem,$numinrow,$dropdowns);
5763: if ($provider eq 'proctorio') {
5764: $datatable .= '<table>';
5765: $numinrow = 4;
5766: }
5767: my $i = 0;
5768: foreach my $field (@{$defaults{$provider}}) {
5769: my $checked;
5770: if ($inuse{$field}) {
5771: $checked = ' checked="checked"';
5772: }
5773: if ($provider eq 'examity') {
5774: if ($field eq 'display') {
5775: $datatable .= '<span class="LC_nobreak">'.&mt('Display target:');
5776: foreach my $option ('iframe','tab','window') {
5777: my $checkdisp;
5778: if ($currentdef{'target'} eq $option) {
5779: $checkdisp = ' checked="checked"';
5780: }
5781: $datatable .= '<label><input type="radio" name="proctoring_target_'.$provider.'" value="'.$option.'"'.$checkdisp.' />'.
5782: $fieldtitles{$option}.'</label>'.(' 'x2);
5783: }
5784: $datatable .= (' 'x4);
5785: foreach my $dimen ('width','height') {
5786: $datatable .= '<label>'.$fieldtitles{$dimen}.' '.
5787: '<input type="text" name="proctoring_'.$dimen.'_'.$provider.'" size="5" '.
5788: 'value="'.$currentdef{$dimen}.'" /></label>'.
5789: (' 'x2);
5790: }
5791: $datatable .= '</span><br />'.
5792: '<div class="LC_left_float">'.$fieldtitles{'linktext'}.'<br />'.
5793: '<input type="text" name="proctoring_linktext_'.$provider.'" '.
5794: 'size="25" value="'.$currentdef{'linktext'}.'" /></div>'.
5795: '<div class="LC_left_float">'.$fieldtitles{'explanation'}.'<br />'.
5796: '<textarea name="proctoring_explanation_'.$provider.'" rows="5" cols="40">'.
5797: $currentdef{'explanation'}.
5798: '</textarea></div><div style=""></div><br />';
5799: }
5800: } else {
5801: if ((exists($options{$field})) && (ref($options{$field}) eq 'ARRAY')) {
5802: my ($output,$selnone);
5803: unless ($checked) {
5804: $selnone = ' selected="selected"';
5805: }
5806: $output .= '<span class="LC_nobreak">'.$fieldtitles{$field}.': '.
5807: '<select name="proctoring_defaults_'.$field.'_'.$provider.'">'.
5808: '<option value=""'.$selnone.'>'.&mt('Not in use').'</option>';
5809: foreach my $option (@{$options{$field}}) {
5810: my $sel;
5811: if ($inuse{$field} eq $option) {
5812: $sel = ' selected="selected"';
5813: }
5814: $output .= '<option value="'.$option.'"'.$sel.'>'.$fieldtitles{$option}.'</option>';
5815: }
5816: $output .= '</select></span>';
5817: push(@selectboxes,$output);
5818: } else {
5819: $rem = $i%($numinrow);
5820: if ($rem == 0) {
5821: if ($i > 0) {
5822: $datatable .= '</tr>';
5823: }
5824: $datatable .= '<tr>';
5825: }
5826: $datatable .= '<td class="LC_left_item">'.
5827: '<span class="LC_nobreak">'.
5828: '<label><input type="checkbox" name="proctoring_defaults_'.$provider.'" value="'.$field.'"'.$checked.' />'.
5829: $fieldtitles{$field}.'</label></span></td>';
5830: $i++;
5831: }
5832: }
5833: }
5834: if ($provider eq 'proctorio') {
5835: if ($numinrow) {
5836: $rem = $i%$numinrow;
5837: }
5838: my $colsleft = $numinrow - $rem;
5839: if ($colsleft > 1) {
5840: $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
5841: } else {
5842: $datatable .= '<td class="LC_left_item">';
5843: }
5844: $datatable .= ' '.
5845: '</td></tr></table>';
5846: if (@selectboxes) {
5847: $datatable .= '<hr /><table>';
5848: $numinrow = 2;
5849: for (my $i=0; $i<@selectboxes; $i++) {
5850: $rem = $i%($numinrow);
5851: if ($rem == 0) {
5852: if ($i > 0) {
5853: $datatable .= '</tr>';
5854: }
5855: $datatable .= '<tr>';
5856: }
5857: $datatable .= '<td class="LC_left_item">'.
5858: $selectboxes[$i].'</td>';
5859: }
5860: if ($numinrow) {
5861: $rem = $i%$numinrow;
5862: }
5863: $colsleft = $numinrow - $rem;
5864: if ($colsleft > 1) {
5865: $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
5866: } else {
5867: $datatable .= '<td class="LC_left_item">';
5868: }
5869: $datatable .= ' '.
5870: '</td></tr></table>';
5871: }
5872: }
5873: $datatable .= '</fieldset>';
5874: }
5875: if (ref($crsconf{$provider}) eq 'ARRAY') {
5876: $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'.
5877: '<legend>'.&mt('Configurable in course').'</legend>';
5878: my ($rem,$numinrow);
5879: if ($provider eq 'proctorio') {
5880: $datatable .= '<table>';
5881: $numinrow = 4;
5882: }
5883: my $i = 0;
5884: foreach my $item (@{$crsconf{$provider}}) {
5885: my $name;
5886: if ($provider eq 'examity') {
5887: $name = $lt{'crs'.$item};
5888: } elsif ($provider eq 'proctorio') {
5889: $name = $fieldtitles{$item};
5890: $rem = $i%($numinrow);
5891: if ($rem == 0) {
5892: if ($i > 0) {
5893: $datatable .= '</tr>';
5894: }
5895: $datatable .= '<tr>';
5896: }
5897: $datatable .= '<td class="LC_left_item>';
5898: }
5899: my $checked;
5900: if ($crsconfig{$item}) {
5901: $checked = ' checked="checked"';
5902: }
5903: $datatable .= '<span class="LC_nobreak"><label>'.
5904: '<input type="checkbox" name="proctoring_crsconf_'.$provider.'" value="'.$item.'"'.$checked.' />'.
5905: $name.'</label></span>';
5906: if ($provider eq 'examity') {
5907: $datatable .= ' ';
5908: }
5909: $datatable .= "\n";
5910: $i++;
5911: }
5912: if ($provider eq 'proctorio') {
5913: if ($numinrow) {
5914: $rem = $i%$numinrow;
5915: }
5916: my $colsleft = $numinrow - $rem;
5917: if ($colsleft > 1) {
5918: $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
5919: } else {
5920: $datatable .= '<td class="LC_left_item">';
5921: }
5922: $datatable .= ' '.
5923: '</td></tr></table>';
5924: }
5925: $datatable .= '</fieldset>';
5926: }
5927: if ($showroles) {
5928: $datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'.
5929: '<legend>'.&mt('Role mapping').'</legend><table><tr>';
5930: foreach my $role (@courseroles) {
5931: my ($selected,$selectnone);
5932: if (!$rolemaps{$role}) {
5933: $selectnone = ' selected="selected"';
5934: }
5935: $datatable .= '<td style="text-align: center">'.
5936: &Apache::lonnet::plaintext($role,'Course').'<br />'.
5937: '<select name="proctoring_roles_'.$role.'_'.$provider.'">'.
5938: '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
5939: foreach my $ltirole (@ltiroles) {
5940: unless ($selectnone) {
5941: if ($rolemaps{$role} eq $ltirole) {
5942: $selected = ' selected="selected"';
5943: } else {
5944: $selected = '';
5945: }
5946: }
5947: $datatable .= '<option value="'.$ltirole.'"'.$selected.'>'.$ltirole.'</option>';
5948: }
5949: $datatable .= '</select></td>';
5950: }
5951: $datatable .= '</tr></table></fieldset>'.
5952: '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'.
5953: '<legend>'.&mt('Custom items sent on launch').'</legend>'.
5954: '<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>'.
5955: '<tr><td></td><td>lms</td>'.
5956: '<td><input type="text" name="proctoring_customval_lms_'.$provider.'"'.
5957: ' value="Loncapa" disabled="disabled"/></td></tr>';
5958: if ((ref($settings) eq 'HASH') && (ref($settings->{$provider}) eq 'HASH') &&
5959: (ref($settings->{$provider}->{'custom'}) eq 'HASH')) {
5960: my %custom = %{$settings->{$provider}->{'custom'}};
5961: if (keys(%custom) > 0) {
5962: foreach my $key (sort(keys(%custom))) {
5963: next if ($key eq 'lms');
5964: $datatable .= '<tr><td><span class="LC_nobreak">'.
5965: '<label><input type="checkbox" name="proctoring_customdel_'.$provider.'" value="'.
5966: $key.'" />'.&mt('Delete').'</label></span></td><td>'.$key.'</td>'.
5967: '<td><input type="text" name="proctoring_customval_'.$key.'_'.$provider.'"'.
5968: ' value="'.$custom{$key}.'" /></td></tr>';
5969: }
5970: }
5971: }
5972: $datatable .= '<tr><td><span class="LC_nobreak">'.
5973: '<label><input type="checkbox" name="proctoring_customadd" value="'.$provider.'" />'.
5974: &mt('Add more').'</label></span></td><td><input type="text" name="proctoring_custom_name_'.$provider.'" />'.
5975: '</td><td><input type="text" name="proctoring_custom_value_'.$provider.'" /></td></tr>'.
5976: '</table></fieldset></td></tr>'."\n";
5977: }
5978: $datatable .= '</td></tr>';
5979: }
5980: $itemcount ++;
5981: }
5982: }
5983: return $datatable;
5984: }
5985:
5986: sub proctoring_data {
5987: my $requserfields = {
5988: proctorio => ['user'],
5989: examity => ['roles','user'],
5990: };
5991: my $optuserfields = {
5992: proctorio => ['fullname'],
5993: examity => ['fullname','firstname','lastname','email'],
5994: };
5995: my $defaults = {
5996: proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic',
5997: 'recordroomstart','verifyvideo','verifyaudio','verifydesktop',
5998: 'verifyid','verifysignature','fullscreen','clipboard','tabslinks',
5999: 'closetabs','onescreen','print','downloads','cache','rightclick',
6000: 'reentry','calculator','whiteboard'],
6001: examity => ['display'],
6002: };
6003: my $extended = {
6004: proctorio => {
6005: verifyid => ['verifyidauto','verifyidlive'],
6006: fullscreen => ['fullscreenlenient','fullscreenmoderate','fullscreensever'],
6007: tabslinks => ['notabs','linksonly'],
6008: reentry => ['noreentry','agentreentry'],
6009: calculator => ['calculatorbasic','calculatorsci'],
6010: },
6011: examity => {
6012: display => {
6013: target => ['iframe','tab','window'],
6014: width => '',
6015: height => '',
6016: linktext => '',
6017: explanation => '',
6018: },
6019: },
6020: };
6021: my $crsconf = {
6022: proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic',
6023: 'recordroomstart','verifyvideo','verifyaudio','verifydesktop',
6024: 'verifyid','verifysignature','fullscreen','clipboard','tabslinks',
6025: 'closetabs','onescreen','print','downloads','cache','rightclick',
6026: 'reentry','calculator','whiteboard'],
6027: examity => ['label','title','target','linktext','explanation','append'],
6028: };
6029: my $courseroles = ['cc','in','ta','ep','st'];
6030: my $ltiroles = ['Instructor','ContentDeveloper','TeachingAssistant','Learner'];
6031: return ($requserfields,$optuserfields,$defaults,$extended,$crsconf,$courseroles,$ltiroles);
6032: }
6033:
6034: sub proctoring_titles {
6035: my ($item) = @_;
6036: my (%common_lt,%custom_lt);
6037: %common_lt = &Apache::lonlocal::texthash (
6038: 'avai' => 'Available?',
6039: 'base' => 'Basic Settings',
6040: 'requ' => 'User data required to be sent on launch',
6041: 'optu' => 'User data optionally sent on launch',
6042: 'udsl' => 'User data sent on launch',
6043: 'defa' => 'Defaults for items configurable in course',
6044: 'sigmethod' => 'Signature Method',
6045: 'key' => 'Key',
6046: 'lifetime' => 'Nonce lifetime (s)',
6047: 'secret' => 'Secret',
6048: 'icon' => 'Icon',
6049: 'fullname' => 'Full Name',
6050: 'visible' => 'Visible input',
6051: 'username' => 'username',
6052: 'user' => 'User',
6053: );
6054: if ($item eq 'proctorio') {
6055: %custom_lt = &Apache::lonlocal::texthash (
6056: 'version' => 'OAuth version',
6057: 'url' => 'API URL',
6058: 'uname:dom' => 'username-domain',
6059: );
6060: } elsif ($item eq 'examity') {
6061: %custom_lt = &Apache::lonlocal::texthash (
6062: 'version' => 'LTI Version',
6063: 'url' => 'URL',
6064: 'uname:dom' => 'username:domain',
6065: 'msgtype' => 'Message Type',
6066: 'firstname' => 'First Name',
6067: 'lastname' => 'Last Name',
6068: 'email' => 'E-mail',
6069: 'roles' => 'Role',
6070: 'crstarget' => 'Display target',
6071: 'crslabel' => 'Course label',
6072: 'crstitle' => 'Course title',
6073: 'crslinktext' => 'Link Text',
6074: 'crsexplanation' => 'Explanation',
6075: 'crsappend' => 'Provider URL',
6076: );
6077: }
6078: my %lt = (%common_lt,%custom_lt);
6079: return %lt;
6080: }
6081:
6082: sub proctoring_fieldtitles {
6083: my ($item) = @_;
6084: if ($item eq 'proctorio') {
6085: return &Apache::lonlocal::texthash (
6086: 'recordvideo' => 'Record video',
6087: 'recordaudio' => 'Record audio',
6088: 'recordscreen' => 'Record screen',
6089: 'recordwebtraffic' => 'Record web traffic',
6090: 'recordroomstart' => 'Record room scan',
6091: 'verifyvideo' => 'Verify webcam',
6092: 'verifyaudio' => 'Verify microphone',
6093: 'verifydesktop' => 'Verify desktop recording',
6094: 'verifyid' => 'Photo ID verification',
6095: 'verifysignature' => 'Require signature',
6096: 'fullscreen' => 'Fullscreen',
6097: 'clipboard' => 'Disable copy/paste',
6098: 'tabslinks' => 'New tabs/windows',
6099: 'closetabs' => 'Close other tabs',
6100: 'onescreen' => 'Limit to single screen',
6101: 'print' => 'Disable Printing',
6102: 'downloads' => 'Disable Downloads',
6103: 'cache' => 'Empty cache after exam',
6104: 'rightclick' => 'Disable right click',
6105: 'reentry' => 'Re-entry to exam',
6106: 'calculator' => 'Onscreen calculator',
6107: 'whiteboard' => 'Onscreen whiteboard',
6108: 'verifyidauto' => 'Automated verification',
6109: 'verifyidlive' => 'Live agent verification',
6110: 'fullscreenlenient' => 'Forced, but can navigate away for up to 30s',
6111: 'fullscreenmoderate' => 'Forced, but can navigate away for up to 15s',
6112: 'fullscreensever' => 'Forced, navigation away ends exam',
6113: 'notabs' => 'Disaallowed',
6114: 'linksonly' => 'Allowed from links in exam',
6115: 'noreentry' => 'Disallowed',
6116: 'agentreentry' => 'Agent required for re-entry',
6117: 'calculatorbasic' => 'Basic',
6118: 'calculatorsci' => 'Scientific',
6119: );
6120: } elsif ($item eq 'examity') {
6121: return &Apache::lonlocal::texthash (
6122: 'target' => 'Display target',
6123: 'window' => 'Window',
6124: 'tab' => 'Tab',
6125: 'iframe' => 'iFrame',
6126: 'height' => 'Height (pixels)',
6127: 'width' => 'Width (pixels)',
6128: 'linktext' => 'Default Link Text',
6129: 'explanation' => 'Default Explanation',
6130: 'append' => 'Provider URL',
6131: );
6132: }
6133: }
6134:
6135: sub proctoring_providernames {
6136: return (
6137: proctorio => 'Proctorio',
6138: examity => 'Examity',
6139: );
6140: }
6141:
1.320 raeburn 6142: sub print_lti {
1.405 raeburn 6143: my ($position,$dom,$settings,$rowtotal) = @_;
1.320 raeburn 6144: my $itemcount = 1;
1.405 raeburn 6145: my ($datatable,$css_class);
6146: my (%rules,%encrypt,%privkeys,%linkprot);
1.320 raeburn 6147: if (ref($settings) eq 'HASH') {
1.405 raeburn 6148: if ($position eq 'top') {
6149: if (exists($settings->{'encrypt'})) {
6150: if (ref($settings->{'encrypt'}) eq 'HASH') {
6151: foreach my $key (keys(%{$settings->{'encrypt'}})) {
6152: if ($key eq 'consumers') {
6153: $encrypt{'ltisec_'.$key} = $settings->{'encrypt'}{$key};
6154: } else {
6155: $encrypt{'ltisec_'.$key.'linkprot'} = $settings->{'encrypt'}{$key};
6156: }
6157: }
6158: }
6159: }
6160: if (exists($settings->{'private'})) {
6161: if (ref($settings->{'private'}) eq 'HASH') {
6162: if (ref($settings->{'private'}) eq 'HASH') {
6163: if (ref($settings->{'private'}{'keys'}) eq 'ARRAY') {
6164: map { $privkeys{$_} = 1; } (@{$settings->{'private'}{'keys'}});
6165: }
6166: }
6167: }
6168: }
6169: } elsif ($position eq 'middle') {
6170: if (exists($settings->{'rules'})) {
6171: if (ref($settings->{'rules'}) eq 'HASH') {
6172: %rules = %{$settings->{'rules'}};
6173: }
6174: }
6175: } elsif ($position eq 'lower') {
6176: if (exists($settings->{'linkprot'})) {
6177: if (ref($settings->{'linkprot'}) eq 'HASH') {
6178: %linkprot = %{$settings->{'linkprot'}};
1.406 raeburn 6179: if ($linkprot{'lock'}) {
6180: delete($linkprot{'lock'});
6181: }
1.405 raeburn 6182: }
6183: }
6184: } else {
6185: foreach my $key ('encrypt','private','rules','linkprot') {
6186: if (exists($settings->{$key})) {
6187: delete($settings->{$key});
1.390 raeburn 6188: }
1.320 raeburn 6189: }
6190: }
6191: }
1.405 raeburn 6192: if ($position eq 'top') {
1.421 raeburn 6193: $datatable = &secrets_form($dom,'ltisec',\%encrypt,\%privkeys,$rowtotal);
6194: } elsif ($position eq 'middle') {
6195: $datatable = &password_rules('ltisecrets',\$itemcount,\%rules);
6196: $$rowtotal += $itemcount;
6197: } elsif ($position eq 'lower') {
6198: $datatable .= &Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain');
6199: } else {
1.424 raeburn 6200: my ($switchserver,$switchmessage);
6201: $switchserver = &check_switchserver($dom);
6202: $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver);
1.421 raeburn 6203: my $maxnum = 0;
6204: my %ordered;
6205: if (ref($settings) eq 'HASH') {
6206: foreach my $item (keys(%{$settings})) {
6207: if (ref($settings->{$item}) eq 'HASH') {
6208: my $num = $settings->{$item}{'order'};
6209: if ($num eq '') {
6210: $num = scalar(keys(%{$settings}));
6211: }
6212: $ordered{$num} = $item;
1.405 raeburn 6213: }
1.352 raeburn 6214: }
1.405 raeburn 6215: }
6216: $maxnum = scalar(keys(%ordered));
6217: my %lt = <i_names();
6218: if (keys(%ordered)) {
6219: my @items = sort { $a <=> $b } keys(%ordered);
6220: for (my $i=0; $i<@items; $i++) {
6221: $css_class = $itemcount%2?' class="LC_odd_row"':'';
6222: my $item = $ordered{$items[$i]};
1.424 raeburn 6223: my ($key,$secret,$usable,$lifetime,$consumer,$requser,$crsinc,$current);
1.405 raeburn 6224: if (ref($settings->{$item}) eq 'HASH') {
6225: $key = $settings->{$item}->{'key'};
1.424 raeburn 6226: $usable = $settings->{$item}->{'usable'};
1.405 raeburn 6227: $lifetime = $settings->{$item}->{'lifetime'};
6228: $consumer = $settings->{$item}->{'consumer'};
6229: $requser = $settings->{$item}->{'requser'};
6230: $crsinc = $settings->{$item}->{'crsinc'};
6231: $current = $settings->{$item};
6232: }
6233: my $onclickrequser = ' onclick="toggleLTI(this.form,'."'requser','$i'".');"';
6234: my %checkedrequser = (
6235: yes => ' checked="checked"',
6236: no => '',
6237: );
6238: if (!$requser) {
6239: $checkedrequser{'no'} = $checkedrequser{'yes'};
6240: $checkedrequser{'yes'} = '';
6241: }
6242: my $onclickcrsinc = ' onclick="toggleLTI(this.form,'."'crsinc','$i'".');"';
6243: my %checkedcrsinc = (
1.391 raeburn 6244: yes => ' checked="checked"',
6245: no => '',
1.405 raeburn 6246: );
6247: if (!$crsinc) {
6248: $checkedcrsinc{'no'} = $checkedcrsinc{'yes'};
6249: $checkedcrsinc{'yes'} = '';
6250: }
6251: my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'lti_pos_".$item."'".');"';
6252: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
6253: .'<select name="lti_pos_'.$item.'"'.$chgstr.'>';
6254: for (my $k=0; $k<=$maxnum; $k++) {
6255: my $vpos = $k+1;
6256: my $selstr;
6257: if ($k == $i) {
6258: $selstr = ' selected="selected" ';
6259: }
6260: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
1.320 raeburn 6261: }
1.405 raeburn 6262: $datatable .= '</select>'.(' 'x2).
6263: '<label><input type="checkbox" name="lti_del" value="'.$item.'" />'.
6264: &mt('Delete?').'</label></span></td>'.
6265: '<td colspan="2">'.
6266: '<fieldset><legend>'.&mt('Required settings').'</legend>'.
6267: '<span class="LC_nobreak">'.$lt{'consumer'}.
6268: ':<input type="text" size="15" name="lti_consumer_'.$i.'" value="'.$consumer.'" /></span> '.
6269: (' 'x2).
6270: '<span class="LC_nobreak">'.$lt{'version'}.':<select name="lti_version_'.$i.'">'.
6271: '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '.
6272: (' 'x2).
6273: '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" name="lti_lifetime_'.$i.'"'.
1.424 raeburn 6274: 'value="'.$lifetime.'" size="3" /></span><br /><br />';
6275: if ($key ne '') {
6276: $datatable .= '<span class="LC_nobreak">'.$lt{'key'};
6277: if ($switchserver) {
6278: $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']';
6279: } else {
6280: $datatable .= ':<input type="text" size="25" name="lti_key_'.$i.'" value="'.$key.'" autocomplete="off" />';
6281: }
6282: $datatable .= '</span> '.(' 'x2);
6283: } elsif (!$switchserver) {
6284: $datatable .= '<span class="LC_nobreak">'.$lt{'key'}.':'.
6285: '<input type="text" size="25" name="lti_key_'.$i.'" value="'.$key.'" autocomplete="off" />'.
6286: '</span> '.(' 'x2);
6287: }
6288: if ($switchserver) {
6289: if ($usable ne '') {
6290: $datatable .= '<div id="lti_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
6291: $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'</span></div>'.
6292: '<span class="LC_nobreak">'.&mt('Change secret?').
6293: '<label><input type="radio" value="0" name="lti_changesecret_'.$i.'" onclick="javascript:toggleChgSecret(this.form,'."'$i','secret','lti'".');" checked="checked" />'.&mt('No').'</label>'.
6294: (' 'x2).
6295: '<label><input type="radio" value="1" name="lti_changesecret_'.$i.'" onclick="javascript:toggleChgSecret(this.form,'."'$i','secret','lti'".');" />'.&mt('Yes').'</label>'.(' 'x2).
6296: '</span><div id="lti_divchgsecret_'.$i.'" style="display:none" />'.
6297: '<span class="LC_nobreak"> - '.$switchmessage.'</span>'.
6298: '</div>';
6299: } elsif ($key eq '') {
6300: $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
6301: } else {
6302: $datatable .= '<span class="LC_nobreak">'.&mt('Secret required').' - '.$switchmessage.'</span>'."\n";
6303: }
6304: } else {
6305: if ($usable ne '') {
6306: $datatable .= '<div id="lti_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
6307: $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'</span></div>'.
6308: '<span class="LC_nobreak">'.&mt('Change?').
6309: '<label><input type="radio" value="0" name="lti_changesecret_'.$i.'" onclick="javascript:toggleChgSecret(this.form,'."'$i','secret','lti'".');" checked="checked" />'.&mt('No').'</label>'.
6310: (' 'x2).
6311: '<label><input type="radio" value="1" name="lti_changesecret_'.$i.'" onclick="javascript:toggleChgSecret(this.form,'."'$i','secret','lti'".');" />'.&mt('Yes').
6312: '</label> </span><div id="lti_divchgsecret_'.$i.'" style="display:none" />'.
6313: '<span class="LC_nobreak">'.&mt('New Secret').':'.
6314: '<input type="password" size="20" name="lti_secret_'.$i.'" value="" autocomplete="new-password" />'.
6315: '<label><input type="checkbox" name="lti_visible_'.$i.'" id="lti_visible_'.$i.'" onclick="if (this.checked) { this.form.lti_secret_'.$i.'.type='."'text'".' } else { this.form.lti_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label></span></div>';
6316: } else {
6317: $datatable .=
6318: '<span class="LC_nobreak">'.$lt{'secret'}.':'.
6319: '<input type="password" size="20" name="lti_secret_'.$i.'" value="" autocomplete="new-password" />'.
6320: '<label><input type="checkbox" name="lti_visible_'.$i.'" id="lti_visible_'.$i.'" onclick="if (this.checked) { this.form.lti_secret_'.$i.'.type='."'text'".' } else { this.form.lti_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label>';
6321: }
6322: }
1.425 raeburn 6323: $datatable .= '<br /><br />'.
1.405 raeburn 6324: '<span class="LC_nobreak">'.$lt{'requser'}.':'.
6325: '<label><input type="radio" name="lti_requser_'.$i.'" value="1"'.$onclickrequser.$checkedrequser{yes}.' />'.&mt('Yes').'</label> '."\n".
6326: '<label><input type="radio" name="lti_requser_'.$i.'" value="0"'.$onclickrequser.$checkedrequser{no}.' />'.&mt('No').'</label></span>'."\n".
6327: '<br /><br />'.
6328: '<span class="LC_nobreak">'.$lt{'crsinc'}.':'.
6329: '<label><input type="radio" name="lti_crsinc_'.$i.'" value="1"'.$onclickcrsinc.$checkedcrsinc{yes}.' />'.&mt('Yes').'</label> '."\n".
6330: '<label><input type="radio" name="lti_crsinc_'.$i.'" value="0"'.$onclickcrsinc.$checkedcrsinc{no}.' />'.&mt('No').'</label></span>'."\n".
6331: (' 'x4).
6332: '<input type="hidden" name="lti_id_'.$i.'" value="'.$item.'" /></span>'.
6333: '</fieldset>'.<i_options($i,$current,$itemcount,%lt).'</td></tr>';
6334: $itemcount ++;
1.320 raeburn 6335: }
6336: }
1.405 raeburn 6337: $css_class = $itemcount%2?' class="LC_odd_row"':'';
6338: my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'lti_pos_add'".');"';
6339: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
6340: '<input type="hidden" name="lti_maxnum" value="'.$maxnum.'" />'."\n".
6341: '<select name="lti_pos_add"'.$chgstr.'>';
6342: for (my $k=0; $k<$maxnum+1; $k++) {
6343: my $vpos = $k+1;
6344: my $selstr;
6345: if ($k == $maxnum) {
6346: $selstr = ' selected="selected" ';
6347: }
6348: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
1.320 raeburn 6349: }
1.405 raeburn 6350: $datatable .= '</select> '."\n".
6351: '<input type="checkbox" name="lti_add" value="1" />'.&mt('Add').'</span></td>'."\n".
6352: '<td colspan="2">'.
6353: '<fieldset><legend>'.&mt('Required settings').'</legend>'.
6354: '<span class="LC_nobreak">'.$lt{'consumer'}.
6355: ':<input type="text" size="15" name="lti_consumer_add" value="" /></span> '."\n".
6356: (' 'x2).
6357: '<span class="LC_nobreak">'.$lt{'version'}.':<select name="lti_version_add">'.
6358: '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
6359: (' 'x2).
1.424 raeburn 6360: '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="3" name="lti_lifetime_add" value="300" /></span><br /><br />'."\n";
6361: if ($switchserver) {
6362: $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
6363: } else {
6364: $datatable .= '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="lti_key_add" value="" autocomplete="off" /></span> '."\n".
6365: (' 'x2).
6366: '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="lti_secret_add" value="" autocomplete="new-password" />'.
6367: '<label><input type="checkbox" name="lti_add_visible" id="lti_add_visible" onclick="if (this.checked) { this.form.lti_secret_add.type='."'text'".' } else { this.form.lti_secret_add.type='."'password'".' }" />'.&mt('Visible input').'</label></span> '."\n";
6368: }
6369: $datatable .= '<br /><br />'.
1.405 raeburn 6370: '<span class="LC_nobreak">'.$lt{'requser'}.':'.
6371: '<label><input type="radio" name="lti_requser_add" value="1" onclick="toggleLTI(this.form,'."'requser','add'".');" checked="checked" />'.&mt('Yes').'</label> '."\n".
6372: '<label><input type="radio" name="lti_requser_add" value="0" onclick="toggleLTI(this.form,'."'requser','add'".');" />'.&mt('No').'</label></span>'."\n".
6373: '<br /><br />'.
6374: '<span class="LC_nobreak">'.$lt{'crsinc'}.':'.
6375: '<label><input type="radio" name="lti_crsinc_add" value="1" onclick="toggleLTI(this.form,'."'crsinc','add'".');" checked="checked" />'.&mt('Yes').'</label> '."\n".
6376: '<label><input type="radio" name="lti_crsinc_add" value="0" onclick="toggleLTI(this.form,'."'crsinc','add'".');" />'.&mt('No').'</label></span>'."\n".
6377: '</fieldset>'.<i_options('add',undef,$itemcount,%lt).
6378: '</td>'."\n".
6379: '</tr>'."\n";
6380: $itemcount ++;
1.320 raeburn 6381: }
1.405 raeburn 6382: $$rowtotal += $itemcount;
6383: return $datatable;
1.320 raeburn 6384: }
6385:
6386: sub lti_names {
6387: my %lt = &Apache::lonlocal::texthash(
6388: 'version' => 'LTI Version',
6389: 'url' => 'URL',
6390: 'key' => 'Key',
1.322 raeburn 6391: 'lifetime' => 'Nonce lifetime (s)',
1.345 raeburn 6392: 'consumer' => 'Consumer',
1.320 raeburn 6393: 'secret' => 'Secret',
1.345 raeburn 6394: 'requser' => "User's identity sent",
1.391 raeburn 6395: 'crsinc' => "Course's identity sent",
1.320 raeburn 6396: 'email' => 'Email address',
6397: 'sourcedid' => 'User ID',
6398: 'other' => 'Other',
6399: 'passback' => 'Can return grades to Consumer:',
6400: 'roster' => 'Can retrieve roster from Consumer:',
1.326 raeburn 6401: 'topmenu' => 'Display LON-CAPA page header',
1.345 raeburn 6402: 'inlinemenu'=> 'Display LON-CAPA inline menu',
1.320 raeburn 6403: );
6404: return %lt;
6405: }
6406:
6407: sub lti_options {
1.325 raeburn 6408: my ($num,$current,$itemcount,%lt) = @_;
1.363 raeburn 6409: my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield,$callback);
1.320 raeburn 6410: $checked{'mapuser'}{'sourcedid'} = ' checked="checked"';
6411: $checked{'mapcrs'}{'course_offering_sourcedid'} = ' checked="checked"';
1.392 raeburn 6412: $checked{'storecrs'}{'Y'} = ' checked="checked"';
6413: $checked{'makecrs'}{'N'} = ' checked="checked"';
1.320 raeburn 6414: $checked{'mapcrstype'} = {};
6415: $checked{'makeuser'} = {};
6416: $checked{'selfenroll'} = {};
6417: $checked{'crssec'} = {};
6418: $checked{'crssecsrc'} = {};
1.325 raeburn 6419: $checked{'lcauth'} = {};
1.326 raeburn 6420: $checked{'menuitem'} = {};
1.325 raeburn 6421: if ($num eq 'add') {
6422: $checked{'lcauth'}{'lti'} = ' checked="checked"';
6423: }
1.320 raeburn 6424: my $userfieldsty = 'none';
6425: my $crsfieldsty = 'none';
6426: my $crssecfieldsty = 'none';
6427: my $secsrcfieldsty = 'none';
1.363 raeburn 6428: my $callbacksty = 'none';
1.337 raeburn 6429: my $passbacksty = 'none';
1.345 raeburn 6430: my $optionsty = 'block';
1.391 raeburn 6431: my $crssty = 'block';
1.325 raeburn 6432: my $lcauthparm;
6433: my $lcauthparmstyle = 'display:none';
6434: my $lcauthparmtext;
1.326 raeburn 6435: my $menusty;
1.325 raeburn 6436: my $numinrow = 4;
1.326 raeburn 6437: my %menutitles = <imenu_titles();
1.320 raeburn 6438:
6439: if (ref($current) eq 'HASH') {
1.345 raeburn 6440: if (!$current->{'requser'}) {
6441: $optionsty = 'none';
1.391 raeburn 6442: $crssty = 'none';
6443: } elsif (!$current->{'crsinc'}) {
6444: $crssty = 'none';
1.345 raeburn 6445: }
1.320 raeburn 6446: if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
6447: $checked{'mapuser'}{'sourcedid'} = '';
6448: if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') {
1.425 raeburn 6449: $checked{'mapuser'}{'email'} = ' checked="checked"';
1.320 raeburn 6450: } else {
6451: $checked{'mapuser'}{'other'} = ' checked="checked"';
6452: $userfield = $current->{'mapuser'};
6453: $userfieldsty = 'inline-block';
6454: }
6455: }
6456: if (($current->{'mapcrs'} ne '') && ($current->{'mapcrs'} ne 'course_offering_sourcedid')) {
6457: $checked{'mapcrs'}{'course_offering_sourcedid'} = '';
6458: if ($current->{'mapcrs'} eq 'context_id') {
1.425 raeburn 6459: $checked{'mapcrs'}{'context_id'} = ' checked="checked"';
1.320 raeburn 6460: } else {
6461: $checked{'mapcrs'}{'other'} = ' checked="checked"';
6462: $cidfield = $current->{'mapcrs'};
6463: $crsfieldsty = 'inline-block';
6464: }
6465: }
6466: if (ref($current->{'mapcrstype'}) eq 'ARRAY') {
6467: foreach my $type (@{$current->{'mapcrstype'}}) {
6468: $checked{'mapcrstype'}{$type} = ' checked="checked"';
6469: }
6470: }
1.392 raeburn 6471: if (!$current->{'storecrs'}) {
6472: $checked{'storecrs'}{'N'} = $checked{'storecrs'}{'Y'};
6473: $checked{'storecrs'}{'Y'} = '';
6474: }
1.345 raeburn 6475: if ($current->{'makecrs'}) {
1.320 raeburn 6476: $checked{'makecrs'}{'Y'} = ' checked="checked"';
1.326 raeburn 6477: }
1.320 raeburn 6478: if (ref($current->{'makeuser'}) eq 'ARRAY') {
6479: foreach my $role (@{$current->{'makeuser'}}) {
6480: $checked{'makeuser'}{$role} = ' checked="checked"';
6481: }
6482: }
1.325 raeburn 6483: if ($current->{'lcauth'} =~ /^(internal|localauth|krb4|krb5|lti)$/) {
6484: $checked{'lcauth'}{$1} = ' checked="checked"';
6485: unless (($current->{'lcauth'} eq 'lti') || ($current->{'lcauth'} eq 'internal')) {
6486: $lcauthparm = $current->{'lcauthparm'};
1.425 raeburn 6487: $lcauthparmstyle = 'display:table-row';
1.325 raeburn 6488: if ($current->{'lcauth'} eq 'localauth') {
6489: $lcauthparmtext = &mt('Local auth argument');
6490: } else {
6491: $lcauthparmtext = &mt('Kerberos domain');
6492: }
6493: }
6494: }
1.320 raeburn 6495: if (ref($current->{'selfenroll'}) eq 'ARRAY') {
6496: foreach my $role (@{$current->{'selfenroll'}}) {
6497: $checked{'selfenroll'}{$role} = ' checked="checked"';
6498: }
6499: }
6500: if (ref($current->{'maproles'}) eq 'HASH') {
6501: %rolemaps = %{$current->{'maproles'}};
6502: }
6503: if ($current->{'section'} ne '') {
1.425 raeburn 6504: $checked{'crssec'}{'Y'} = ' checked="checked"';
1.320 raeburn 6505: $crssecfieldsty = 'inline-block';
6506: if ($current->{'section'} eq 'course_section_sourcedid') {
6507: $checked{'crssecsrc'}{'sourcedid'} = ' checked="checked"';
6508: } else {
6509: $checked{'crssecsrc'}{'other'} = ' checked="checked"';
6510: $crssecsrc = $current->{'section'};
6511: $secsrcfieldsty = 'inline-block';
6512: }
6513: } else {
6514: $checked{'crssec'}{'N'} = ' checked="checked"';
6515: }
1.363 raeburn 6516: if ($current->{'callback'} ne '') {
6517: $callback = $current->{'callback'};
6518: $checked{'callback'}{'Y'} = ' checked="checked"';
6519: $callbacksty = 'inline-block';
6520: } else {
6521: $checked{'callback'}{'N'} = ' checked="checked"';
6522: }
1.326 raeburn 6523: if ($current->{'topmenu'}) {
6524: $checked{'topmenu'}{'Y'} = ' checked="checked"';
6525: } else {
6526: $checked{'topmenu'}{'N'} = ' checked="checked"';
6527: }
6528: if ($current->{'inlinemenu'}) {
6529: $checked{'inlinemenu'}{'Y'} = ' checked="checked"';
6530: } else {
6531: $checked{'inlinemenu'}{'N'} = ' checked="checked"';
6532: }
6533: if (($current->{'topmenu'}) || ($current->{'inlinemenu'})) {
6534: $menusty = 'inline-block';
6535: if (ref($current->{'lcmenu'}) eq 'ARRAY') {
6536: foreach my $item (@{$current->{'lcmenu'}}) {
6537: if (exists($menutitles{$item})) {
6538: $checked{'menuitem'}{$item} = ' checked="checked"';
6539: }
6540: }
6541: }
6542: } else {
6543: $menusty = 'none';
6544: }
1.320 raeburn 6545: } else {
6546: $checked{'makecrs'}{'N'} = ' checked="checked"';
6547: $checked{'crssec'}{'N'} = ' checked="checked"';
1.363 raeburn 6548: $checked{'callback'}{'N'} = ' checked="checked"';
1.326 raeburn 6549: $checked{'topmenu'}{'N'} = ' checked="checked"';
1.425 raeburn 6550: $checked{'inlinemenu'}{'Y'} = ' checked="checked"';
1.326 raeburn 6551: $checked{'menuitem'}{'grades'} = ' checked="checked"';
1.425 raeburn 6552: $menusty = 'inline-block';
1.320 raeburn 6553: }
1.325 raeburn 6554: my @coursetypes = ('official','unofficial','community','textbook','placement','lti');
1.320 raeburn 6555: my %coursetypetitles = &Apache::lonlocal::texthash (
6556: official => 'Official',
6557: unofficial => 'Unofficial',
6558: community => 'Community',
6559: textbook => 'Textbook',
6560: placement => 'Placement Test',
1.325 raeburn 6561: lti => 'LTI Provider',
1.320 raeburn 6562: );
1.325 raeburn 6563: my @authtypes = ('internal','krb4','krb5','localauth');
6564: my %shortauth = (
6565: internal => 'int',
6566: krb4 => 'krb4',
6567: krb5 => 'krb5',
6568: localauth => 'loc'
6569: );
6570: my %authnames = &authtype_names();
1.320 raeburn 6571: my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
6572: my @lticourseroles = qw(Learner Instructor TeachingAssistant Mentor);
6573: my @courseroles = ('cc','in','ta','ep','st');
6574: my $onclickuser = ' onclick="toggleLTI(this.form,'."'user','$num'".');"';
6575: my $onclickcrs = ' onclick="toggleLTI(this.form,'."'crs','$num'".');"';
6576: my $onclicksec = ' onclick="toggleLTI(this.form,'."'sec','$num'".');"';
1.363 raeburn 6577: my $onclickcallback = ' onclick="toggleLTI(this.form,'."'callback','$num'".');"';
1.320 raeburn 6578: my $onclicksecsrc = ' onclick="toggleLTI(this.form,'."'secsrc','$num'".')"';
1.325 raeburn 6579: my $onclicklcauth = ' onclick="toggleLTI(this.form,'."'lcauth','$num'".')"';
1.326 raeburn 6580: my $onclickmenu = ' onclick="toggleLTI(this.form,'."'lcmenu','$num'".');"';
1.391 raeburn 6581: my $output = '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Logout options').'</legend>'.
1.392 raeburn 6582: '<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('Callback to logout LON-CAPA on log out from Consumer').': '.
1.391 raeburn 6583: '<label><input type="radio" name="lti_callback_'.$num.'" value="0"'.
6584: $checked{'callback'}{'N'}.$onclickcallback.' />'.&mt('No').'</label>'.(' 'x2).
6585: '<label><input type="radio" name="lti_callback_'.$num.'" value="1"'.
6586: $checked{'callback'}{'Y'}.$onclickcallback.' />'.&mt('Yes').'</label></span></div>'.
6587: '<div class="LC_floatleft" style="display:'.$callbacksty.';" id="lti_callbackfield_'.$num.'">'.
6588: '<span class="LC_nobreak">'.&mt('Parameter').': '.
6589: '<input type="text" name="lti_callbackparam_'.$num.'" value="'.$callback.'" /></span>'.
6590: '</div><div style="padding:0;clear:both;margin:0;border:0"></div></fieldset>'.
6591: '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Mapping users').'</legend>'.
1.320 raeburn 6592: '<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('LON-CAPA username').': ';
6593: foreach my $option ('sourcedid','email','other') {
6594: $output .= '<label><input type="radio" name="lti_mapuser_'.$num.'" value="'.$option.'"'.
6595: $checked{'mapuser'}{$option}.$onclickuser.' />'.$lt{$option}.'</label>'.
6596: ($option eq 'other' ? '' : (' 'x2) );
6597: }
6598: $output .= '</span></div>'.
6599: '<div class="LC_floatleft" style="display:'.$userfieldsty.';" id="lti_userfield_'.$num.'">'.
6600: '<input type="text" name="lti_customuser_'.$num.'" '.
1.372 raeburn 6601: 'value="'.$userfield.'" /></div></fieldset>'.
1.391 raeburn 6602: '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Roles which may create user accounts').'</legend>';
1.320 raeburn 6603: foreach my $ltirole (@ltiroles) {
6604: $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="lti_makeuser_'.$num.'" value="'.$ltirole.'"'.
1.425 raeburn 6605: $checked{'makeuser'}{$ltirole}.' />'.$ltirole.'</label> </span> ';
1.320 raeburn 6606: }
6607: $output .= '</fieldset>'.
1.391 raeburn 6608: '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('New user accounts created for LTI users').'</legend>'.
1.325 raeburn 6609: '<table>'.
6610: &modifiable_userdata_row('lti','instdata_'.$num,$current,$numinrow,$itemcount).
6611: '</table>'.
6612: '<table class="LC_nested"><tr><td class="LC_left_item">LON-CAPA Authentication</td>'.
6613: '<td class="LC_left_item">';
6614: foreach my $auth ('lti',@authtypes) {
6615: my $authtext;
6616: if ($auth eq 'lti') {
6617: $authtext = &mt('None');
6618: } else {
6619: $authtext = $authnames{$shortauth{$auth}};
6620: }
6621: $output .= '<span class="LC_nobreak"><label><input type="radio" name="lti_lcauth_'.$num.
6622: '" value="'.$auth.'"'.$checked{'lcauth'}{$auth}.$onclicklcauth.' />'.
6623: $authtext.'</label></span> ';
6624: }
6625: $output .= '</td></tr>'.
6626: '<tr id="lti_lcauth_parmrow_'.$num.'" style="'.$lcauthparmstyle.'">'.
6627: '<td class="LC_right_item" colspan="2"><span class="LC_nobreak">'.
6628: '<span id="lti_lcauth_parmtext_'.$num.'">'.$lcauthparmtext.'</span>'.
6629: '<input type="text" name="lti_lcauthparm_'.$num.'" value="" /></span></td></tr>'.
6630: '</table></fieldset>'.
1.391 raeburn 6631: '<fieldset class="ltioption_usr_'.$num.'" style="display:'.$optionsty.'"><legend>'.
6632: &mt('LON-CAPA menu items (Course Coordinator can override)').'</legend>'.
6633: '<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{'topmenu'}.': '.
6634: '<label><input type="radio" name="lti_topmenu_'.$num.'" value="0"'.
6635: $checked{'topmenu'}{'N'}.$onclickmenu.' />'.&mt('No').'</label>'.(' 'x2).
6636: '<label><input type="radio" name="lti_topmenu_'.$num.'" value="1"'.
6637: $checked{'topmenu'}{'Y'}.$onclickmenu.' />'.&mt('Yes').'</label></span></div>'.
6638: '<div style="padding:0;clear:both;margin:0;border:0"></div>'.
6639: '<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{'inlinemenu'}.': '.
6640: '<label><input type="radio" name="lti_inlinemenu_'.$num.'" value="0"'.
6641: $checked{'inlinemenu'}{'N'}.$onclickmenu.' />'.&mt('No').'</label>'.(' 'x2).
6642: '<label><input type="radio" name="lti_inlinemenu_'.$num.'" value="1"'.
6643: $checked{'inlinemenu'}{'Y'}.$onclickmenu.' />'.&mt('Yes').'</label></span></div>';
6644: $output .='<div style="padding:0;clear:both;margin:0;border:0"></div>'.
6645: '<div class="LC_floatleft" style="display:'.$menusty.';" id="lti_menufield_'.$num.'">'.
6646: '<span class="LC_nobreak">'.&mt('Menu items').': ';
6647: foreach my $type ('fullname','coursetitle','role','logout','grades') {
6648: $output .= '<label><input type="checkbox" name="lti_menuitem_'.$num.'" value="'.$type.'"'.
6649: $checked{'menuitem'}{$type}.' />'.$menutitles{$type}.'</label>'.
6650: (' 'x2);
6651: }
6652: $output .= '</span></div></fieldset>'.
6653: '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Mapping courses').'</legend>'.
1.320 raeburn 6654: '<div class="LC_floatleft"><span class="LC_nobreak">'.
6655: &mt('Unique course identifier').': ';
6656: foreach my $option ('course_offering_sourcedid','context_id','other') {
6657: $output .= '<label><input type="radio" name="lti_mapcrs_'.$num.'" value="'.$option.'"'.
6658: $checked{'mapcrs'}{$option}.$onclickcrs.' />'.$option.'</label>'.
6659: ($option eq 'other' ? '' : (' 'x2) );
6660: }
1.334 raeburn 6661: $output .= '</span></div><div class="LC_floatleft" style="display:'.$crsfieldsty.';" id="lti_crsfield_'.$num.'">'.
1.320 raeburn 6662: '<input type="text" name="lti_mapcrsfield_'.$num.'" value="'.$cidfield.'" />'.
6663: '</div><div style="padding:0;clear:both;margin:0;border:0"></div>'.
6664: '<span class="LC_nobreak">'.&mt('LON-CAPA course type(s)').': ';
6665: foreach my $type (@coursetypes) {
6666: $output .= '<label><input type="checkbox" name="lti_mapcrstype_'.$num.'" value="'.$type.'"'.
6667: $checked{'mapcrstype'}{$type}.' />'.$coursetypetitles{$type}.'</label>'.
6668: (' 'x2);
6669: }
1.392 raeburn 6670: $output .= '</span><br /><br />'.
6671: '<span class="LC_nobreak">'.&mt('Store mapping of course identifier to LON-CAPA CourseID').': '.
6672: '<label><input type="radio" name="lti_storecrs_'.$num.'" value="0"'.
6673: $checked{'storecrs'}{'N'}.' />'.&mt('No').'</label>'.(' 'x2).
6674: '<label><input type="radio" name="lti_storecrs_'.$num.'" value="1"'.
6675: $checked{'storecrs'}{'Y'}.' />'.&mt('Yes').'</label></span>'.
6676: '</fieldset>'.
1.391 raeburn 6677: '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Mapping course roles').'</legend><table><tr>';
6678: foreach my $ltirole (@lticourseroles) {
6679: my ($selected,$selectnone);
6680: if ($rolemaps{$ltirole} eq '') {
6681: $selectnone = ' selected="selected"';
6682: }
6683: $output .= '<td style="text-align: center">'.$ltirole.'<br />'.
6684: '<select name="lti_maprole_'.$ltirole.'_'.$num.'">'.
6685: '<option value=""'.$selectnone.'>'.&mt('Select').'</option>';
6686: foreach my $role (@courseroles) {
6687: unless ($selectnone) {
6688: if ($rolemaps{$ltirole} eq $role) {
6689: $selected = ' selected="selected"';
6690: } else {
6691: $selected = '';
6692: }
6693: }
6694: $output .= '<option value="'.$role.'"'.$selected.'>'.
6695: &Apache::lonnet::plaintext($role,'Course').
6696: '</option>';
6697: }
6698: $output .= '</select></td>';
6699: }
6700: $output .= '</tr></table></fieldset>'.
6701: '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Creating courses').'</legend>'.
1.320 raeburn 6702: '<span class="LC_nobreak">'.&mt('Course created (if absent) on Instructor access').': '.
6703: '<label><input type="radio" name="lti_makecrs_'.$num.'" value="0"'.
6704: $checked{'makecrs'}{'N'}.' />'.&mt('No').'</label>'.(' 'x2).
6705: '<label><input type="radio" name="lti_makecrs_'.$num.'" value="1"'.
6706: $checked{'makecrs'}{'Y'}.' />'.&mt('Yes').'</label></span>'.
6707: '</fieldset>'.
1.391 raeburn 6708: '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Roles which may self-enroll').'</legend>';
1.320 raeburn 6709: foreach my $lticrsrole (@lticourseroles) {
6710: $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="lti_selfenroll_'.$num.'" value="'.$lticrsrole.'"'.
6711: $checked{'selfenroll'}{$lticrsrole}.' />'.$lticrsrole.'</label> </span> ';
6712: }
6713: $output .= '</fieldset>'.
1.391 raeburn 6714: '<fieldset class="ltioption_crs_'.$num.'" style="display:'.$crssty.'"><legend>'.&mt('Course options').'</legend>'.
1.320 raeburn 6715: '<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('Assign users to sections').': '.
6716: '<label><input type="radio" name="lti_crssec_'.$num.'" value="0"'.
6717: $checked{'crssec'}{'N'}.$onclicksec.' />'.&mt('No').'</label>'.(' 'x2).
6718: '<label><input type="radio" name="lti_crssec_'.$num.'" value="1"'.
1.334 raeburn 6719: $checked{'crssec'}{'Y'}.$onclicksec.' />'.&mt('Yes').'</label></span></div>'.
1.320 raeburn 6720: '<div class="LC_floatleft" style="display:'.$crssecfieldsty.';" id="lti_crssecfield_'.$num.'">'.
6721: '<span class="LC_nobreak">'.&mt('From').':<label>'.
6722: '<input type="radio" name="lti_crssecsrc_'.$num.'" value="course_section_sourcedid"'.
6723: $checked{'crssecsrc'}{'sourcedid'}.$onclicksecsrc.' />'.
6724: &mt('Standard field').'</label>'.(' 'x2).
6725: '<label><input type="radio" name="lti_crssecsrc_'.$num.'" value="other"'.
6726: $checked{'crssecsrc'}{'other'}.$onclicksecsrc.' />'.&mt('Other').
1.334 raeburn 6727: '</label></span></div><div class="LC_floatleft" style="display:'.$secsrcfieldsty.';" id="lti_secsrcfield_'.$num.'">'.
1.320 raeburn 6728: '<input type="text" name="lti_customsection_'.$num.'" value="'.$crssecsrc.'" />'.
1.337 raeburn 6729: '</div><div style="padding:0;clear:both;margin:0;border:0"></div>';
6730: my ($pb1p1chk,$pb1p0chk,$onclickpb);
6731: foreach my $extra ('roster','passback') {
1.320 raeburn 6732: my $checkedon = '';
6733: my $checkedoff = ' checked="checked"';
1.337 raeburn 6734: if ($extra eq 'passback') {
6735: $pb1p1chk = ' checked="checked"';
6736: $pb1p0chk = '';
1.425 raeburn 6737: $onclickpb = ' onclick="toggleLTI(this.form,'."'passback','$num'".');"';
1.337 raeburn 6738: } else {
1.425 raeburn 6739: $onclickpb = '';
1.337 raeburn 6740: }
1.320 raeburn 6741: if (ref($current) eq 'HASH') {
6742: if (($current->{$extra})) {
6743: $checkedon = $checkedoff;
6744: $checkedoff = '';
1.337 raeburn 6745: if ($extra eq 'passback') {
6746: $passbacksty = 'inline-block';
6747: }
6748: if ($current->{'passbackformat'} eq '1.0') {
6749: $pb1p0chk = ' checked="checked"';
6750: $pb1p1chk = '';
6751: }
1.320 raeburn 6752: }
6753: }
6754: $output .= $lt{$extra}.' '.
1.337 raeburn 6755: '<label><input type="radio" name="lti_'.$extra.'_'.$num.'" value="0"'.$checkedoff.$onclickpb.' />'.
1.320 raeburn 6756: &mt('No').'</label>'.(' 'x2).
1.339 raeburn 6757: '<label><input type="radio" name="lti_'.$extra.'_'.$num.'" value="1"'.$checkedon.$onclickpb.' />'.
1.320 raeburn 6758: &mt('Yes').'</label><br />';
6759: }
1.337 raeburn 6760: $output .= '<div class="LC_floatleft" style="display:'.$passbacksty.';" id="lti_passback_'.$num.'">'.
6761: '<span class="LC_nobreak">'.&mt('Grade format').
6762: '<label><input type="radio" name="lti_passbackformat_'.$num.'" value="1.1"'.$pb1p1chk.' />'.
6763: &mt('Outcomes Service (1.1)').'</label>'.(' 'x2).
6764: '<label><input type="radio" name="lti_passbackformat_'.$num.'" value="1.0"'.$pb1p0chk.'/>'.
1.363 raeburn 6765: &mt('Outcomes Extension (1.0)').'</label></span></div>'.
1.391 raeburn 6766: '<div style="padding:0;clear:both;margin:0;border:0"></div></fieldset>';
1.334 raeburn 6767: $output .= '</span></div></fieldset>';
1.320 raeburn 6768: # '<fieldset><legend>'.&mt('Assigning author roles').'</legend>';
6769: #
6770: # $output .= '</fieldset>'.
6771: # '<fieldset><legend>'.&mt('Assigning domain roles').'</legend>';
6772: return $output;
6773: }
6774:
1.326 raeburn 6775: sub ltimenu_titles {
6776: return &Apache::lonlocal::texthash(
6777: fullname => 'Full name',
6778: coursetitle => 'Course title',
6779: role => 'Role',
6780: logout => 'Logout',
6781: grades => 'Grades',
6782: );
6783: }
6784:
1.121 raeburn 6785: sub print_coursedefaults {
1.139 raeburn 6786: my ($position,$dom,$settings,$rowtotal) = @_;
1.192 raeburn 6787: my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
1.121 raeburn 6788: my $itemcount = 1;
1.192 raeburn 6789: my %choices = &Apache::lonlocal::texthash (
6790: canuse_pdfforms => 'Course/Community users can create/upload PDF forms',
1.198 raeburn 6791: uploadquota => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',
1.428 ! raeburn 6792: coursequota => 'Default cumulative quota for all group portfolio spaces in course',
1.192 raeburn 6793: anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
6794: coursecredits => 'Credits can be specified for courses',
1.257 raeburn 6795: uselcmath => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',
6796: usejsme => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',
1.398 raeburn 6797: inline_chem => 'Use inline previewer for chemical reaction response in place of pop-up',
1.314 raeburn 6798: texengine => 'Default method to display mathematics',
1.257 raeburn 6799: postsubmit => 'Disable submit button/keypress following student submission',
1.276 raeburn 6800: canclone => "People who may clone a course (besides course's owner and coordinators)",
6801: mysqltables => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',
1.405 raeburn 6802: ltiauth => 'Student username in LTI launch of deep-linked URL can be accepted without re-authentication',
1.422 raeburn 6803: domexttool => 'External Tools defined in the domain may be used in courses/communities (by type)',
6804: exttool => 'External Tools can be defined and configured in courses/communities (by type)',
1.192 raeburn 6805: );
1.198 raeburn 6806: my %staticdefaults = (
6807: anonsurvey_threshold => 10,
6808: uploadquota => 500,
1.428 ! raeburn 6809: coursequota => 20,
1.257 raeburn 6810: postsubmit => 60,
1.276 raeburn 6811: mysqltables => 172800,
1.422 raeburn 6812: domexttool => 1,
6813: exttool => 0,
1.198 raeburn 6814: );
1.139 raeburn 6815: if ($position eq 'top') {
1.257 raeburn 6816: %defaultchecked = (
6817: 'canuse_pdfforms' => 'off',
6818: 'uselcmath' => 'on',
6819: 'usejsme' => 'on',
1.398 raeburn 6820: 'inline_chem' => 'on',
1.289 raeburn 6821: 'canclone' => 'none',
1.257 raeburn 6822: );
1.398 raeburn 6823: @toggles = ('canuse_pdfforms','uselcmath','usejsme','inline_chem');
1.349 raeburn 6824: my $deftex = $Apache::lonnet::deftex;
1.314 raeburn 6825: if (ref($settings) eq 'HASH') {
6826: if ($settings->{'texengine'}) {
6827: if ($settings->{'texengine'} =~ /^(MathJax|mimetex|tth)$/) {
6828: $deftex = $settings->{'texengine'};
6829: }
6830: }
6831: }
6832: $css_class = $itemcount%2?' class="LC_odd_row"':'';
6833: my $mathdisp = '<tr'.$css_class.'><td style="vertical-align: top">'.
6834: '<span class="LC_nobreak">'.$choices{'texengine'}.
6835: '</span></td><td class="LC_right_item">'.
6836: '<select name="texengine">'."\n";
6837: my %texoptions = (
6838: MathJax => 'MathJax',
6839: mimetex => &mt('Convert to Images'),
6840: tth => &mt('TeX to HTML'),
6841: );
6842: foreach my $renderer ('MathJax','mimetex','tth') {
6843: my $selected = '';
6844: if ($renderer eq $deftex) {
6845: $selected = ' selected="selected"';
6846: }
6847: $mathdisp .= '<option value="'.$renderer.'"'.$selected.'>'.$texoptions{$renderer}.'</option>'."\n";
6848: }
6849: $mathdisp .= '</select></td></tr>'."\n";
6850: $itemcount ++;
1.139 raeburn 6851: ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
1.257 raeburn 6852: \%choices,$itemcount);
1.314 raeburn 6853: $datatable = $mathdisp.$datatable;
1.264 raeburn 6854: $css_class = $itemcount%2?' class="LC_odd_row"':'';
6855: $datatable .=
1.306 raeburn 6856: '<tr'.$css_class.'><td style="vertical-align: top">'.
1.264 raeburn 6857: '<span class="LC_nobreak">'.$choices{'canclone'}.
6858: '</span></td><td class="LC_left_item">';
6859: my $currcanclone = 'none';
6860: my $onclick;
6861: my @cloneoptions = ('none','domain');
1.380 raeburn 6862: my %clonetitles = &Apache::lonlocal::texthash (
1.264 raeburn 6863: none => 'No additional course requesters',
6864: domain => "Any course requester in course's domain",
6865: instcode => 'Course requests for official courses ...',
6866: );
6867: my (%codedefaults,@code_order,@posscodes);
6868: if (&Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,
6869: \@code_order) eq 'ok') {
6870: if (@code_order > 0) {
6871: push(@cloneoptions,'instcode');
6872: $onclick = ' onclick="toggleDisplay(this.form,'."'cloneinstcode'".');"';
6873: }
6874: }
6875: if (ref($settings) eq 'HASH') {
6876: if ($settings->{'canclone'}) {
6877: if (ref($settings->{'canclone'}) eq 'HASH') {
6878: if (ref($settings->{'canclone'}{'instcode'}) eq 'ARRAY') {
6879: if (@code_order > 0) {
6880: $currcanclone = 'instcode';
6881: @posscodes = @{$settings->{'canclone'}{'instcode'}};
6882: }
6883: }
6884: } elsif ($settings->{'canclone'} eq 'domain') {
6885: $currcanclone = $settings->{'canclone'};
6886: }
6887: }
1.289 raeburn 6888: }
1.264 raeburn 6889: foreach my $option (@cloneoptions) {
6890: my ($checked,$additional);
6891: if ($currcanclone eq $option) {
6892: $checked = ' checked="checked"';
6893: }
6894: if ($option eq 'instcode') {
6895: if (@code_order) {
6896: my $show = 'none';
6897: if ($checked) {
6898: $show = 'block';
6899: }
1.317 raeburn 6900: $additional = '<div id="cloneinstcode" style="display:'.$show.';" />'.
1.264 raeburn 6901: &mt('Institutional codes for new and cloned course have identical:').
6902: '<br />';
6903: foreach my $item (@code_order) {
6904: my $codechk;
6905: if ($checked) {
6906: if (grep(/^\Q$item\E$/,@posscodes)) {
6907: $codechk = ' checked="checked"';
6908: }
6909: }
6910: $additional .= '<label>'.
6911: '<input type="checkbox" name="clonecode" value="'.$item.'"'.$codechk.' />'.
6912: $item.'</label>';
6913: }
6914: $additional .= (' 'x2).'('.&mt('check as many as needed').')</div>';
6915: }
6916: }
6917: $datatable .=
6918: '<span class="LC_nobreak"><label><input type="radio" name="canclone"'.$checked.
6919: ' value="'.$option.'"'.$onclick.' />'.$clonetitles{$option}.
6920: '</label> '.$additional.'</span><br />';
6921: }
6922: $datatable .= '</td>'.
6923: '</tr>';
6924: $itemcount ++;
1.139 raeburn 6925: } else {
6926: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
1.428 ! raeburn 6927: my ($currdefresponder,%defcredits,%curruploadquota,%currcoursequota,
! 6928: %deftimeout,%currmysql);
1.192 raeburn 6929: my $currusecredits = 0;
1.257 raeburn 6930: my $postsubmitclient = 1;
1.405 raeburn 6931: my $ltiauth = 0;
1.422 raeburn 6932: my %domexttool;
6933: my %exttool;
1.271 raeburn 6934: my @types = ('official','unofficial','community','textbook','placement');
1.139 raeburn 6935: if (ref($settings) eq 'HASH') {
1.404 raeburn 6936: if ($settings->{'ltiauth'}) {
6937: $ltiauth = 1;
1.405 raeburn 6938: }
1.422 raeburn 6939: if (ref($settings->{'domexttool'}) eq 'HASH') {
6940: foreach my $type (@types) {
6941: if ($settings->{'domexttool'}->{$type}) {
6942: $domexttool{$type} = ' checked="checked"';
6943: }
6944: }
6945: } else {
6946: foreach my $type (@types) {
6947: if ($staticdefaults{'domexttool'}) {
6948: $domexttool{$type} = ' checked="checked"';
6949: }
6950: }
6951: }
6952: if (ref($settings->{'exttool'}) eq 'HASH') {
6953: foreach my $type (@types) {
6954: if ($settings->{'exttool'}->{$type}) {
6955: $exttool{$type} = ' checked="checked"';
6956: }
6957: }
6958: }
1.139 raeburn 6959: $currdefresponder = $settings->{'anonsurvey_threshold'};
1.198 raeburn 6960: if (ref($settings->{'uploadquota'}) eq 'HASH') {
6961: foreach my $type (keys(%{$settings->{'uploadquota'}})) {
6962: $curruploadquota{$type} = $settings->{'uploadquota'}{$type};
6963: }
6964: }
1.428 ! raeburn 6965: if (ref($settings->{'coursequota'}) eq 'HASH') {
! 6966: foreach my $type (keys(%{$settings->{'coursequota'}})) {
! 6967: $currcoursequota{$type} = $settings->{'coursequota'}{$type};
! 6968: }
! 6969: }
1.192 raeburn 6970: if (ref($settings->{'coursecredits'}) eq 'HASH') {
1.257 raeburn 6971: foreach my $type (@types) {
6972: next if ($type eq 'community');
6973: $defcredits{$type} = $settings->{'coursecredits'}->{$type};
6974: if ($defcredits{$type} ne '') {
6975: $currusecredits = 1;
6976: }
6977: }
6978: }
6979: if (ref($settings->{'postsubmit'}) eq 'HASH') {
6980: if ($settings->{'postsubmit'}->{'client'} eq 'off') {
6981: $postsubmitclient = 0;
6982: foreach my $type (@types) {
6983: $deftimeout{$type} = $staticdefaults{'postsubmit'};
6984: }
6985: } else {
6986: foreach my $type (@types) {
6987: if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') {
6988: if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) {
1.289 raeburn 6989: $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type};
1.257 raeburn 6990: } else {
6991: $deftimeout{$type} = $staticdefaults{'postsubmit'};
6992: }
6993: } else {
6994: $deftimeout{$type} = $staticdefaults{'postsubmit'};
6995: }
6996: }
6997: }
6998: } else {
6999: foreach my $type (@types) {
7000: $deftimeout{$type} = $staticdefaults{'postsubmit'};
1.192 raeburn 7001: }
7002: }
1.276 raeburn 7003: if (ref($settings->{'mysqltables'}) eq 'HASH') {
7004: foreach my $type (keys(%{$settings->{'mysqltables'}})) {
7005: $currmysql{$type} = $settings->{'mysqltables'}{$type};
7006: }
7007: } else {
7008: foreach my $type (@types) {
7009: $currmysql{$type} = $staticdefaults{'mysqltables'};
7010: }
7011: }
1.258 raeburn 7012: } else {
7013: foreach my $type (@types) {
7014: $deftimeout{$type} = $staticdefaults{'postsubmit'};
1.422 raeburn 7015: if ($staticdefaults{'domexttool'}) {
7016: $domexttool{$type} = ' checked="checked"';
7017: }
1.258 raeburn 7018: }
1.139 raeburn 7019: }
7020: if (!$currdefresponder) {
1.198 raeburn 7021: $currdefresponder = $staticdefaults{'anonsurvey_threshold'};
1.139 raeburn 7022: } elsif ($currdefresponder < 1) {
7023: $currdefresponder = 1;
7024: }
1.198 raeburn 7025: foreach my $type (@types) {
7026: if ($curruploadquota{$type} eq '') {
7027: $curruploadquota{$type} = $staticdefaults{'uploadquota'};
7028: }
1.428 ! raeburn 7029: if ($currcoursequota{$type} eq '') {
! 7030: $currcoursequota{$type} = $staticdefaults{'coursequota'};
! 7031: }
1.198 raeburn 7032: }
1.139 raeburn 7033: $datatable .=
1.192 raeburn 7034: '<tr'.$css_class.'><td><span class="LC_nobreak">'.
7035: $choices{'anonsurvey_threshold'}.
1.139 raeburn 7036: '</span></td>'.
7037: '<td class="LC_right_item"><span class="LC_nobreak">'.
7038: '<input type="text" name="anonsurvey_threshold"'.
7039: ' value="'.$currdefresponder.'" size="5" /></span>'.
1.230 raeburn 7040: '</td></tr>'."\n";
7041: $itemcount ++;
7042: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
7043: $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
7044: $choices{'uploadquota'}.
7045: '</span></td>'.
1.306 raeburn 7046: '<td style="text-align: right" class="LC_right_item">'.
1.230 raeburn 7047: '<table><tr>';
1.198 raeburn 7048: foreach my $type (@types) {
1.306 raeburn 7049: $datatable .= '<td style="text-align: center">'.&mt($type).'<br />'.
1.198 raeburn 7050: '<input type="text" name="uploadquota_'.$type.'"'.
7051: ' value="'.$curruploadquota{$type}.'" size="5" /></td>';
7052: }
7053: $datatable .= '</tr></table></td></tr>'."\n";
1.230 raeburn 7054: $itemcount ++;
1.428 ! raeburn 7055: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
! 7056: $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
! 7057: $choices{'coursequota'}.
! 7058: '</span></td>'.
! 7059: '<td style="text-align: right" class="LC_right_item">'.
! 7060: '<table><tr>';
! 7061: foreach my $type (@types) {
! 7062: $datatable .= '<td style="text-align: center">'.&mt($type).'<br />'.
! 7063: '<input type="text" name="coursequota_'.$type.'"'.
! 7064: ' value="'.$currcoursequota{$type}.'" size="5" /></td>';
! 7065: }
! 7066: $datatable .= '</tr></table></td></tr>'."\n";
! 7067: $itemcount ++;
1.236 raeburn 7068: my $onclick = "toggleDisplay(this.form,'credits');";
1.210 raeburn 7069: my $display = 'none';
1.192 raeburn 7070: if ($currusecredits) {
7071: $display = 'block';
7072: }
7073: my $additional = '<div id="credits" style="display: '.$display.'">'.
1.257 raeburn 7074: '<i>'.&mt('Default credits').'</i><br /><table><tr>';
7075: foreach my $type (@types) {
7076: next if ($type eq 'community');
1.306 raeburn 7077: $additional .= '<td style="text-align: center">'.&mt($type).'<br />'.
1.257 raeburn 7078: '<input type="text" name="'.$type.'_credits"'.
1.258 raeburn 7079: ' value="'.$defcredits{$type}.'" size="3" /></td>';
1.257 raeburn 7080: }
7081: $additional .= '</tr></table></div>'."\n";
1.192 raeburn 7082: %defaultchecked = ('coursecredits' => 'off');
7083: @toggles = ('coursecredits');
7084: my $current = {
7085: 'coursecredits' => $currusecredits,
7086: };
7087: (my $table,$itemcount) =
7088: &radiobutton_prefs($current,\@toggles,\%defaultchecked,
1.257 raeburn 7089: \%choices,$itemcount,$onclick,$additional,'left');
7090: $datatable .= $table;
7091: $onclick = "toggleDisplay(this.form,'studentsubmission');";
7092: my $display = 'none';
7093: if ($postsubmitclient) {
7094: $display = 'block';
7095: }
7096: $additional = '<div id="studentsubmission" style="display: '.$display.'">'.
1.259 raeburn 7097: &mt('Number of seconds submit is disabled').'<br />'.
7098: '<i>'.&mt('Enter 0 to remain disabled until page reload.').'</i><br />'.
7099: '<table><tr>';
1.257 raeburn 7100: foreach my $type (@types) {
1.306 raeburn 7101: $additional .= '<td style="text-align: center">'.&mt($type).'<br />'.
1.257 raeburn 7102: '<input type="text" name="'.$type.'_timeout" value="'.
7103: $deftimeout{$type}.'" size="5" /></td>';
7104: }
7105: $additional .= '</tr></table></div>'."\n";
7106: %defaultchecked = ('postsubmit' => 'on');
7107: @toggles = ('postsubmit');
1.280 raeburn 7108: $current = {
7109: 'postsubmit' => $postsubmitclient,
7110: };
1.257 raeburn 7111: ($table,$itemcount) =
7112: &radiobutton_prefs($current,\@toggles,\%defaultchecked,
7113: \%choices,$itemcount,$onclick,$additional,'left');
1.192 raeburn 7114: $datatable .= $table;
1.276 raeburn 7115: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
7116: $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
7117: $choices{'mysqltables'}.
7118: '</span></td>'.
1.306 raeburn 7119: '<td style="text-align: right" class="LC_right_item">'.
1.276 raeburn 7120: '<table><tr>';
7121: foreach my $type (@types) {
1.306 raeburn 7122: $datatable .= '<td style="text-align: center">'.&mt($type).'<br />'.
1.276 raeburn 7123: '<input type="text" name="mysqltables_'.$type.'"'.
1.295 raeburn 7124: ' value="'.$currmysql{$type}.'" size="8" /></td>';
1.276 raeburn 7125: }
7126: $datatable .= '</tr></table></td></tr>'."\n";
7127: $itemcount ++;
1.404 raeburn 7128: %defaultchecked = ('ltiauth' => 'off');
7129: @toggles = ('ltiauth');
7130: $current = {
7131: 'ltiauth' => $ltiauth,
7132: };
7133: ($table,$itemcount) =
7134: &radiobutton_prefs($current,\@toggles,\%defaultchecked,
7135: \%choices,$itemcount,undef,undef,'left');
7136: $datatable .= $table;
1.422 raeburn 7137: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
7138: $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
7139: $choices{'domexttool'}.
7140: '</span></td>'.
7141: '<td style="text-align: right" class="LC_right_item">'.
7142: '<table><tr>';
7143: foreach my $type (@types) {
7144: $datatable .= '<td style="text-align: left">'.
7145: '<span class="LC_nobreak">'.
7146: '<input type="checkbox" name="domexttool"'.
7147: ' value="'.$type.'"'.$domexttool{$type}.' />'.
7148: &mt($type).'</span></td>'."\n";
7149: }
7150: $datatable .= '</tr></table></td></tr>'."\n";
1.404 raeburn 7151: $itemcount ++;
1.422 raeburn 7152: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
7153: $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
7154: $choices{'exttool'}.
7155: '</span></td>'.
7156: '<td style="text-align: right" class="LC_right_item">'.
7157: '<table><tr>';
7158: foreach my $type (@types) {
7159: $datatable .= '<td style="text-align: left">'.
7160: '<span class="LC_nobreak">'.
7161: '<input type="checkbox" name="exttool"'.
7162: ' value="'.$type.'"'.$exttool{$type}.' />'.
7163: &mt($type).'</span></td>'."\n";
7164: }
7165: $datatable .= '</tr></table></td></tr>'."\n";
1.139 raeburn 7166: }
1.192 raeburn 7167: $$rowtotal += $itemcount;
1.121 raeburn 7168: return $datatable;
1.118 jms 7169: }
7170:
1.231 raeburn 7171: sub print_selfenrollment {
7172: my ($position,$dom,$settings,$rowtotal) = @_;
7173: my ($css_class,$datatable);
7174: my $itemcount = 1;
1.271 raeburn 7175: my @types = ('official','unofficial','community','textbook','placement');
1.231 raeburn 7176: if (($position eq 'top') || ($position eq 'middle')) {
1.232 raeburn 7177: my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
7178: my %descs = &Apache::lonuserutils::selfenroll_default_descs();
1.231 raeburn 7179: my @rows;
7180: my $key;
7181: if ($position eq 'top') {
7182: $key = 'admin';
7183: if (ref($rowsref) eq 'ARRAY') {
7184: @rows = @{$rowsref};
7185: }
7186: } elsif ($position eq 'middle') {
7187: $key = 'default';
7188: @rows = ('types','registered','approval','limit');
7189: }
7190: foreach my $row (@rows) {
7191: if (defined($titlesref->{$row})) {
7192: $itemcount ++;
7193: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7194: $datatable .= '<tr'.$css_class.'>'.
7195: '<td>'.$titlesref->{$row}.'</td>'.
7196: '<td class="LC_left_item">'.
7197: '<table><tr>';
7198: my (%current,%currentcap);
7199: if (ref($settings) eq 'HASH') {
7200: if (ref($settings->{$key}) eq 'HASH') {
7201: foreach my $type (@types) {
7202: if (ref($settings->{$key}->{$type}) eq 'HASH') {
7203: $current{$type} = $settings->{$key}->{$type}->{$row};
7204: }
7205: if (($row eq 'limit') && ($key eq 'default')) {
7206: if (ref($settings->{$key}->{$type}) eq 'HASH') {
7207: $currentcap{$type} = $settings->{$key}->{$type}->{'cap'};
7208: }
7209: }
7210: }
7211: }
7212: }
7213: my %roles = (
7214: '0' => &Apache::lonnet::plaintext('dc'),
7215: );
7216:
7217: foreach my $type (@types) {
7218: unless (($row eq 'registered') && ($key eq 'default')) {
7219: $datatable .= '<th>'.&mt($type).'</th>';
7220: }
7221: }
7222: unless (($row eq 'registered') && ($key eq 'default')) {
7223: $datatable .= '</tr><tr>';
7224: }
7225: foreach my $type (@types) {
7226: if ($type eq 'community') {
7227: $roles{'1'} = &mt('Community personnel');
7228: } else {
7229: $roles{'1'} = &mt('Course personnel');
7230: }
7231: $datatable .= '<td style="vertical-align: top">';
7232: if ($position eq 'top') {
7233: my %checked;
7234: if ($current{$type} eq '0') {
7235: $checked{'0'} = ' checked="checked"';
7236: } else {
7237: $checked{'1'} = ' checked="checked"';
7238: }
7239: foreach my $role ('1','0') {
7240: $datatable .= '<span class="LC_nobreak"><label>'.
7241: '<input type="radio" name="selfenrolladmin_'.$row.'_'.$type.'" '.
7242: 'value="'.$role.'"'.$checked{$role}.' />'.
7243: $roles{$role}.'</label></span> ';
7244: }
7245: } else {
7246: if ($row eq 'types') {
7247: my %checked;
7248: if ($current{$type} =~ /^(all|dom)$/) {
7249: $checked{$1} = ' checked="checked"';
7250: } else {
7251: $checked{''} = ' checked="checked"';
7252: }
7253: foreach my $val ('','dom','all') {
7254: $datatable .= '<span class="LC_nobreak"><label>'.
7255: '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
7256: 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
7257: }
7258: } elsif ($row eq 'registered') {
7259: my %checked;
7260: if ($current{$type} eq '1') {
7261: $checked{'1'} = ' checked="checked"';
7262: } else {
7263: $checked{'0'} = ' checked="checked"';
7264: }
7265: foreach my $val ('0','1') {
7266: $datatable .= '<span class="LC_nobreak"><label>'.
7267: '<input type ="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
7268: 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
7269: }
7270: } elsif ($row eq 'approval') {
7271: my %checked;
7272: if ($current{$type} =~ /^([12])$/) {
7273: $checked{$1} = ' checked="checked"';
7274: } else {
7275: $checked{'0'} = ' checked="checked"';
7276: }
7277: for my $val (0..2) {
7278: $datatable .= '<span class="LC_nobreak"><label>'.
7279: '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
7280: 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
7281: }
7282: } elsif ($row eq 'limit') {
7283: my %checked;
7284: if ($current{$type} =~ /^(allstudents|selfenrolled)$/) {
7285: $checked{$1} = ' checked="checked"';
7286: } else {
7287: $checked{'none'} = ' checked="checked"';
7288: }
7289: my $cap;
7290: if ($currentcap{$type} =~ /^\d+$/) {
7291: $cap = $currentcap{$type};
7292: }
7293: foreach my $val ('none','allstudents','selfenrolled') {
7294: $datatable .= '<span class="LC_nobreak"><label>'.
7295: '<input type="radio" name="selfenrolldefault_'.$row.'_'.$type.'" '.
7296: 'value="'.$val.'"'.$checked{$val}.' />'.$descs{$row}{$val}.'</label></span> ';
7297: }
7298: $datatable .= '<br />'.
7299: '<span class="LC_nobreak">'.&mt('Maximum allowed: ').
7300: '<input type="text" name="selfenrolldefault_cap_'.$type.'" size = "5" value="'.$cap.'" />'.
7301: '</span>';
7302: }
7303: }
7304: $datatable .= '</td>';
7305: }
7306: $datatable .= '</tr>';
7307: }
7308: $datatable .= '</table></td></tr>';
7309: }
7310: } elsif ($position eq 'bottom') {
1.235 raeburn 7311: $datatable .= &print_validation_rows('selfenroll',$dom,$settings,\$itemcount);
7312: }
7313: $$rowtotal += $itemcount;
7314: return $datatable;
7315: }
7316:
7317: sub print_validation_rows {
7318: my ($caller,$dom,$settings,$rowtotal) = @_;
7319: my ($itemsref,$namesref,$fieldsref);
7320: if ($caller eq 'selfenroll') {
7321: ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();
7322: } elsif ($caller eq 'requestcourses') {
7323: ($itemsref,$namesref,$fieldsref) = &Apache::loncoursequeueadmin::requestcourses_validation_types();
7324: }
7325: my %currvalidation;
7326: if (ref($settings) eq 'HASH') {
7327: if (ref($settings->{'validation'}) eq 'HASH') {
7328: %currvalidation = %{$settings->{'validation'}};
1.231 raeburn 7329: }
1.235 raeburn 7330: }
7331: my $datatable;
7332: my $itemcount = 0;
7333: foreach my $item (@{$itemsref}) {
7334: my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
7335: $datatable .= '<tr'.$css_class.'><td><span class="LC_nobreak">'.
7336: $namesref->{$item}.
7337: '</span></td>'.
7338: '<td class="LC_left_item">';
7339: if (($item eq 'url') || ($item eq 'button')) {
7340: $datatable .= '<span class="LC_nobreak">'.
7341: '<input type="text" name="'.$caller.'_validation_'.$item.'"'.
7342: ' value="'.$currvalidation{$item}.'" size="50" /></span>';
7343: } elsif ($item eq 'fields') {
7344: my @currfields;
7345: if (ref($currvalidation{$item}) eq 'ARRAY') {
7346: @currfields = @{$currvalidation{$item}};
7347: }
7348: foreach my $field (@{$fieldsref}) {
7349: my $check = '';
7350: if (grep(/^\Q$field\E$/,@currfields)) {
7351: $check = ' checked="checked"';
7352: }
7353: $datatable .= '<span class="LC_nobreak"><label>'.
7354: '<input type="checkbox" name="'.$caller.'_validation_fields"'.
7355: ' value="'.$field.'"'.$check.' />'.$field.
7356: '</label></span> ';
7357: }
7358: } elsif ($item eq 'markup') {
1.334 raeburn 7359: $datatable .= '<textarea name="'.$caller.'_validation_markup" cols="50" rows="5">'.
1.235 raeburn 7360: $currvalidation{$item}.
1.231 raeburn 7361: '</textarea>';
1.235 raeburn 7362: }
7363: $datatable .= '</td></tr>'."\n";
7364: if (ref($rowtotal)) {
1.231 raeburn 7365: $itemcount ++;
7366: }
7367: }
1.235 raeburn 7368: if ($caller eq 'requestcourses') {
7369: my %currhash;
1.248 raeburn 7370: if (ref($settings) eq 'HASH') {
7371: if (ref($settings->{'validation'}) eq 'HASH') {
7372: if ($settings->{'validation'}{'dc'} ne '') {
7373: $currhash{$settings->{'validation'}{'dc'}} = 1;
7374: }
1.235 raeburn 7375: }
7376: }
7377: my $numinrow = 2;
7378: my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio',
7379: 'validationdc',%currhash);
1.247 raeburn 7380: my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
1.334 raeburn 7381: $datatable .= '<tr'.$css_class.'><td>';
1.235 raeburn 7382: if ($numdc > 1) {
1.247 raeburn 7383: $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)');
1.235 raeburn 7384: } else {
1.247 raeburn 7385: $datatable .= &mt('Course creation processed as: ');
1.235 raeburn 7386: }
1.247 raeburn 7387: $datatable .= '</td><td class="LC_left_item">'.$dctable.'</td></tr>';
1.235 raeburn 7388: $itemcount ++;
7389: }
7390: if (ref($rowtotal)) {
7391: $$rowtotal += $itemcount;
7392: }
1.231 raeburn 7393: return $datatable;
7394: }
7395:
1.357 raeburn 7396: sub print_privacy {
7397: my ($position,$dom,$settings,$rowtotal) = @_;
7398: my ($datatable,$css_class,$numinrow,@items,%names,$othertitle,$usertypes,$types);
7399: my $itemcount = 0;
1.417 raeburn 7400: if ($position eq 'top') {
7401: $numinrow = 2;
7402: } else {
1.357 raeburn 7403: @items = ('domain','author','course','community');
7404: %names = &Apache::lonlocal::texthash (
7405: domain => 'Assigned domain role(s)',
7406: author => 'Assigned co-author role(s)',
7407: course => 'Assigned course role(s)',
1.416 raeburn 7408: community => 'Assigned community role(s)',
1.357 raeburn 7409: );
7410: $numinrow = 4;
7411: ($othertitle,$usertypes,$types) =
7412: &Apache::loncommon::sorted_inst_types($dom);
7413: }
7414: if (($position eq 'top') || ($position eq 'middle')) {
7415: my (%by_ip,%by_location,@intdoms,@instdoms);
7416: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
7417: if ($position eq 'top') {
7418: my %curr;
7419: my @options = ('none','user','domain','auto');
7420: my %titles = &Apache::lonlocal::texthash (
7421: none => 'Not allowed',
7422: user => 'User authorizes',
7423: domain => 'DC authorizes',
7424: auto => 'Unrestricted',
7425: instdom => 'Other domain shares institution/provider',
7426: extdom => 'Other domain has different institution/provider',
1.418 raeburn 7427: notify => 'Notify when role needs authorization',
1.357 raeburn 7428: );
7429: my %names = &Apache::lonlocal::texthash (
7430: domain => 'Domain role',
7431: author => 'Co-author role',
7432: course => 'Course role',
7433: community => 'Community role',
7434: );
7435: my $primary_id = &Apache::lonnet::domain($dom,'primary');
7436: my $intdom = &Apache::lonnet::internet_dom($primary_id);
7437: foreach my $domtype ('instdom','extdom') {
7438: my (%checked,$skip);
7439: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7440: $datatable .= '<tr'.$css_class.'><td>'.$titles{$domtype}.'</td>'.
7441: '<td class="LC_left_item">';
7442: if ($domtype eq 'instdom') {
7443: unless (@instdoms > 1) {
7444: $datatable .= &mt('Nothing to set, as no domains besides [_1] are hosted by [_2]',$dom,$intdom);
7445: $skip = 1;
7446: }
7447: } elsif ($domtype eq 'extdom') {
7448: if (keys(%by_location) == 0) {
7449: $datatable .= &mt('Nothing to set, as no other hosts besides [_1]',$intdom);
7450: $skip = 1;
7451: }
7452: }
7453: unless ($skip) {
7454: foreach my $roletype ('domain','author','course','community') {
7455: $checked{'auto'} = ' checked="checked"';
7456: if (ref($settings) eq 'HASH') {
7457: if (ref($settings->{approval}) eq 'HASH') {
7458: if (ref($settings->{approval}->{$domtype}) eq 'HASH') {
7459: if ($settings->{approval}->{$domtype}->{$roletype}=~ /^(none|user|domain)$/) {
7460: $checked{$1} = ' checked="checked"';
7461: $checked{'auto'} = '';
7462: }
7463: }
7464: }
7465: }
7466: $datatable .= '<fieldset><legend>'.$names{$roletype}.'</legend>';
7467: foreach my $option (@options) {
7468: $datatable .= '<span class="LC_nobreak"><label>'.
7469: '<input type="radio" name="privacy_approval_'.$domtype.'_'.$roletype.'" '.
7470: 'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
7471: '</label></span> ';
7472: }
7473: $datatable .= '</fieldset>';
7474: }
7475: }
7476: $datatable .= '</td></tr>';
7477: $itemcount ++;
7478: }
1.417 raeburn 7479: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7480: $datatable .= '<tr'.$css_class.'><td>'.$titles{'notify'}.'</td>'.
7481: '<td class="LC_left_item">';
7482: if ((@instdoms > 1) || (keys(%by_location) > 0)) {
7483: my %curr;
7484: if (ref($settings) eq 'HASH') {
7485: if ($settings->{'notify'} ne '') {
7486: map {$curr{$_}=1;} split(/,/,$settings->{'notify'});
7487: }
7488: }
7489: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7490: my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',
7491: 'privacy_notify',%curr);
7492: if ($numdc > 0) {
7493: $datatable .= $table;
7494: } else {
7495: $datatable .= &mt('There are no active Domain Coordinators');
7496: }
7497: } else {
7498: $datatable .= &mt('Nothing to set here, as there are no other domains');
7499: }
7500: $datatable .='</td></tr>';
1.357 raeburn 7501: } elsif ($position eq 'middle') {
7502: if ((@instdoms > 1) || (keys(%by_location) > 0)) {
7503: if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
7504: foreach my $item (@{$types}) {
7505: $datatable .= &modifiable_userdata_row('privacy','othdom_'.$item,$settings,
7506: $numinrow,$itemcount,'','','','','',
7507: '',$usertypes->{$item});
7508: $itemcount ++;
7509: }
7510: }
7511: $datatable .= &modifiable_userdata_row('privacy','othdom_default',$settings,
7512: $numinrow,$itemcount,'','','','','',
7513: '',$othertitle);
7514: $itemcount ++;
7515: } else {
1.360 raeburn 7516: my (@insttypes,%insttitles);
7517: if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
7518: @insttypes = @{$types};
7519: %insttitles = %{$usertypes};
7520: }
7521: foreach my $item (@insttypes,'default') {
7522: my $title;
7523: if ($item eq 'default') {
7524: $title = $othertitle;
7525: } else {
7526: $title = $insttitles{$item};
7527: }
7528: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7529: $datatable .= '<tr'.$css_class.'>'.
7530: '<td class="LC_left_item">'.$title.'</td>'.
7531: '<td class="LC_left_item">'.
7532: &mt('Nothing to set here, as there are no other domains').
7533: '</td></tr>';
7534: $itemcount ++;
7535: }
1.357 raeburn 7536: }
7537: }
7538: } else {
7539: my $prefix;
7540: if ($position eq 'lower') {
7541: $prefix = 'priv';
7542: } else {
7543: $prefix = 'unpriv';
7544: }
7545: foreach my $item (@items) {
7546: $datatable .= &modifiable_userdata_row('privacy',$prefix.'_'.$item,$settings,
7547: $numinrow,$itemcount,'','','','','',
7548: '',$names{$item});
7549: $itemcount ++;
7550: }
7551: }
7552: if (ref($rowtotal)) {
7553: $$rowtotal += $itemcount;
7554: }
7555: return $datatable;
7556: }
7557:
1.354 raeburn 7558: sub print_passwords {
7559: my ($position,$dom,$confname,$settings,$rowtotal) = @_;
7560: my ($datatable,$css_class);
7561: my $itemcount = 0;
7562: my %titles = &Apache::lonlocal::texthash (
7563: captcha => '"Forgot Password" CAPTCHA validation',
7564: link => 'Reset link expiration (hours)',
7565: case => 'Case-sensitive usernames/e-mail',
7566: prelink => 'Information required (form 1)',
7567: postlink => 'Information required (form 2)',
7568: emailsrc => 'LON-CAPA e-mail address type(s)',
7569: customtext => 'Domain specific text (HTML)',
7570: intauth_cost => 'Encryption cost for bcrypt (positive integer)',
7571: intauth_check => 'Check bcrypt cost if authenticated',
7572: intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',
7573: permanent => 'Permanent e-mail address',
7574: critical => 'Critical notification address',
7575: notify => 'Notification address',
7576: min => 'Minimum password length',
7577: max => 'Maximum password length',
7578: chars => 'Required characters',
7579: expire => 'Password expiration (days)',
1.356 raeburn 7580: numsaved => 'Number of previous passwords to save and disallow reuse',
1.354 raeburn 7581: );
7582: if ($position eq 'top') {
7583: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
7584: my $shownlinklife = 2;
7585: my $prelink = 'both';
7586: my (%casesens,%postlink,%emailsrc,$nostdtext,$customurl);
7587: if (ref($settings) eq 'HASH') {
7588: if ($settings->{resetlink} =~ /^\d+(|\.\d*)$/) {
7589: $shownlinklife = $settings->{resetlink};
7590: }
7591: if (ref($settings->{resetcase}) eq 'ARRAY') {
7592: map { $casesens{$_} = 1; } (@{$settings->{resetcase}});
7593: }
7594: if ($settings->{resetprelink} =~ /^(both|either)$/) {
7595: $prelink = $settings->{resetprelink};
7596: }
7597: if (ref($settings->{resetpostlink}) eq 'HASH') {
7598: %postlink = %{$settings->{resetpostlink}};
7599: }
7600: if (ref($settings->{resetemail}) eq 'ARRAY') {
7601: map { $emailsrc{$_} = 1; } (@{$settings->{resetemail}});
7602: }
7603: if ($settings->{resetremove}) {
7604: $nostdtext = 1;
7605: }
7606: if ($settings->{resetcustom}) {
7607: $customurl = $settings->{resetcustom};
7608: }
7609: } else {
7610: if (ref($types) eq 'ARRAY') {
7611: foreach my $item (@{$types}) {
7612: $casesens{$item} = 1;
7613: $postlink{$item} = ['username','email'];
7614: }
7615: }
7616: $casesens{'default'} = 1;
7617: $postlink{'default'} = ['username','email'];
7618: $prelink = 'both';
7619: %emailsrc = (
7620: permanent => 1,
7621: critical => 1,
7622: notify => 1,
7623: );
7624: }
7625: $datatable = &captcha_choice('passwords',$settings,$$rowtotal);
7626: $itemcount ++;
7627: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7628: $datatable .= '<tr'.$css_class.'><td>'.$titles{'link'}.'</td>'.
7629: '<td class="LC_left_item">'.
7630: '<input type="textbox" value="'.$shownlinklife.'" '.
7631: 'name="passwords_link" size="3" /></td></tr>';
7632: $itemcount ++;
7633: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7634: $datatable .= '<tr'.$css_class.'><td>'.$titles{'case'}.'</td>'.
7635: '<td class="LC_left_item">';
7636: if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
7637: foreach my $item (@{$types}) {
7638: my $checkedcase;
7639: if ($casesens{$item}) {
7640: $checkedcase = ' checked="checked"';
7641: }
7642: $datatable .= '<span class="LC_nobreak"><label>'.
7643: '<input type="checkbox" name="passwords_case_sensitive" value="'.
7644: $item.'"'.$checkedcase.' />'.$usertypes->{$item}.'</label>'.
1.369 raeburn 7645: '</span> ';
1.354 raeburn 7646: }
7647: }
7648: my $checkedcase;
7649: if ($casesens{'default'}) {
7650: $checkedcase = ' checked="checked"';
7651: }
7652: $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.
7653: 'name="passwords_case_sensitive" value="default"'.$checkedcase.' />'.
7654: $othertitle.'</label></span></td>';
7655: $itemcount ++;
7656: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7657: my %checkedpre = (
7658: both => ' checked="checked"',
7659: either => '',
7660: );
7661: if ($prelink eq 'either') {
7662: $checkedpre{either} = ' checked="checked"';
7663: $checkedpre{both} = '';
7664: }
7665: $datatable .= '<tr'.$css_class.'><td>'.$titles{'prelink'}.'</td>'.
7666: '<td class="LC_left_item"><span class="LC_nobreak">'.
7667: '<label><input type="radio" name="passwords_prelink" value="both"'.$checkedpre{'both'}.' />'.
7668: &mt('Both username and e-mail address').'</label></span> '.
7669: '<span class="LC_nobreak"><label>'.
7670: '<input type="radio" name="passwords_prelink" value="either"'.$checkedpre{'either'}.' />'.
7671: &mt('Either username or e-mail address').'</label></span></td></tr>';
7672: $itemcount ++;
7673: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7674: $datatable .= '<tr'.$css_class.'><td>'.$titles{'postlink'}.'</td>'.
7675: '<td class="LC_left_item">';
7676: my %postlinked;
7677: if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
7678: foreach my $item (@{$types}) {
7679: undef(%postlinked);
7680: $datatable .= '<fieldset style="display: inline-block;">'.
7681: '<legend>'.$usertypes->{$item}.'</legend>';
7682: if (ref($postlink{$item}) eq 'ARRAY') {
7683: map { $postlinked{$_} = 1; } (@{$postlink{$item}});
7684: }
7685: foreach my $field ('email','username') {
7686: my $checked;
7687: if ($postlinked{$field}) {
7688: $checked = ' checked="checked"';
7689: }
7690: $datatable .= '<span class="LC_nobreak"><label>'.
7691: '<input type="checkbox" name="passwords_postlink_'.$item.'" value="'.
7692: $field.'"'.$checked.' />'.$field.'</label>'.
7693: '<span> ';
7694: }
7695: $datatable .= '</fieldset>';
7696: }
7697: }
7698: if (ref($postlink{'default'}) eq 'ARRAY') {
7699: map { $postlinked{$_} = 1; } (@{$postlink{'default'}});
7700: }
7701: $datatable .= '<fieldset style="display: inline-block;">'.
7702: '<legend>'.$othertitle.'</legend>';
7703: foreach my $field ('email','username') {
7704: my $checked;
7705: if ($postlinked{$field}) {
7706: $checked = ' checked="checked"';
7707: }
7708: $datatable .= '<span class="LC_nobreak"><label>'.
7709: '<input type="checkbox" name="passwords_postlink_default" value="'.
7710: $field.'"'.$checked.' />'.$field.'</label>'.
7711: '<span> ';
7712: }
7713: $datatable .= '</fieldset></td></tr>';
7714: $itemcount ++;
7715: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7716: $datatable .= '<tr'.$css_class.'><td>'.$titles{'emailsrc'}.'</td>'.
7717: '<td class="LC_left_item">';
7718: foreach my $type ('permanent','critical','notify') {
7719: my $checkedemail;
7720: if ($emailsrc{$type}) {
7721: $checkedemail = ' checked="checked"';
7722: }
7723: $datatable .= '<span class="LC_nobreak"><label>'.
7724: '<input type="checkbox" name="passwords_emailsrc" value="'.
7725: $type.'"'.$checkedemail.' />'.$titles{$type}.'</label>'.
7726: '<span> ';
7727: }
7728: $datatable .= '</td></tr>';
7729: $itemcount ++;
7730: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7731: my $switchserver = &check_switchserver($dom,$confname);
7732: my ($showstd,$noshowstd);
7733: if ($nostdtext) {
7734: $noshowstd = ' checked="checked"';
7735: } else {
7736: $showstd = ' checked="checked"';
7737: }
7738: $datatable .= '<tr'.$css_class.'><td>'.$titles{'customtext'}.'</td>'.
7739: '<td class="LC_left_item"><span class="LC_nobreak">'.
7740: &mt('Retain standard text:').
7741: '<label><input type="radio" name="passwords_stdtext" value="1"'.$showstd.' />'.
7742: &mt('Yes').'</label>'.' '.
7743: '<label><input type="radio" name="passwords_stdtext" value="0"'.$noshowstd.' />'.
7744: &mt('No').'</label></span><br />'.
7745: '<span class="LC_fontsize_small">'.
7746: &mt('(If you use the same account ... reset a password from this page.)').'</span><br /><br />'.
7747: &mt('Include custom text:');
7748: if ($customurl) {
1.369 raeburn 7749: my $link = &Apache::loncommon::modal_link($customurl,&mt('custom text'),600,500,
1.354 raeburn 7750: undef,undef,undef,undef,'background-color:#ffffff');
7751: $datatable .= '<span class="LC_nobreak"> '.$link.
7752: '<label><input type="checkbox" name="passwords_custom_del"'.
7753: ' value="1" />'.&mt('Delete?').'</label></span>'.
7754: ' <span class="LC_nobreak"> '.&mt('Replace:').'</span>';
7755: }
7756: if ($switchserver) {
7757: $datatable .= '<span class="LC_nobreak"> '.&mt('Upload to library server: [_1]',$switchserver).'</span>';
7758: } else {
7759: $datatable .='<span class="LC_nobreak"> '.
7760: '<input type="file" name="passwords_customfile" /></span>';
7761: }
7762: $datatable .= '</td></tr>';
7763: } elsif ($position eq 'middle') {
7764: my %domconf = &Apache::lonnet::get_dom('configuration',['defaults'],$dom);
7765: my @items = ('intauth_cost','intauth_check','intauth_switch');
7766: my %defaults;
7767: if (ref($domconf{'defaults'}) eq 'HASH') {
7768: %defaults = %{$domconf{'defaults'}};
7769: if ($defaults{'intauth_cost'} !~ /^\d+$/) {
7770: $defaults{'intauth_cost'} = 10;
7771: }
7772: if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {
7773: $defaults{'intauth_check'} = 0;
7774: }
7775: if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {
7776: $defaults{'intauth_switch'} = 0;
7777: }
7778: } else {
7779: %defaults = (
7780: 'intauth_cost' => 10,
7781: 'intauth_check' => 0,
7782: 'intauth_switch' => 0,
7783: );
7784: }
7785: foreach my $item (@items) {
7786: if ($itemcount%2) {
7787: $css_class = '';
7788: } else {
7789: $css_class = ' class="LC_odd_row" ';
7790: }
7791: $datatable .= '<tr'.$css_class.'>'.
7792: '<td><span class="LC_nobreak">'.$titles{$item}.
7793: '</span></td><td class="LC_left_item" colspan="3">';
7794: if ($item eq 'intauth_switch') {
7795: my @options = (0,1,2);
7796: my %optiondesc = &Apache::lonlocal::texthash (
7797: 0 => 'No',
7798: 1 => 'Yes',
7799: 2 => 'Yes, and copy existing passwd file to passwd.bak file',
7800: );
7801: $datatable .= '<table width="100%">';
7802: foreach my $option (@options) {
7803: my $checked = ' ';
7804: if ($defaults{$item} eq $option) {
7805: $checked = ' checked="checked"';
7806: }
7807: $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
7808: '<label><input type="radio" name="'.$item.
7809: '" value="'.$option.'"'.$checked.' />'.
7810: $optiondesc{$option}.'</label></span></td></tr>';
7811: }
7812: $datatable .= '</table>';
7813: } elsif ($item eq 'intauth_check') {
7814: my @options = (0,1,2);
7815: my %optiondesc = &Apache::lonlocal::texthash (
7816: 0 => 'No',
7817: 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
7818: 2 => 'Yes, disallow login if stored cost is less than domain default',
7819: );
7820: $datatable .= '<table width="100%">';
7821: foreach my $option (@options) {
7822: my $checked = ' ';
7823: my $onclick;
7824: if ($defaults{$item} eq $option) {
7825: $checked = ' checked="checked"';
7826: }
7827: if ($option == 2) {
7828: $onclick = ' onclick="javascript:warnIntAuth(this);"';
7829: }
7830: $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
7831: '<label><input type="radio" name="'.$item.
7832: '" value="'.$option.'"'.$checked.$onclick.' />'.
7833: $optiondesc{$option}.'</label></span></td></tr>';
7834: }
7835: $datatable .= '</table>';
7836: } else {
7837: $datatable .= '<input type="text" name="'.$item.'" value="'.
7838: $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />';
7839: }
7840: $datatable .= '</td></tr>';
7841: $itemcount ++;
7842: }
7843: } elsif ($position eq 'lower') {
1.405 raeburn 7844: $datatable .= &password_rules('passwords',\$itemcount,$settings);
1.354 raeburn 7845: } else {
1.359 raeburn 7846: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
7847: my %ownerchg = (
7848: by => {},
7849: for => {},
7850: );
7851: my %ownertitles = &Apache::lonlocal::texthash (
7852: by => 'Course owner status(es) allowed',
7853: for => 'Student status(es) allowed',
7854: );
1.354 raeburn 7855: if (ref($settings) eq 'HASH') {
1.359 raeburn 7856: if (ref($settings->{crsownerchg}) eq 'HASH') {
7857: if (ref($settings->{crsownerchg}{'by'}) eq 'ARRAY') {
7858: map { $ownerchg{by}{$_} = 1; } (@{$settings->{crsownerchg}{'by'}});
7859: }
7860: if (ref($settings->{crsownerchg}{'for'}) eq 'ARRAY') {
7861: map { $ownerchg{for}{$_} = 1; } (@{$settings->{crsownerchg}{'for'}});
7862: }
1.354 raeburn 7863: }
7864: }
7865: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7866: $datatable .= '<tr '.$css_class.'>'.
7867: '<td>'.
7868: &mt('Requirements').'<ul>'.
1.359 raeburn 7869: '<li>'.&mt("Course 'type' is not a Community or Placement Test").'</li>'.
1.354 raeburn 7870: '<li>'.&mt('User is Course Coordinator and also course owner').'</li>'.
7871: '<li>'.&mt("Student's only active roles are student role(s) in course(s) owned by this user").'</li>'.
1.359 raeburn 7872: '<li>'.&mt('User, course, and student share same domain').'</li>'.
1.354 raeburn 7873: '</ul>'.
7874: '</td>'.
1.359 raeburn 7875: '<td class="LC_left_item">';
7876: foreach my $item ('by','for') {
7877: $datatable .= '<fieldset style="display: inline-block;">'.
7878: '<legend>'.$ownertitles{$item}.'</legend>';
7879: if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
7880: foreach my $type (@{$types}) {
7881: my $checked;
7882: if ($ownerchg{$item}{$type}) {
7883: $checked = ' checked="checked"';
7884: }
7885: $datatable .= '<span class="LC_nobreak"><label>'.
7886: '<input type="checkbox" name="passwords_crsowner_'.$item.'" value="'.
7887: $type.'"'.$checked.' />'.$usertypes->{$type}.'</label>'.
1.369 raeburn 7888: '</span> ';
1.359 raeburn 7889: }
7890: }
7891: my $checked;
7892: if ($ownerchg{$item}{'default'}) {
7893: $checked = ' checked="checked"';
7894: }
7895: $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.
7896: 'name="passwords_crsowner_'.$item.'" value="default"'.$checked.' />'.
7897: $othertitle.'</label></span></fieldset>';
7898: }
7899: $datatable .= '</td></tr>';
1.354 raeburn 7900: }
7901: return $datatable;
7902: }
7903:
1.405 raeburn 7904: sub password_rules {
7905: my ($prefix,$itemcountref,$settings) = @_;
7906: my ($min,$max,%chars,$expire,$numsaved,$numinrow);
7907: my %titles;
7908: if ($prefix eq 'passwords') {
7909: %titles = &Apache::lonlocal::texthash (
7910: min => 'Minimum password length',
7911: max => 'Maximum password length',
7912: chars => 'Required characters',
7913: );
1.421 raeburn 7914: } elsif (($prefix eq 'ltisecrets') || ($prefix eq 'toolsecrets')) {
1.405 raeburn 7915: %titles = &Apache::lonlocal::texthash (
7916: min => 'Minimum secret length',
7917: max => 'Maximum secret length',
7918: chars => 'Required characters',
7919: );
7920: }
7921: $min = $Apache::lonnet::passwdmin;
7922: my $datatable;
7923: my $itemcount;
7924: if (ref($itemcountref)) {
7925: $itemcount = $$itemcountref;
7926: }
7927: if (ref($settings) eq 'HASH') {
7928: if ($settings->{min}) {
7929: $min = $settings->{min};
7930: }
7931: if ($settings->{max}) {
7932: $max = $settings->{max};
7933: }
7934: if (ref($settings->{chars}) eq 'ARRAY') {
7935: map { $chars{$_} = 1; } (@{$settings->{chars}});
7936: }
1.425 raeburn 7937: if ($prefix eq 'passwords') {
1.405 raeburn 7938: if ($settings->{expire}) {
7939: $expire = $settings->{expire};
7940: }
7941: if ($settings->{numsaved}) {
7942: $numsaved = $settings->{numsaved};
7943: }
7944: }
7945: }
7946: my %rulenames = &Apache::lonlocal::texthash(
7947: uc => 'At least one upper case letter',
7948: lc => 'At least one lower case letter',
7949: num => 'At least one number',
7950: spec => 'At least one non-alphanumeric',
7951: );
7952: my $css_class = $itemcount%2?' class="LC_odd_row"':'';
7953: $datatable .= '<tr'.$css_class.'><td>'.$titles{'min'}.'</td>'.
7954: '<td class="LC_left_item"><span class="LC_nobreak">'.
7955: '<input type="text" name="'.$prefix.'_min" value="'.$min.'" size="3" '.
7956: 'onblur="javascript:warnInt'.$prefix.'(this);" />'.
7957: '<span class="LC_fontsize_small"> '.&mt('(Enter an integer: 7 or larger)').'</span>'.
7958: '</span></td></tr>';
7959: $itemcount ++;
7960: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7961: $datatable .= '<tr'.$css_class.'><td>'.$titles{'max'}.'</td>'.
7962: '<td class="LC_left_item"><span class="LC_nobreak">'.
7963: '<input type="text" name="'.$prefix.'_max" value="'.$max.'" size="3" '.
7964: 'onblur="javascript:warnInt'.$prefix.'(this);" />'.
7965: '<span class="LC_fontsize_small"> '.&mt('(Leave blank for no maximum)').'</span>'.
7966: '</span></td></tr>';
7967: $itemcount ++;
7968: $css_class = $itemcount%2?' class="LC_odd_row"':'';
7969: $datatable .= '<tr'.$css_class.'><td>'.$titles{'chars'}.'<br />'.
7970: '<span class="LC_nobreak LC_fontsize_small">'.&mt('(Leave unchecked if not required)').
7971: '</span></td>';
7972: my $numinrow = 2;
7973: my @possrules = ('uc','lc','num','spec');
7974: $datatable .= '<td class="LC_left_item"><table>';
7975: for (my $i=0; $i<@possrules; $i++) {
7976: my ($rem,$checked);
7977: if ($chars{$possrules[$i]}) {
7978: $checked = ' checked="checked"';
7979: }
7980: $rem = $i%($numinrow);
7981: if ($rem == 0) {
7982: if ($i > 0) {
7983: $datatable .= '</tr>';
7984: }
7985: $datatable .= '<tr>';
7986: }
7987: $datatable .= '<td><span class="LC_nobreak"><label>'.
7988: '<input type="checkbox" name="'.$prefix.'_chars" value="'.$possrules[$i].'"'.$checked.' />'.
7989: $rulenames{$possrules[$i]}.'</label></span></td>';
7990: }
7991: my $rem = @possrules%($numinrow);
7992: my $colsleft = $numinrow - $rem;
7993: if ($colsleft > 1 ) {
7994: $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
7995: ' </td>';
7996: } elsif ($colsleft == 1) {
7997: $datatable .= '<td class="LC_left_item"> </td>';
7998: }
7999: $datatable .='</table></td></tr>';
8000: $itemcount ++;
8001: if ($prefix eq 'passwords') {
8002: $titles{'expire'} = &mt('Password expiration (days)');
8003: $titles{'numsaved'} = &mt('Number of previous passwords to save and disallow reuse');
8004: $css_class = $itemcount%2?' class="LC_odd_row"':'';
8005: $datatable .= '<tr'.$css_class.'><td>'.$titles{'expire'}.'</td>'.
8006: '<td class="LC_left_item"><span class="LC_nobreak">'.
8007: '<input type="text" name="'.$prefix.'_expire" value="'.$expire.'" size="4" '.
8008: 'onblur="javascript:warnInt'.$prefix.'(this);" />'.
8009: '<span class="LC_fontsize_small"> '.&mt('(Leave blank for no expiration)').'</span>'.
8010: '</span></td></tr>';
8011: $itemcount ++;
8012: $css_class = $itemcount%2?' class="LC_odd_row"':'';
8013: $datatable .= '<tr'.$css_class.'><td>'.$titles{'numsaved'}.'</td>'.
8014: '<td class="LC_left_item"><span class="LC_nobreak">'.
8015: '<input type="text" name="'.$prefix.'_numsaved" value="'.$numsaved.'" size="3" '.
8016: 'onblur="javascript:warnInt'.$prefix.'(this);" />'.
8017: '<span class="LC_fontsize_small"> '.&mt('(Leave blank to not save previous passwords)').'</span>'.
8018: '</span></td></tr>';
8019: $itemcount ++;
8020: }
8021: if (ref($itemcountref)) {
8022: $$itemcountref += $itemcount;
8023: }
8024: return $datatable;
8025: }
8026:
1.373 raeburn 8027: sub print_wafproxy {
8028: my ($position,$dom,$settings,$rowtotal) = @_;
8029: my $css_class;
8030: my $itemcount = 0;
8031: my $datatable;
8032: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.388 raeburn 8033: my (%othercontrol,%otherdoms,%aliases,%saml,%values,$setdom,$showdom);
1.374 raeburn 8034: my %lt = &wafproxy_titles();
1.373 raeburn 8035: foreach my $server (sort(keys(%servers))) {
8036: my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
1.381 raeburn 8037: next if ($serverhome eq '');
1.373 raeburn 8038: my $serverdom;
8039: if ($serverhome ne $server) {
8040: $serverdom = &Apache::lonnet::host_domain($serverhome);
1.381 raeburn 8041: if (($serverdom ne '') && (&Apache::lonnet::domain($serverdom) ne '')) {
8042: $othercontrol{$server} = $serverdom;
8043: }
1.373 raeburn 8044: } else {
8045: $serverdom = &Apache::lonnet::host_domain($server);
1.381 raeburn 8046: next if (($serverdom eq '') || (&Apache::lonnet::domain($serverdom) eq ''));
1.373 raeburn 8047: if ($serverdom ne $dom) {
8048: $othercontrol{$server} = $serverdom;
8049: } else {
8050: $setdom = 1;
8051: if (ref($settings) eq 'HASH') {
8052: if (ref($settings->{'alias'}) eq 'HASH') {
8053: $aliases{$dom} = $settings->{'alias'};
1.381 raeburn 8054: if ($aliases{$dom} ne '') {
8055: $showdom = 1;
8056: }
1.373 raeburn 8057: }
1.388 raeburn 8058: if (ref($settings->{'saml'}) eq 'HASH') {
8059: $saml{$dom} = $settings->{'saml'};
8060: }
1.373 raeburn 8061: }
8062: }
8063: }
8064: }
1.381 raeburn 8065: if ($setdom) {
8066: %{$values{$dom}} = ();
8067: if (ref($settings) eq 'HASH') {
8068: foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
8069: $values{$dom}{$item} = $settings->{$item};
8070: }
8071: }
8072: }
1.373 raeburn 8073: if (keys(%othercontrol)) {
8074: %otherdoms = reverse(%othercontrol);
8075: foreach my $domain (keys(%otherdoms)) {
8076: %{$values{$domain}} = ();
8077: my %config = &Apache::lonnet::get_dom('configuration',['wafproxy'],$domain);
1.383 raeburn 8078: if (ref($config{'wafproxy'}) eq 'HASH') {
8079: $aliases{$domain} = $config{'wafproxy'}{'alias'};
1.425 raeburn 8080: if (exists($config{'wafproxy'}{'saml'})) {
1.388 raeburn 8081: $saml{$domain} = $config{'wafproxy'}{'saml'};
8082: }
1.383 raeburn 8083: foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
8084: $values{$domain}{$item} = $config{'wafproxy'}{$item};
1.373 raeburn 8085: }
8086: }
8087: }
8088: }
8089: if ($position eq 'top') {
8090: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.381 raeburn 8091: my %aliasinfo;
1.373 raeburn 8092: foreach my $server (sort(keys(%servers))) {
1.381 raeburn 8093: $itemcount ++;
8094: my $dom_in_effect;
8095: my $aliasrows = '<tr>'.
1.383 raeburn 8096: '<td class="LC_left_item" style="vertical-align: baseline;">'.
8097: &mt('Hostname').': '.
8098: '<i>'.&Apache::lonnet::hostname($server).'</i></td><td> </td>';
1.373 raeburn 8099: if ($othercontrol{$server}) {
1.381 raeburn 8100: $dom_in_effect = $othercontrol{$server};
1.388 raeburn 8101: my ($current,$forsaml);
1.383 raeburn 8102: if (ref($aliases{$dom_in_effect}) eq 'HASH') {
8103: $current = $aliases{$dom_in_effect}{$server};
1.373 raeburn 8104: }
1.388 raeburn 8105: if (ref($saml{$dom_in_effect}) eq 'HASH') {
8106: if ($saml{$dom_in_effect}{$server}) {
8107: $forsaml = 1;
8108: }
8109: }
1.383 raeburn 8110: $aliasrows .= '<td class="LC_left_item" style="vertical-align: baseline;">'.
8111: &mt('Alias').': ';
1.373 raeburn 8112: if ($current) {
1.381 raeburn 8113: $aliasrows .= $current;
1.388 raeburn 8114: if ($forsaml) {
1.396 raeburn 8115: $aliasrows .= ' ('.&mt('also for SSO Auth').')';
1.388 raeburn 8116: }
1.373 raeburn 8117: } else {
1.383 raeburn 8118: $aliasrows .= &mt('None');
1.373 raeburn 8119: }
1.383 raeburn 8120: $aliasrows .= ' <span class="LC_small">('.
8121: &mt('controlled by domain: [_1]',
8122: '<b>'.$dom_in_effect.'</b>').')</span></td>';
1.373 raeburn 8123: } else {
1.381 raeburn 8124: $dom_in_effect = $dom;
1.388 raeburn 8125: my ($current,$samlon,$samloff);
8126: $samloff = ' checked="checked"';
1.373 raeburn 8127: if (ref($aliases{$dom}) eq 'HASH') {
8128: if ($aliases{$dom}{$server}) {
8129: $current = $aliases{$dom}{$server};
8130: }
8131: }
1.388 raeburn 8132: if (ref($saml{$dom}) eq 'HASH') {
8133: if ($saml{$dom}{$server}) {
8134: $samlon = $samloff;
8135: undef($samloff);
8136: }
8137: }
1.383 raeburn 8138: $aliasrows .= '<td class="LC_left_item" style="vertical-align: baseline;">'.
8139: &mt('Alias').': '.
1.381 raeburn 8140: '<input type="text" name="wafproxy_alias_'.$server.'" '.
1.388 raeburn 8141: 'value="'.$current.'" size="30" />'.
8142: (' 'x2).'<span class="LC_nobreak">'.
1.396 raeburn 8143: &mt('Alias used for SSO Auth').': <label>'.
1.388 raeburn 8144: '<input type="radio" value="0"'.$samloff.' name="wafproxy_alias_saml_'.$server.'" />'.
1.425 raeburn 8145: &mt('No').'</label> <label>'.
1.388 raeburn 8146: '<input type="radio" value="1"'.$samlon.' name="wafproxy_alias_saml_'.$server.'" />'.
8147: &mt('Yes').'</label></span>'.
1.425 raeburn 8148: '</td>';
1.381 raeburn 8149: }
8150: $aliasrows .= '</tr>';
8151: $aliasinfo{$dom_in_effect} .= $aliasrows;
8152: }
8153: if ($aliasinfo{$dom}) {
8154: my ($onclick,$wafon,$wafoff,$showtable);
8155: $onclick = ' onclick="javascript:toggleWAF();"';
8156: $wafoff = ' checked="checked"';
8157: $showtable = ' style="display:none";';
8158: if ($showdom) {
8159: $wafon = $wafoff;
8160: $wafoff = '';
8161: $showtable = ' style="display:inline;"';
8162: }
8163: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
8164: $datatable = '<tr'.$css_class.'>'.
8165: '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'<br />'.
8166: '<span class="LC_nobreak">'.&mt('WAF in use?').' <label>'.
8167: '<input type="radio" name="wafproxy_'.$dom.'" value="1"'.$wafon.$onclick.' />'.
8168: &mt('Yes').'</label>'.(' 'x2).'<label>'.
8169: '<input type="radio" name="wafproxy_'.$dom.'" value="0"'.$wafoff.$onclick.' />'.
8170: &mt('No').'</label></span></td>'.
8171: '<td class="LC_left_item">'.
8172: '<table id="wafproxy_table"'.$showtable.'>'.$aliasinfo{$dom}.
8173: '</table></td></tr>';
8174: $itemcount++;
8175: }
1.383 raeburn 8176: if (keys(%otherdoms)) {
8177: foreach my $key (sort(keys(%otherdoms))) {
1.381 raeburn 8178: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
1.383 raeburn 8179: $datatable .= '<tr'.$css_class.'>'.
8180: '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$key.'</b>').'</td>'.
8181: '<td class="LC_left_item"><table>'.$aliasinfo{$key}.
8182: '</table></td></tr>';
1.381 raeburn 8183: $itemcount++;
1.373 raeburn 8184: }
8185: }
8186: } else {
1.383 raeburn 8187: my %ip_methods = &remoteip_methods();
1.373 raeburn 8188: if ($setdom) {
8189: $itemcount ++;
8190: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
1.381 raeburn 8191: my ($nowafstyle,$wafstyle,$curr_remotip,$currwafdisplay,$vpndircheck,$vpnaliascheck,
1.382 raeburn 8192: $currwafvpn,$wafrangestyle,$alltossl,$ssltossl);
1.381 raeburn 8193: $wafstyle = ' style="display:none;"';
8194: $nowafstyle = ' style="display:table-row;"';
8195: $currwafdisplay = ' style="display: none"';
8196: $wafrangestyle = ' style="display: none"';
8197: $curr_remotip = 'n';
1.382 raeburn 8198: $ssltossl = ' checked="checked"';
1.381 raeburn 8199: if ($showdom) {
8200: $wafstyle = ' style="display:table-row;"';
8201: $nowafstyle = ' style="display:none;"';
8202: if (keys(%{$values{$dom}})) {
8203: if ($values{$dom}{remoteip} =~ /^[nmh]$/) {
8204: $curr_remotip = $values{$dom}{remoteip};
8205: }
8206: if ($curr_remotip eq 'h') {
8207: $currwafdisplay = ' style="display:table-row"';
8208: $wafrangestyle = ' style="display:inline-block;"';
8209: }
1.382 raeburn 8210: if ($values{$dom}{'sslopt'}) {
8211: $alltossl = ' checked="checked"';
8212: $ssltossl = '';
8213: }
1.381 raeburn 8214: }
8215: if (($values{$dom}{'vpnint'} ne '') || ($values{$dom}{'vpnext'} ne '')) {
8216: $vpndircheck = ' checked="checked"';
8217: $currwafvpn = ' style="display:table-row;"';
8218: $wafrangestyle = ' style="display:inline-block;"';
8219: } else {
8220: $vpnaliascheck = ' checked="checked"';
8221: $currwafvpn = ' style="display:none;"';
8222: }
8223: }
8224: $datatable .= '<tr'.$css_class.' id="nowafproxyrow_'.$dom.'"'.$wafstyle.'>'.
8225: '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'</td>'.
8226: '<td class="LC_right_item">'.&mt('WAF not in use, nothing to set').'</td>'.
8227: '</tr>'.
8228: '<tr'.$css_class.' id="wafproxyrow_'.$dom.'"'.$wafstyle.'>'.
1.374 raeburn 8229: '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'<br /><br />'.
1.381 raeburn 8230: '<div id="wafproxyranges_'.$dom.'">'.&mt('Format for comma separated IP ranges').':<br />'.
1.393 raeburn 8231: &mt('A.B.C.D/N or A.B.C.D-E.F.G.H').'<br />'.
8232: &mt('Range(s) stored in CIDR notation').'</div></td>'.
1.381 raeburn 8233: '<td class="LC_left_item"><table>'.
8234: '<tr>'.
8235: '<td valign="top">'.$lt{'remoteip'}.': '.
8236: '<select name="wafproxy_remoteip" id="wafproxy_remoteip" onchange="javascript:updateWAF();">';
8237: foreach my $option ('m','h','n') {
8238: my $sel;
8239: if ($option eq $curr_remotip) {
8240: $sel = ' selected="selected"';
8241: }
8242: $datatable .= '<option value="'.$option.'"'.$sel.'>'.
8243: $ip_methods{$option}.'</option>';
8244: }
8245: $datatable .= '</select></td></tr>'."\n".
8246: '<tr id="wafproxy_header"'.$currwafdisplay.'><td>'.
8247: $lt{'ipheader'}.': '.
8248: '<input type="text" value="'.$values{$dom}{'ipheader'}.'" '.
8249: 'name="wafproxy_ipheader" />'.
8250: '</td></tr>'."\n".
8251: '<tr id="wafproxy_trust"'.$currwafdisplay.'><td>'.
1.382 raeburn 8252: $lt{'trusted'}.':<br />'.
1.381 raeburn 8253: '<textarea name="wafproxy_trusted" rows="3" cols="80">'.
8254: $values{$dom}{'trusted'}.'</textarea>'.
8255: '</td></tr>'."\n".
8256: '<tr><td><hr /></td></tr>'."\n".
8257: '<tr>'.
8258: '<td valign="top">'.$lt{'vpnaccess'}.':<br /><span class="LC_nobreak">'.
8259: '<label><input type="radio" name="wafproxy_vpnaccess"'.$vpndircheck.' value="1" onclick="javascript:checkWAF();" />'.
8260: $lt{'vpndirect'}.'</label>'.(' 'x2).
8261: '<label><input type="radio" name="wafproxy_vpnaccess"'.$vpnaliascheck.' value="0" onclick="javascript:checkWAF();" />'.
8262: $lt{'vpnaliased'}.'</label></span></td></tr>';
8263: foreach my $item ('vpnint','vpnext') {
8264: $datatable .= '<tr id="wafproxy_show_'.$item.'"'.$currwafvpn.'>'.
1.382 raeburn 8265: '<td valign="top">'.$lt{$item}.':<br />'.
1.381 raeburn 8266: '<textarea name="wafproxy_'.$item.'" rows="3" cols="80">'.
8267: $values{$dom}{$item}.'</textarea>'.
8268: '</td></tr>'."\n";
1.373 raeburn 8269: }
1.382 raeburn 8270: $datatable .= '<tr><td><hr /></td></tr>'."\n".
8271: '<tr>'.
8272: '<td valign="top">'.$lt{'sslopt'}.':<br /><span class="LC_nobreak">'.
8273: '<label><input type="radio" name="wafproxy_sslopt"'.$alltossl.' value="1" />'.
8274: $lt{'alltossl'}.'</label>'.(' 'x2).
8275: '<label><input type="radio" name="wafproxy_sslopt"'.$ssltossl.' value="0" />'.
8276: $lt{'ssltossl'}.'</label></span></td></tr>'."\n".
8277: '</table></td></tr>';
1.373 raeburn 8278: }
8279: if (keys(%otherdoms)) {
8280: foreach my $domain (sort(keys(%otherdoms))) {
8281: $itemcount ++;
8282: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
8283: $datatable .= '<tr'.$css_class.'>'.
1.383 raeburn 8284: '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$domain.'</b>').'</td>'.
1.374 raeburn 8285: '<td class="LC_left_item"><table>';
1.382 raeburn 8286: foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
1.373 raeburn 8287: my $showval = &mt('None');
1.382 raeburn 8288: if ($item eq 'ssl') {
8289: $showval = $lt{'ssltossl'};
8290: }
1.373 raeburn 8291: if ($values{$domain}{$item}) {
1.381 raeburn 8292: $showval = $values{$domain}{$item};
1.382 raeburn 8293: if ($item eq 'ssl') {
8294: $showval = $lt{'alltossl'};
1.383 raeburn 8295: } elsif ($item eq 'remoteip') {
8296: $showval = $ip_methods{$values{$domain}{$item}};
1.382 raeburn 8297: }
1.373 raeburn 8298: }
8299: $datatable .= '<tr>'.
8300: '<td>'.$lt{$item}.': '.$showval.'</td></tr>';
8301: }
1.381 raeburn 8302: $datatable .= '</table></td></tr>';
1.373 raeburn 8303: }
8304: }
8305: }
8306: $$rowtotal += $itemcount;
8307: return $datatable;
8308: }
8309:
8310: sub wafproxy_titles {
8311: return &Apache::lonlocal::texthash(
1.381 raeburn 8312: remoteip => "Method for determining user's IP",
8313: ipheader => 'Request header containing remote IP',
8314: trusted => 'Trusted IP range(s)',
8315: vpnaccess => 'Access from institutional VPN',
8316: vpndirect => 'via regular hostname (no WAF)',
8317: vpnaliased => 'via aliased hostname (WAF)',
8318: vpnint => 'Internal IP Range(s) for VPN sessions',
8319: vpnext => 'IP Range(s) for backend WAF connections',
1.382 raeburn 8320: sslopt => 'Forwarding http/https',
1.381 raeburn 8321: alltossl => 'WAF forwards both http and https requests to https',
8322: ssltossl => 'WAF forwards http requests to http and https to https',
8323: );
8324: }
8325:
8326: sub remoteip_methods {
8327: return &Apache::lonlocal::texthash(
8328: m => 'Use Apache mod_remoteip',
8329: h => 'Use headers parsed by LON-CAPA',
8330: n => 'Not in use',
1.373 raeburn 8331: );
8332: }
8333:
1.137 raeburn 8334: sub print_usersessions {
8335: my ($position,$dom,$settings,$rowtotal) = @_;
1.279 raeburn 8336: my ($css_class,$datatable,$itemcount,%checked,%choices);
1.275 raeburn 8337: my (%by_ip,%by_location,@intdoms,@instdoms);
8338: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
1.145 raeburn 8339:
8340: my @alldoms = &Apache::lonnet::all_domains();
1.152 raeburn 8341: my %serverhomes = %Apache::lonnet::serverhomeIDs;
1.149 raeburn 8342: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.152 raeburn 8343: my %altids = &id_for_thisdom(%servers);
1.145 raeburn 8344: if ($position eq 'top') {
1.152 raeburn 8345: if (keys(%serverhomes) > 1) {
1.145 raeburn 8346: my %spareid = ¤t_offloads_to($dom,$settings,\%servers);
1.371 raeburn 8347: my ($curroffloadnow,$curroffloadoth);
1.261 raeburn 8348: if (ref($settings) eq 'HASH') {
8349: if (ref($settings->{'offloadnow'}) eq 'HASH') {
8350: $curroffloadnow = $settings->{'offloadnow'};
8351: }
1.371 raeburn 8352: if (ref($settings->{'offloadoth'}) eq 'HASH') {
8353: $curroffloadoth = $settings->{'offloadoth'};
8354: }
1.261 raeburn 8355: }
1.371 raeburn 8356: my $other_insts = scalar(keys(%by_location));
8357: $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,
8358: $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);
1.145 raeburn 8359: } else {
1.140 raeburn 8360: $datatable .= '<tr'.$css_class.'><td colspan="2">'.
1.279 raeburn 8361: &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.').
8362: '</td></tr>';
1.140 raeburn 8363: }
1.137 raeburn 8364: } else {
1.279 raeburn 8365: my %titles = &usersession_titles();
8366: my ($prefix,@types);
8367: if ($position eq 'bottom') {
8368: $prefix = 'remote';
8369: @types = ('version','excludedomain','includedomain');
1.145 raeburn 8370: } else {
1.279 raeburn 8371: $prefix = 'hosted';
8372: @types = ('excludedomain','includedomain');
8373: }
8374: ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
8375: }
8376: $$rowtotal += $itemcount;
8377: return $datatable;
8378: }
8379:
8380: sub rules_by_location {
8381: my ($settings,$prefix,$by_location,$by_ip,$types,$titles) = @_;
8382: my ($datatable,$itemcount,$css_class);
8383: if (keys(%{$by_location}) == 0) {
8384: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
8385: $datatable = '<tr'.$css_class.'><td colspan="2">'.
8386: &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
8387: '</td></tr>';
8388: $itemcount = 1;
8389: } else {
8390: $itemcount = 0;
8391: my $numinrow = 5;
8392: my (%current,%checkedon,%checkedoff);
8393: my @locations = sort(keys(%{$by_location}));
8394: foreach my $type (@{$types}) {
8395: $checkedon{$type} = '';
8396: $checkedoff{$type} = ' checked="checked"';
8397: }
8398: if (ref($settings) eq 'HASH') {
8399: if (ref($settings->{$prefix}) eq 'HASH') {
8400: foreach my $key (keys(%{$settings->{$prefix}})) {
8401: $current{$key} = $settings->{$prefix}{$key};
8402: if ($key eq 'version') {
8403: if ($current{$key} ne '') {
1.145 raeburn 8404: $checkedon{$key} = ' checked="checked"';
8405: $checkedoff{$key} = '';
8406: }
1.279 raeburn 8407: } elsif (ref($current{$key}) eq 'ARRAY') {
8408: $checkedon{$key} = ' checked="checked"';
8409: $checkedoff{$key} = '';
1.137 raeburn 8410: }
8411: }
8412: }
1.279 raeburn 8413: }
8414: foreach my $type (@{$types}) {
8415: next if ($type ne 'version' && !@locations);
8416: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
8417: $datatable .= '<tr'.$css_class.'>
8418: <td><span class="LC_nobreak">'.$titles->{$type}.'</span><br />
8419: <span class="LC_nobreak">
8420: <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>
8421: <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>';
8422: if ($type eq 'version') {
8423: my @lcversions = &Apache::lonnet::all_loncaparevs();
8424: my $selector = '<select name="'.$prefix.'_version">';
8425: foreach my $version (@lcversions) {
8426: my $selected = '';
8427: if ($current{'version'} eq $version) {
8428: $selected = ' selected="selected"';
1.145 raeburn 8429: }
1.279 raeburn 8430: $selector .= ' <option value="'.$version.'"'.
8431: $selected.'>'.$version.'</option>';
8432: }
8433: $selector .= '</select> ';
8434: $datatable .= &mt('remote server must be version: [_1] or later',$selector);
8435: } else {
8436: $datatable.= '<div><input type="button" value="'.&mt('check all').'" '.
8437: 'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
8438: ' />'.(' 'x2).
8439: '<input type="button" value="'.&mt('uncheck all').'" '.
8440: 'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
8441: "\n".
8442: '</div><div><table>';
8443: my $rem;
8444: for (my $i=0; $i<@locations; $i++) {
8445: my ($showloc,$value,$checkedtype);
8446: if (ref($by_location->{$locations[$i]}) eq 'ARRAY') {
8447: my $ip = $by_location->{$locations[$i]}->[0];
8448: if (ref($by_ip->{$ip}) eq 'ARRAY') {
8449: $value = join(':',@{$by_ip->{$ip}});
8450: $showloc = join(', ',@{$by_ip->{$ip}});
8451: if (ref($current{$type}) eq 'ARRAY') {
8452: foreach my $loc (@{$by_ip->{$ip}}) {
8453: if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
8454: $checkedtype = ' checked="checked"';
8455: last;
1.145 raeburn 8456: }
1.138 raeburn 8457: }
8458: }
8459: }
1.137 raeburn 8460: }
1.279 raeburn 8461: $rem = $i%($numinrow);
8462: if ($rem == 0) {
8463: if ($i > 0) {
8464: $datatable .= '</tr>';
8465: }
8466: $datatable .= '<tr>';
8467: }
8468: $datatable .= '<td class="LC_left_item">'.
8469: '<span class="LC_nobreak"><label>'.
8470: '<input type="checkbox" name="'.$prefix.'_'.$type.
8471: '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
8472: '</label></span></td>';
8473: }
8474: $rem = @locations%($numinrow);
8475: my $colsleft = $numinrow - $rem;
8476: if ($colsleft > 1 ) {
8477: $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
8478: ' </td>';
8479: } elsif ($colsleft == 1) {
8480: $datatable .= '<td class="LC_left_item"> </td>';
1.137 raeburn 8481: }
1.279 raeburn 8482: $datatable .= '</tr></table>';
1.137 raeburn 8483: }
1.279 raeburn 8484: $datatable .= '</td></tr>';
8485: $itemcount ++;
1.137 raeburn 8486: }
8487: }
1.279 raeburn 8488: return ($datatable,$itemcount);
1.137 raeburn 8489: }
8490:
1.275 raeburn 8491: sub print_ssl {
8492: my ($position,$dom,$settings,$rowtotal) = @_;
8493: my ($css_class,$datatable);
8494: my $itemcount = 1;
8495: if ($position eq 'top') {
1.281 raeburn 8496: my $primary_id = &Apache::lonnet::domain($dom,'primary');
8497: my $intdom = &Apache::lonnet::internet_dom($primary_id);
8498: my $same_institution;
8499: if ($intdom ne '') {
8500: my $internet_names = &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
8501: if (ref($internet_names) eq 'ARRAY') {
8502: if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
8503: $same_institution = 1;
8504: }
8505: }
8506: }
1.275 raeburn 8507: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.281 raeburn 8508: $datatable = '<tr'.$css_class.'><td colspan="2">';
8509: if ($same_institution) {
8510: my %domservers = &Apache::lonnet::get_servers($dom);
8511: $datatable .= &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs');
8512: } else {
8513: $datatable .= &mt("You need to be logged into one of your own domain's servers to display information about the status of LON-CAPA SSL certificates.");
8514: }
8515: $datatable .= '</td></tr>';
1.275 raeburn 8516: $itemcount ++;
8517: } else {
8518: my %titles = &ssl_titles();
8519: my (%by_ip,%by_location,@intdoms,@instdoms);
8520: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
8521: my @alldoms = &Apache::lonnet::all_domains();
8522: my %serverhomes = %Apache::lonnet::serverhomeIDs;
8523: my @domservers = &Apache::lonnet::get_servers($dom);
8524: my %servers = &Apache::lonnet::internet_dom_servers($dom);
8525: my %altids = &id_for_thisdom(%servers);
1.293 raeburn 8526: if (($position eq 'connto') || ($position eq 'connfrom')) {
8527: my $legacy;
8528: unless (ref($settings) eq 'HASH') {
8529: my $name;
8530: if ($position eq 'connto') {
8531: $name = 'loncAllowInsecure';
8532: } else {
8533: $name = 'londAllowInsecure';
8534: }
8535: my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
8536: my @ids=&Apache::lonnet::current_machine_ids();
8537: if (($primarylibserv ne '') && (!grep(/^\Q$primarylibserv\E$/,@ids))) {
8538: my %what = (
8539: $name => 1,
8540: );
8541: my ($result,$returnhash) =
8542: &Apache::lonnet::get_remote_globals($primarylibserv,\%what);
8543: if ($result eq 'ok') {
8544: if (ref($returnhash) eq 'HASH') {
8545: $legacy = $returnhash->{$name};
8546: }
8547: }
8548: } else {
8549: $legacy = $Apache::lonnet::perlvar{$name};
8550: }
8551: }
1.275 raeburn 8552: foreach my $type ('dom','intdom','other') {
8553: my %checked;
8554: $css_class = $itemcount%2?' class="LC_odd_row"':'';
8555: $datatable .= '<tr'.$css_class.'><td>'.$titles{$type}.'</td>'.
8556: '<td class="LC_right_item">';
8557: my $skip;
8558: if ($type eq 'dom') {
8559: unless (keys(%servers) > 1) {
8560: $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');
8561: $skip = 1;
8562: }
8563: }
8564: if ($type eq 'intdom') {
8565: unless (@instdoms > 1) {
8566: $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
8567: $skip = 1;
8568: }
8569: } elsif ($type eq 'other') {
8570: if (keys(%by_location) == 0) {
8571: $datatable .= &mt('Nothing to set here, as there are no other institutions');
8572: $skip = 1;
8573: }
8574: }
8575: unless ($skip) {
8576: $checked{'yes'} = ' checked="checked"';
8577: if (ref($settings) eq 'HASH') {
1.293 raeburn 8578: if (ref($settings->{$position}) eq 'HASH') {
8579: if ($settings->{$position}->{$type} =~ /^(no|req)$/) {
1.275 raeburn 8580: $checked{$1} = $checked{'yes'};
8581: delete($checked{'yes'});
8582: }
8583: }
1.293 raeburn 8584: } else {
8585: if ($legacy == 0) {
8586: $checked{'req'} = $checked{'yes'};
8587: delete($checked{'yes'});
8588: }
1.275 raeburn 8589: }
8590: foreach my $option ('no','yes','req') {
8591: $datatable .= '<span class="LC_nobreak"><label>'.
1.293 raeburn 8592: '<input type="radio" name="'.$position.'_'.$type.'" '.
1.275 raeburn 8593: 'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
8594: '</label></span>'.(' 'x2);
8595: }
8596: }
8597: $datatable .= '</td></tr>';
8598: $itemcount ++;
8599: }
8600: } else {
8601: my $prefix = 'replication';
8602: my @types = ('certreq','nocertreq');
1.279 raeburn 8603: if (keys(%by_location) == 0) {
8604: $datatable .= '<tr'.$css_class.'><td>'.
8605: &mt('Nothing to set here, as there are no other institutions').
8606: '</td></tr>';
8607: $itemcount ++;
1.275 raeburn 8608: } else {
1.279 raeburn 8609: ($datatable,$itemcount) =
8610: &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
1.275 raeburn 8611: }
8612: }
8613: }
8614: $$rowtotal += $itemcount;
8615: return $datatable;
8616: }
8617:
8618: sub ssl_titles {
8619: return &Apache::lonlocal::texthash (
8620: dom => 'LON-CAPA servers/VMs from same domain',
8621: intdom => 'LON-CAPA servers/VMs from same "internet" domain',
8622: other => 'External LON-CAPA servers/VMs',
1.293 raeburn 8623: connto => 'Connections to other servers',
8624: connfrom => 'Connections from other servers',
1.275 raeburn 8625: replication => 'Replicating content to other institutions',
8626: certreq => 'Client certificate required, but specific domains exempt',
8627: nocertreq => 'No client certificate required, except for specific domains',
8628: no => 'SSL not used',
8629: yes => 'SSL Optional (used if available)',
8630: req => 'SSL Required',
8631: );
1.279 raeburn 8632: }
8633:
8634: sub print_trust {
8635: my ($prefix,$dom,$settings,$rowtotal) = @_;
8636: my ($css_class,$datatable,%checked,%choices);
8637: my (%by_ip,%by_location,@intdoms,@instdoms);
8638: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
8639: my $itemcount = 1;
8640: my %titles = &trust_titles();
8641: my @types = ('exc','inc');
8642: if ($prefix eq 'top') {
8643: $prefix = 'content';
8644: } elsif ($prefix eq 'bottom') {
8645: $prefix = 'msg';
8646: }
8647: ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
8648: $$rowtotal += $itemcount;
8649: return $datatable;
8650: }
8651:
8652: sub trust_titles {
8653: return &Apache::lonlocal::texthash(
8654: content => "Access to this domain's content by others",
8655: shared => "Access to other domain's content by this domain",
8656: enroll => "Enrollment in this domain's courses by others",
8657: othcoau => "Co-author roles in this domain for others",
8658: coaurem => "Co-author roles for this domain's users elsewhere",
8659: domroles => "Domain roles in this domain assignable to others",
8660: catalog => "Course Catalog for this domain displayed elsewhere",
8661: reqcrs => "Requests for creation of courses in this domain by others",
8662: msg => "Users in other domains can send messages to this domain",
8663: exc => "Allow all, but exclude specific domains",
8664: inc => "Deny all, but include specific domains",
8665: );
1.275 raeburn 8666: }
8667:
1.138 raeburn 8668: sub build_location_hashes {
1.275 raeburn 8669: my ($intdoms,$by_ip,$by_location,$instdoms) = @_;
1.138 raeburn 8670: return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
1.275 raeburn 8671: (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY'));
1.138 raeburn 8672: my %iphost = &Apache::lonnet::get_iphost();
8673: my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
8674: my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
8675: if (ref($iphost{$primary_ip}) eq 'ARRAY') {
8676: foreach my $id (@{$iphost{$primary_ip}}) {
8677: my $intdom = &Apache::lonnet::internet_dom($id);
8678: unless(grep(/^\Q$intdom\E$/,@{$intdoms})) {
8679: push(@{$intdoms},$intdom);
8680: }
8681: }
8682: }
8683: foreach my $ip (keys(%iphost)) {
8684: if (ref($iphost{$ip}) eq 'ARRAY') {
8685: foreach my $id (@{$iphost{$ip}}) {
8686: my $location = &Apache::lonnet::internet_dom($id);
8687: if ($location) {
1.275 raeburn 8688: if (grep(/^\Q$location\E$/,@{$intdoms})) {
8689: my $dom = &Apache::lonnet::host_domain($id);
8690: unless (grep(/^\Q$dom\E/,@{$instdoms})) {
8691: push(@{$instdoms},$dom);
8692: }
8693: next;
8694: }
1.138 raeburn 8695: if (ref($by_ip->{$ip}) eq 'ARRAY') {
8696: unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
8697: push(@{$by_ip->{$ip}},$location);
8698: }
8699: } else {
8700: $by_ip->{$ip} = [$location];
8701: }
8702: }
8703: }
8704: }
8705: }
8706: foreach my $ip (sort(keys(%{$by_ip}))) {
8707: if (ref($by_ip->{$ip}) eq 'ARRAY') {
8708: @{$by_ip->{$ip}} = sort(@{$by_ip->{$ip}});
8709: my $first = $by_ip->{$ip}->[0];
8710: if (ref($by_location->{$first}) eq 'ARRAY') {
8711: unless (grep(/^\Q$ip\E$/,@{$by_location->{$first}})) {
8712: push(@{$by_location->{$first}},$ip);
8713: }
8714: } else {
8715: $by_location->{$first} = [$ip];
8716: }
8717: }
8718: }
8719: return;
8720: }
8721:
1.145 raeburn 8722: sub current_offloads_to {
8723: my ($dom,$settings,$servers) = @_;
8724: my (%spareid,%otherdomconfigs);
1.152 raeburn 8725: if (ref($servers) eq 'HASH') {
1.145 raeburn 8726: foreach my $lonhost (sort(keys(%{$servers}))) {
8727: my $gotspares;
1.152 raeburn 8728: if (ref($settings) eq 'HASH') {
8729: if (ref($settings->{'spares'}) eq 'HASH') {
8730: if (ref($settings->{'spares'}{$lonhost}) eq 'HASH') {
8731: $spareid{$lonhost}{'primary'} = $settings->{'spares'}{$lonhost}{'primary'};
8732: $spareid{$lonhost}{'default'} = $settings->{'spares'}{$lonhost}{'default'};
8733: $gotspares = 1;
8734: }
1.145 raeburn 8735: }
8736: }
8737: unless ($gotspares) {
8738: my $gotspares;
8739: my $serverhomeID =
8740: &Apache::lonnet::get_server_homeID($servers->{$lonhost});
8741: my $serverhomedom =
8742: &Apache::lonnet::host_domain($serverhomeID);
8743: if ($serverhomedom ne $dom) {
8744: if (ref($otherdomconfigs{$serverhomedom} eq 'HASH')) {
8745: if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') {
8746: if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') {
8747: $spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'};
8748: $spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'};
8749: $gotspares = 1;
8750: }
8751: }
8752: } else {
8753: $otherdomconfigs{$serverhomedom} =
8754: &Apache::lonnet::get_dom('configuration',['usersessions'],$serverhomedom);
8755: if (ref($otherdomconfigs{$serverhomedom}) eq 'HASH') {
8756: if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') {
8757: if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') {
8758: if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{$lonhost}) eq 'HASH') {
8759: $spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'};
8760: $spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'};
8761: $gotspares = 1;
8762: }
8763: }
8764: }
8765: }
8766: }
8767: }
8768: }
8769: unless ($gotspares) {
8770: if ($lonhost eq $Apache::lonnet::perlvar{'lonHostID'}) {
8771: $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};
8772: $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};
8773: } else {
8774: my $server_hostname = &Apache::lonnet::hostname($lonhost);
8775: my $server_homeID = &Apache::lonnet::get_server_homeID($server_hostname);
8776: if ($server_homeID eq $Apache::lonnet::perlvar{'lonHostID'}) {
8777: $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'};
8778: $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'};
8779: } else {
1.150 raeburn 8780: my %what = (
8781: spareid => 1,
8782: );
8783: my ($result,$returnhash) =
8784: &Apache::lonnet::get_remote_globals($lonhost,\%what);
8785: if ($result eq 'ok') {
8786: if (ref($returnhash) eq 'HASH') {
8787: if (ref($returnhash->{'spareid'}) eq 'HASH') {
8788: $spareid{$lonhost}{'primary'} = $returnhash->{'spareid'}->{'primary'};
8789: $spareid{$lonhost}{'default'} = $returnhash->{'spareid'}->{'default'};
8790: }
8791: }
1.145 raeburn 8792: }
8793: }
8794: }
8795: }
8796: }
8797: }
8798: return %spareid;
8799: }
8800:
8801: sub spares_row {
1.371 raeburn 8802: my ($dom,$servers,$spareid,$serverhomes,$altids,$other_insts,
8803: $curroffloadnow,$curroffloadoth,$rowtotal) = @_;
1.145 raeburn 8804: my $css_class;
8805: my $numinrow = 4;
8806: my $itemcount = 1;
8807: my $datatable;
1.152 raeburn 8808: my %typetitles = &sparestype_titles();
8809: if ((ref($servers) eq 'HASH') && (ref($spareid) eq 'HASH') && (ref($altids) eq 'HASH')) {
1.145 raeburn 8810: foreach my $server (sort(keys(%{$servers}))) {
1.152 raeburn 8811: my $serverhome = &Apache::lonnet::get_server_homeID($servers->{$server});
8812: my ($othercontrol,$serverdom);
8813: if ($serverhome ne $server) {
8814: $serverdom = &Apache::lonnet::host_domain($serverhome);
8815: $othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
8816: } else {
8817: $serverdom = &Apache::lonnet::host_domain($server);
8818: if ($serverdom ne $dom) {
8819: $othercontrol = &mt('Session offloading controlled by domain: [_1]','<b>'.$serverdom.'</b>');
8820: }
8821: }
8822: next unless (ref($spareid->{$server}) eq 'HASH');
1.371 raeburn 8823: my ($checkednow,$checkedoth);
1.261 raeburn 8824: if (ref($curroffloadnow) eq 'HASH') {
8825: if ($curroffloadnow->{$server}) {
8826: $checkednow = ' checked="checked"';
8827: }
8828: }
1.371 raeburn 8829: if (ref($curroffloadoth) eq 'HASH') {
8830: if ($curroffloadoth->{$server}) {
8831: $checkedoth = ' checked="checked"';
8832: }
8833: }
1.145 raeburn 8834: $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
8835: $datatable .= '<tr'.$css_class.'>
8836: <td rowspan="2">
1.183 bisitz 8837: <span class="LC_nobreak">'.
8838: &mt('[_1] when busy, offloads to:'
1.261 raeburn 8839: ,'<b>'.$server.'</b>').'</span><br />'.
1.289 raeburn 8840: '<span class="LC_nobreak">'."\n".
1.261 raeburn 8841: '<label><input type="checkbox" name="offloadnow" value="'.$server.'"'.$checkednow.' />'.
1.371 raeburn 8842: ' '.&mt('Switch any active user on next access').'</label></span>'.
1.183 bisitz 8843: "\n";
1.371 raeburn 8844: if ($other_insts) {
8845: $datatable .= '<br />'.
8846: '<span class="LC_nobreak">'."\n".
8847: '<label><input type="checkbox" name="offloadoth" value="'.$server.'"'.$checkedoth.' />'.
8848: ' '.&mt('Switch other institutions on next access').'</label></span>'.
8849: "\n";
8850: }
1.145 raeburn 8851: my (%current,%canselect);
1.152 raeburn 8852: my @choices =
8853: &possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
8854: foreach my $type ('primary','default') {
8855: if (ref($spareid->{$server}) eq 'HASH') {
1.145 raeburn 8856: if (ref($spareid->{$server}{$type}) eq 'ARRAY') {
8857: my @spares = @{$spareid->{$server}{$type}};
8858: if (@spares > 0) {
1.152 raeburn 8859: if ($othercontrol) {
8860: $current{$type} = join(', ',@spares);
8861: } else {
8862: $current{$type} .= '<table>';
8863: my $numspares = scalar(@spares);
8864: for (my $i=0; $i<@spares; $i++) {
8865: my $rem = $i%($numinrow);
8866: if ($rem == 0) {
8867: if ($i > 0) {
8868: $current{$type} .= '</tr>';
8869: }
8870: $current{$type} .= '<tr>';
1.145 raeburn 8871: }
1.152 raeburn 8872: $current{$type} .= '<td><label><input type="checkbox" name="spare_'.$type.'_'.$server.'" id="spare_'.$type.'_'.$server.'_'.$i.'" checked="checked" value="'.$spareid->{$server}{$type}[$i].'" onclick="updateNewSpares(this.form,'."'$server'".');" /> '.
8873: $spareid->{$server}{$type}[$i].
8874: '</label></td>'."\n";
8875: }
8876: my $rem = @spares%($numinrow);
8877: my $colsleft = $numinrow - $rem;
8878: if ($colsleft > 1 ) {
8879: $current{$type} .= '<td colspan="'.$colsleft.
8880: '" class="LC_left_item">'.
8881: ' </td>';
8882: } elsif ($colsleft == 1) {
8883: $current{$type} .= '<td class="LC_left_item"> </td>'."\n";
1.145 raeburn 8884: }
1.152 raeburn 8885: $current{$type} .= '</tr></table>';
1.150 raeburn 8886: }
1.145 raeburn 8887: }
8888: }
8889: if ($current{$type} eq '') {
8890: $current{$type} = &mt('None specified');
8891: }
1.152 raeburn 8892: if ($othercontrol) {
8893: if ($type eq 'primary') {
8894: $canselect{$type} = $othercontrol;
8895: }
8896: } else {
8897: $canselect{$type} =
8898: &mt('Add new [_1]'.$type.'[_2]:','<i>','</i>').' '.
8899: '<select name="newspare_'.$type.'_'.$server.'" '.
8900: 'id="newspare_'.$type.'_'.$server.'" onchange="checkNewSpares('."'$server','$type'".');">'."\n".
8901: '<option value="" selected ="selected">'.&mt('Select').'</option>'."\n";
8902: if (@choices > 0) {
8903: foreach my $lonhost (@choices) {
8904: $canselect{$type} .= '<option value="'.$lonhost.'">'.$lonhost.'</option>'."\n";
8905: }
8906: }
8907: $canselect{$type} .= '</select>'."\n";
8908: }
8909: } else {
8910: $current{$type} = &mt('Could not be determined');
8911: if ($type eq 'primary') {
8912: $canselect{$type} = $othercontrol;
8913: }
1.145 raeburn 8914: }
1.152 raeburn 8915: if ($type eq 'default') {
8916: $datatable .= '<tr'.$css_class.'>';
8917: }
8918: $datatable .= '<td><i>'.$typetitles{$type}.'</i></td>'."\n".
8919: '<td>'.$current{$type}.'</td>'."\n".
8920: '<td>'.$canselect{$type}.'</td></tr>'."\n";
1.145 raeburn 8921: }
8922: $itemcount ++;
8923: }
8924: }
8925: $$rowtotal += $itemcount;
8926: return $datatable;
8927: }
8928:
1.152 raeburn 8929: sub possible_newspares {
8930: my ($server,$currspares,$serverhomes,$altids) = @_;
8931: my $serverhostname = &Apache::lonnet::hostname($server);
8932: my %excluded;
8933: if ($serverhostname ne '') {
8934: %excluded = (
8935: $serverhostname => 1,
8936: );
8937: }
8938: if (ref($currspares) eq 'HASH') {
8939: foreach my $type (keys(%{$currspares})) {
8940: if (ref($currspares->{$type}) eq 'ARRAY') {
8941: if (@{$currspares->{$type}} > 0) {
8942: foreach my $curr (@{$currspares->{$type}}) {
8943: my $hostname = &Apache::lonnet::hostname($curr);
8944: $excluded{$hostname} = 1;
8945: }
8946: }
8947: }
8948: }
8949: }
8950: my @choices;
8951: if ((ref($serverhomes) eq 'HASH') && (ref($altids) eq 'HASH')) {
8952: if (keys(%{$serverhomes}) > 1) {
8953: foreach my $name (sort(keys(%{$serverhomes}))) {
8954: unless ($excluded{$name}) {
8955: if (exists($altids->{$serverhomes->{$name}})) {
8956: push(@choices,$altids->{$serverhomes->{$name}});
8957: } else {
8958: push(@choices,$serverhomes->{$name});
1.145 raeburn 8959: }
8960: }
8961: }
8962: }
8963: }
1.152 raeburn 8964: return sort(@choices);
1.145 raeburn 8965: }
8966:
1.150 raeburn 8967: sub print_loadbalancing {
8968: my ($dom,$settings,$rowtotal) = @_;
8969: my $primary_id = &Apache::lonnet::domain($dom,'primary');
8970: my $intdom = &Apache::lonnet::internet_dom($primary_id);
8971: my $numinrow = 1;
8972: my $datatable;
8973: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.342 raeburn 8974: my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
1.171 raeburn 8975: if (ref($settings) eq 'HASH') {
8976: %existing = %{$settings};
8977: }
8978: if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
8979: &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
1.342 raeburn 8980: \%currtargets,\%currrules,\%currcookies);
1.150 raeburn 8981: } else {
8982: return;
8983: }
8984: my ($othertitle,$usertypes,$types) =
8985: &Apache::loncommon::sorted_inst_types($dom);
1.209 raeburn 8986: my $rownum = 8;
1.150 raeburn 8987: if (ref($types) eq 'ARRAY') {
8988: $rownum += scalar(@{$types});
8989: }
1.171 raeburn 8990: my @css_class = ('LC_odd_row','LC_even_row');
8991: my $balnum = 0;
8992: my $islast;
8993: my (@toshow,$disabledtext);
8994: if (keys(%currbalancer) > 0) {
8995: @toshow = sort(keys(%currbalancer));
8996: if (scalar(@toshow) < scalar(keys(%servers)) + 1) {
8997: push(@toshow,'');
8998: }
8999: } else {
9000: @toshow = ('');
9001: $disabledtext = &mt('No existing load balancer');
9002: }
9003: foreach my $lonhost (@toshow) {
9004: if ($balnum == scalar(@toshow)-1) {
9005: $islast = 1;
9006: } else {
9007: $islast = 0;
9008: }
9009: my $cssidx = $balnum%2;
9010: my $targets_div_style = 'display: none';
9011: my $disabled_div_style = 'display: block';
9012: my $homedom_div_style = 'display: none';
9013: $datatable .= '<tr class="'.$css_class[$cssidx].'">'.
1.306 raeburn 9014: '<td rowspan="'.$rownum.'" style="vertical-align: top">'.
1.171 raeburn 9015: '<p>';
9016: if ($lonhost eq '') {
1.210 raeburn 9017: $datatable .= '<span class="LC_nobreak">';
1.171 raeburn 9018: if (keys(%currbalancer) > 0) {
9019: $datatable .= &mt('Add balancer:');
9020: } else {
9021: $datatable .= &mt('Enable balancer:');
9022: }
9023: $datatable .= ' '.
9024: '<select name="loadbalancing_lonhost_'.$balnum.'"'.
9025: ' id="loadbalancing_lonhost_'.$balnum.'"'.
9026: ' onchange="toggleTargets('."'$balnum'".');">'."\n".
9027: '<option value="" selected="selected">'.&mt('None').
9028: '</option>'."\n";
9029: foreach my $server (sort(keys(%servers))) {
9030: next if ($currbalancer{$server});
9031: $datatable .= '<option value="'.$server.'">'.$server.'</option>'."\n";
9032: }
1.210 raeburn 9033: $datatable .=
1.171 raeburn 9034: '</select>'."\n".
9035: '<input type="hidden" name="loadbalancing_prevlonhost_'.$balnum.'" id="loadbalancing_prevlonhost_'.$balnum.'" value="" /> </span>'."\n";
9036: } else {
9037: $datatable .= '<i>'.$lonhost.'</i><br /><span class="LC_nobreak">'.
9038: '<label><input type="checkbox" name="loadbalancing_delete" value="'.$balnum.'" id="loadbalancing_delete_'.$balnum.'" onclick="javascript:balancerDeleteChange('."'$balnum'".');" /> '.
9039: &mt('Stop balancing').'</label>'.
9040: '<input type="hidden" name="loadbalancing_lonhost_'.$balnum.'" value="'.$lonhost.'" id="loadbalancing_lonhost_'.$balnum.'" /></span>';
9041: $targets_div_style = 'display: block';
9042: $disabled_div_style = 'display: none';
9043: if ($dom eq &Apache::lonnet::host_domain($lonhost)) {
9044: $homedom_div_style = 'display: block';
9045: }
9046: }
1.306 raeburn 9047: $datatable .= '</p></td><td rowspan="'.$rownum.'" style="vertical-align: top">'.
1.171 raeburn 9048: '<div id="loadbalancing_disabled_'.$balnum.'" style="'.
9049: $disabled_div_style.'">'.$disabledtext.'</div>'."\n".
9050: '<div id="loadbalancing_targets_'.$balnum.'" style="'.$targets_div_style.'">'.&mt('Offloads to:').'<br />';
9051: my ($numspares,@spares) = &count_servers($lonhost,%servers);
9052: my @sparestypes = ('primary','default');
9053: my %typetitles = &sparestype_titles();
1.284 raeburn 9054: my %hostherechecked = (
9055: no => ' checked="checked"',
9056: );
1.342 raeburn 9057: my %balcookiechecked = (
1.425 raeburn 9058: no => ' checked="checked"',
1.342 raeburn 9059: );
1.171 raeburn 9060: foreach my $sparetype (@sparestypes) {
9061: my $targettable;
9062: for (my $i=0; $i<$numspares; $i++) {
9063: my $checked;
9064: if (ref($currtargets{$lonhost}) eq 'HASH') {
9065: if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {
9066: if (grep(/^\Q$spares[$i]\E$/,@{$currtargets{$lonhost}{$sparetype}})) {
9067: $checked = ' checked="checked"';
9068: }
9069: }
9070: }
9071: my ($chkboxval,$disabled);
9072: if (($lonhost ne '') && (exists($servers{$lonhost}))) {
9073: $chkboxval = $spares[$i];
9074: }
9075: if (exists($currbalancer{$spares[$i]})) {
9076: $disabled = ' disabled="disabled"';
9077: }
1.210 raeburn 9078: $targettable .=
1.253 raeburn 9079: '<td><span class="LC_nobreak"><label>'.
9080: '<input type="checkbox" name="loadbalancing_target_'.$balnum.'_'.$sparetype.'"'.
1.171 raeburn 9081: $checked.$disabled.' value="'.$chkboxval.'" id="loadbalancing_target_'.$balnum.'_'.$sparetype.'_'.$i.'" onclick="checkOffloads('."this,'$balnum','$sparetype'".');" /><span id="loadbalancing_targettxt_'.$balnum.'_'.$sparetype.'_'.$i.'"> '.$chkboxval.
1.253 raeburn 9082: '</span></label></span></td>';
1.171 raeburn 9083: my $rem = $i%($numinrow);
9084: if ($rem == 0) {
9085: if (($i > 0) && ($i < $numspares-1)) {
9086: $targettable .= '</tr>';
9087: }
9088: if ($i < $numspares-1) {
9089: $targettable .= '<tr>';
1.150 raeburn 9090: }
9091: }
9092: }
1.171 raeburn 9093: if ($targettable ne '') {
9094: my $rem = $numspares%($numinrow);
9095: my $colsleft = $numinrow - $rem;
9096: if ($colsleft > 1 ) {
9097: $targettable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
9098: ' </td>';
9099: } elsif ($colsleft == 1) {
9100: $targettable .= '<td class="LC_left_item"> </td>';
9101: }
9102: $datatable .= '<i>'.$typetitles{$sparetype}.'</i><br />'.
9103: '<table><tr>'.$targettable.'</tr></table><br />';
9104: }
1.284 raeburn 9105: $hostherechecked{$sparetype} = '';
9106: if (ref($currtargets{$lonhost}) eq 'HASH') {
9107: if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') {
9108: if (grep(/^\Q$lonhost\E$/,@{$currtargets{$lonhost}{$sparetype}})) {
9109: $hostherechecked{$sparetype} = ' checked="checked"';
9110: $hostherechecked{'no'} = '';
9111: }
9112: }
9113: }
9114: }
1.342 raeburn 9115: if ($currcookies{$lonhost}) {
9116: %balcookiechecked = (
9117: yes => ' checked="checked"',
9118: );
9119: }
1.284 raeburn 9120: $datatable .= &mt('Hosting on balancer itself').'<br />'.
9121: '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" value="no"'.
9122: $hostherechecked{'no'}.' />'.&mt('No').'</label><br />';
9123: foreach my $sparetype (@sparestypes) {
9124: $datatable .= '<label><input type="radio" name="loadbalancing_target_'.$balnum.'_hosthere" '.
9125: 'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' /><i>'.$typetitles{$sparetype}.
9126: '</i></label><br />';
1.171 raeburn 9127: }
1.342 raeburn 9128: $datatable .= &mt('Use balancer cookie').'<br />'.
9129: '<label><input type="radio" name="loadbalancing_cookie_'.$balnum.'" value="1"'.
9130: $balcookiechecked{'yes'}.' />'.&mt('Yes').'</label><br />'.
9131: '<label><input type="radio" name="loadbalancing_cookie_'.$balnum.'" value="0"'.
9132: $balcookiechecked{'no'}.' />'.&mt('No').'</label><br />'.
9133: '</div></td></tr>'.
1.171 raeburn 9134: &loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
9135: $othertitle,$usertypes,$types,\%servers,
9136: \%currbalancer,$lonhost,
9137: $targets_div_style,$homedom_div_style,
9138: $css_class[$cssidx],$balnum,$islast);
9139: $$rowtotal += $rownum;
9140: $balnum ++;
9141: }
9142: $datatable .= '<input type="hidden" name="loadbalancing_total" id="loadbalancing_total" value="'.$balnum.'" />';
9143: return $datatable;
9144: }
9145:
9146: sub get_loadbalancers_config {
1.342 raeburn 9147: my ($servers,$existing,$currbalancer,$currtargets,$currrules,$currcookies) = @_;
1.171 raeburn 9148: return unless ((ref($servers) eq 'HASH') &&
9149: (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&
1.342 raeburn 9150: (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH') &&
9151: (ref($currcookies) eq 'HASH'));
1.171 raeburn 9152: if (keys(%{$existing}) > 0) {
9153: my $oldlonhost;
9154: foreach my $key (sort(keys(%{$existing}))) {
9155: if ($key eq 'lonhost') {
9156: $oldlonhost = $existing->{'lonhost'};
9157: $currbalancer->{$oldlonhost} = 1;
9158: } elsif ($key eq 'targets') {
9159: if ($oldlonhost) {
9160: $currtargets->{$oldlonhost} = $existing->{'targets'};
9161: }
9162: } elsif ($key eq 'rules') {
9163: if ($oldlonhost) {
9164: $currrules->{$oldlonhost} = $existing->{'rules'};
9165: }
9166: } elsif (ref($existing->{$key}) eq 'HASH') {
9167: $currbalancer->{$key} = 1;
9168: $currtargets->{$key} = $existing->{$key}{'targets'};
9169: $currrules->{$key} = $existing->{$key}{'rules'};
1.342 raeburn 9170: if ($existing->{$key}{'cookie'}) {
9171: $currcookies->{$key} = 1;
9172: }
1.150 raeburn 9173: }
9174: }
1.171 raeburn 9175: } else {
9176: my ($balancerref,$targetsref) =
9177: &Apache::lonnet::get_lonbalancer_config($servers);
9178: if ((ref($balancerref) eq 'HASH') && (ref($targetsref) eq 'HASH')) {
9179: foreach my $server (sort(keys(%{$balancerref}))) {
9180: $currbalancer->{$server} = 1;
9181: $currtargets->{$server} = $targetsref->{$server};
1.150 raeburn 9182: }
9183: }
9184: }
1.171 raeburn 9185: return;
1.150 raeburn 9186: }
9187:
9188: sub loadbalancing_rules {
9189: my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers,
1.171 raeburn 9190: $currbalancer,$lonhost,$targets_div_style,$homedom_div_style,
9191: $css_class,$balnum,$islast) = @_;
1.150 raeburn 9192: my $output;
1.171 raeburn 9193: my $num = 0;
1.210 raeburn 9194: my ($alltypes,$othertypes,$titles) =
1.150 raeburn 9195: &loadbalancing_titles($dom,$intdom,$usertypes,$types);
9196: if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
9197: foreach my $type (@{$alltypes}) {
1.171 raeburn 9198: $num ++;
1.150 raeburn 9199: my $current;
9200: if (ref($currrules) eq 'HASH') {
9201: $current = $currrules->{$type};
9202: }
1.253 raeburn 9203: if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
1.171 raeburn 9204: if ($dom ne &Apache::lonnet::host_domain($lonhost)) {
1.150 raeburn 9205: $current = '';
9206: }
9207: }
9208: $output .= &loadbalance_rule_row($type,$titles->{$type},$current,
1.171 raeburn 9209: $servers,$currbalancer,$lonhost,$dom,
9210: $targets_div_style,$homedom_div_style,
9211: $css_class,$balnum,$num,$islast);
1.150 raeburn 9212: }
9213: }
9214: return $output;
9215: }
9216:
9217: sub loadbalancing_titles {
9218: my ($dom,$intdom,$usertypes,$types) = @_;
9219: my %othertypes = (
9220: '_LC_adv' => &mt('Advanced users from [_1]',$dom),
9221: '_LC_author' => &mt('Users from [_1] with author role',$dom),
9222: '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom),
9223: '_LC_external' => &mt('Users not from [_1]',$intdom),
1.209 raeburn 9224: '_LC_ipchangesso' => &mt('SSO users from [_1], with IP mismatch',$dom),
9225: '_LC_ipchange' => &mt('Non-SSO users with IP mismatch'),
1.150 raeburn 9226: );
1.209 raeburn 9227: my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange');
1.302 raeburn 9228: my @available;
1.150 raeburn 9229: if (ref($types) eq 'ARRAY') {
1.302 raeburn 9230: @available = @{$types};
1.150 raeburn 9231: }
1.302 raeburn 9232: unless (grep(/^default$/,@available)) {
9233: push(@available,'default');
9234: }
9235: unshift(@alltypes,@available);
1.150 raeburn 9236: my %titles;
9237: foreach my $type (@alltypes) {
9238: if ($type =~ /^_LC_/) {
9239: $titles{$type} = $othertypes{$type};
9240: } elsif ($type eq 'default') {
9241: $titles{$type} = &mt('All users from [_1]',$dom);
9242: if (ref($types) eq 'ARRAY') {
9243: if (@{$types} > 0) {
9244: $titles{$type} = &mt('Other users from [_1]',$dom);
9245: }
9246: }
9247: } elsif (ref($usertypes) eq 'HASH') {
9248: $titles{$type} = $usertypes->{$type};
9249: }
9250: }
9251: return (\@alltypes,\%othertypes,\%titles);
9252: }
9253:
9254: sub loadbalance_rule_row {
1.171 raeburn 9255: my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom,
9256: $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_;
1.209 raeburn 9257: my @rulenames;
1.150 raeburn 9258: my %ruletitles = &offloadtype_text();
1.209 raeburn 9259: if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) {
1.254 raeburn 9260: @rulenames = ('balancer','offloadedto','specific');
1.150 raeburn 9261: } else {
1.209 raeburn 9262: @rulenames = ('default','homeserver');
9263: if ($type eq '_LC_external') {
9264: push(@rulenames,'externalbalancer');
9265: } else {
9266: push(@rulenames,'specific');
9267: }
9268: push(@rulenames,'none');
1.150 raeburn 9269: }
9270: my $style = $targets_div_style;
1.253 raeburn 9271: if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) {
1.150 raeburn 9272: $style = $homedom_div_style;
9273: }
1.171 raeburn 9274: my $space;
9275: if ($islast && $num == 1) {
1.317 raeburn 9276: $space = '<div style="display:inline-block;"> </div>';
1.171 raeburn 9277: }
1.210 raeburn 9278: my $output =
1.306 raeburn 9279: '<tr class="'.$css_class.'" id="balanceruletr_'.$balnum.'_'.$num.'"><td style="vertical-align: top">'.$space.
1.171 raeburn 9280: '<div id="balanceruletitle_'.$balnum.'_'.$type.'" style="'.$style.'">'.$title.'</div></td>'."\n".
9281: '<td valaign="top">'.$space.
9282: '<div id="balancerule_'.$balnum.'_'.$type.'" style="'.$style.'">'."\n";
1.150 raeburn 9283: for (my $i=0; $i<@rulenames; $i++) {
9284: my $rule = $rulenames[$i];
9285: my ($checked,$extra);
9286: if ($rulenames[$i] eq 'default') {
9287: $rule = '';
9288: }
9289: if ($rulenames[$i] eq 'specific') {
9290: if (ref($servers) eq 'HASH') {
9291: my $default;
9292: if (($current ne '') && (exists($servers->{$current}))) {
9293: $checked = ' checked="checked"';
9294: }
9295: unless ($checked) {
9296: $default = ' selected="selected"';
9297: }
1.210 raeburn 9298: $extra =
1.171 raeburn 9299: ': <select name="loadbalancing_singleserver_'.$balnum.'_'.$type.
9300: '" id="loadbalancing_singleserver_'.$balnum.'_'.$type.
9301: '" onchange="singleServerToggle('."'$balnum','$type'".')">'."\n".
9302: '<option value=""'.$default.'></option>'."\n";
9303: foreach my $server (sort(keys(%{$servers}))) {
9304: if (ref($currbalancer) eq 'HASH') {
9305: next if (exists($currbalancer->{$server}));
9306: }
1.150 raeburn 9307: my $selected;
1.171 raeburn 9308: if ($server eq $current) {
1.150 raeburn 9309: $selected = ' selected="selected"';
9310: }
1.171 raeburn 9311: $extra .= '<option value="'.$server.'"'.$selected.'>'.$server.'</option>';
1.150 raeburn 9312: }
9313: $extra .= '</select>';
9314: }
9315: } elsif ($rule eq $current) {
9316: $checked = ' checked="checked"';
9317: }
9318: $output .= '<span class="LC_nobreak"><label>'.
1.171 raeburn 9319: '<input type="radio" name="loadbalancing_rules_'.$balnum.'_'.$type.
9320: '" id="loadbalancing_rules_'.$balnum.'_'.$type.'_'.$i.'" value="'.
9321: $rule.'" onclick="balanceruleChange('."this.form,'$balnum','$type'".
1.254 raeburn 9322: ')"'.$checked.' /> ';
9323: if (($rulenames[$i] eq 'specific') && ($type =~ /^_LC_ipchange/)) {
9324: $output .= $ruletitles{'particular'};
9325: } else {
9326: $output .= $ruletitles{$rulenames[$i]};
9327: }
9328: $output .= '</label>'.$extra.'</span><br />'."\n";
1.150 raeburn 9329: }
9330: $output .= '</div></td></tr>'."\n";
9331: return $output;
9332: }
9333:
9334: sub offloadtype_text {
9335: my %ruletitles = &Apache::lonlocal::texthash (
9336: 'default' => 'Offloads to default destinations',
9337: 'homeserver' => "Offloads to user's home server",
9338: 'externalbalancer' => "Offloads to Load Balancer in user's domain",
9339: 'specific' => 'Offloads to specific server',
1.161 raeburn 9340: 'none' => 'No offload',
1.209 raeburn 9341: 'balancer' => 'Session hosted on Load Balancer, after re-authentication',
9342: 'offloadedto' => 'Session hosted on offload server, after re-authentication',
1.254 raeburn 9343: 'particular' => 'Session hosted (after re-auth) on server:',
1.150 raeburn 9344: );
9345: return %ruletitles;
9346: }
9347:
9348: sub sparestype_titles {
9349: my %typestitles = &Apache::lonlocal::texthash (
9350: 'primary' => 'primary',
9351: 'default' => 'default',
9352: );
9353: return %typestitles;
9354: }
9355:
1.28 raeburn 9356: sub contact_titles {
9357: my %titles = &Apache::lonlocal::texthash (
1.286 raeburn 9358: 'supportemail' => 'Support E-mail address',
9359: 'adminemail' => 'Default Server Admin E-mail address',
9360: 'errormail' => 'Error reports to be e-mailed to',
9361: 'packagesmail' => 'Package update alerts to be e-mailed to',
1.315 raeburn 9362: 'helpdeskmail' => "Helpdesk requests from all users in this domain",
9363: 'otherdomsmail' => 'Helpdesk requests from users in other (unconfigured) domains',
1.286 raeburn 9364: 'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',
9365: 'requestsmail' => 'E-mail from course requests requiring approval',
9366: 'updatesmail' => 'E-mail from nightly check of LON-CAPA module integrity/updates',
1.203 raeburn 9367: 'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
1.350 raeburn 9368: 'hostipmail' => 'E-mail from nightly check of hostname/IP network changes',
1.378 raeburn 9369: 'errorthreshold' => 'Error count threshold for status e-mail to admin(s)',
9370: 'errorsysmail' => 'Error count threshold for e-mail to developer group',
1.340 raeburn 9371: 'errorweights' => 'Weights used to compute error count',
9372: 'errorexcluded' => 'Servers with unsent updates excluded from count',
1.28 raeburn 9373: );
9374: my %short_titles = &Apache::lonlocal::texthash (
9375: adminemail => 'Admin E-mail address',
9376: supportemail => 'Support E-mail',
9377: );
9378: return (\%titles,\%short_titles);
9379: }
9380:
1.286 raeburn 9381: sub helpform_fields {
9382: my %titles = &Apache::lonlocal::texthash (
9383: 'username' => 'Name',
9384: 'user' => 'Username/domain',
9385: 'phone' => 'Phone',
9386: 'cc' => 'Cc e-mail',
9387: 'course' => 'Course Details',
9388: 'section' => 'Sections',
1.289 raeburn 9389: 'screenshot' => 'File upload',
1.286 raeburn 9390: );
9391: my @fields = ('username','phone','user','course','section','cc','screenshot');
9392: my %possoptions = (
9393: username => ['yes','no','req'],
1.289 raeburn 9394: phone => ['yes','no','req'],
1.286 raeburn 9395: user => ['yes','no'],
1.289 raeburn 9396: cc => ['yes','no'],
1.286 raeburn 9397: course => ['yes','no'],
9398: section => ['yes','no'],
9399: screenshot => ['yes','no'],
9400: );
9401: my %fieldoptions = &Apache::lonlocal::texthash (
9402: 'yes' => 'Optional',
9403: 'req' => 'Required',
9404: 'no' => "Not shown",
9405: );
9406: return (\@fields,\%titles,\%fieldoptions,\%possoptions);
9407: }
9408:
1.72 raeburn 9409: sub tool_titles {
9410: my %titles = &Apache::lonlocal::texthash (
1.162 raeburn 9411: aboutme => 'Personal web page',
1.86 raeburn 9412: blog => 'Blog',
1.162 raeburn 9413: webdav => 'WebDAV',
1.86 raeburn 9414: portfolio => 'Portfolio',
1.413 raeburn 9415: timezone => 'Can set time zone',
1.88 bisitz 9416: official => 'Official courses (with institutional codes)',
9417: unofficial => 'Unofficial courses',
1.98 raeburn 9418: community => 'Communities',
1.216 raeburn 9419: textbook => 'Textbook courses',
1.271 raeburn 9420: placement => 'Placement tests',
1.86 raeburn 9421: );
1.72 raeburn 9422: return %titles;
9423: }
9424:
1.101 raeburn 9425: sub courserequest_titles {
9426: my %titles = &Apache::lonlocal::texthash (
9427: official => 'Official',
9428: unofficial => 'Unofficial',
9429: community => 'Communities',
1.216 raeburn 9430: textbook => 'Textbook',
1.271 raeburn 9431: placement => 'Placement tests',
1.325 raeburn 9432: lti => 'LTI Provider',
1.101 raeburn 9433: norequest => 'Not allowed',
1.325 raeburn 9434: approval => 'Approval by DC',
1.101 raeburn 9435: validate => 'With validation',
9436: autolimit => 'Numerical limit',
1.103 raeburn 9437: unlimited => '(blank for unlimited)',
1.101 raeburn 9438: );
9439: return %titles;
9440: }
9441:
1.163 raeburn 9442: sub authorrequest_titles {
9443: my %titles = &Apache::lonlocal::texthash (
9444: norequest => 'Not allowed',
9445: approval => 'Approval by Dom. Coord.',
9446: automatic => 'Automatic approval',
9447: );
9448: return %titles;
1.210 raeburn 9449: }
1.163 raeburn 9450:
1.101 raeburn 9451: sub courserequest_conditions {
9452: my %conditions = &Apache::lonlocal::texthash (
1.104 raeburn 9453: approval => '(Processing of request subject to approval by Domain Coordinator).',
1.193 bisitz 9454: validate => '(Processing of request subject to institutional validation).',
1.101 raeburn 9455: );
9456: return %conditions;
9457: }
9458:
9459:
1.27 raeburn 9460: sub print_usercreation {
1.30 raeburn 9461: my ($position,$dom,$settings,$rowtotal) = @_;
1.27 raeburn 9462: my $numinrow = 4;
1.28 raeburn 9463: my $datatable;
9464: if ($position eq 'top') {
1.30 raeburn 9465: $$rowtotal ++;
1.34 raeburn 9466: my $rowcount = 0;
1.32 raeburn 9467: my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username');
1.28 raeburn 9468: if (ref($rules) eq 'HASH') {
9469: if (keys(%{$rules}) > 0) {
1.32 raeburn 9470: $datatable .= &user_formats_row('username',$settings,$rules,
9471: $ruleorder,$numinrow,$rowcount);
1.30 raeburn 9472: $$rowtotal ++;
1.32 raeburn 9473: $rowcount ++;
9474: }
9475: }
9476: my ($idrules,$idruleorder) = &Apache::lonnet::inst_userrules($dom,'id');
9477: if (ref($idrules) eq 'HASH') {
9478: if (keys(%{$idrules}) > 0) {
9479: $datatable .= &user_formats_row('id',$settings,$idrules,
9480: $idruleorder,$numinrow,$rowcount);
9481: $$rowtotal ++;
9482: $rowcount ++;
1.28 raeburn 9483: }
9484: }
1.39 raeburn 9485: if ($rowcount == 0) {
9486: $datatable .= '<tr><td colspan="2">'.&mt('No format rules have been defined for usernames or IDs in this domain.').'</td></tr>';
9487: $$rowtotal ++;
9488: $rowcount ++;
9489: }
1.34 raeburn 9490: } elsif ($position eq 'middle') {
1.224 raeburn 9491: my @creators = ('author','course','requestcrs');
1.37 raeburn 9492: my ($rules,$ruleorder) =
9493: &Apache::lonnet::inst_userrules($dom,'username');
1.34 raeburn 9494: my %lt = &usercreation_types();
9495: my %checked;
9496: if (ref($settings) eq 'HASH') {
9497: if (ref($settings->{'cancreate'}) eq 'HASH') {
9498: foreach my $item (@creators) {
9499: $checked{$item} = $settings->{'cancreate'}{$item};
9500: }
9501: } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') {
9502: foreach my $item (@creators) {
9503: if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) {
9504: $checked{$item} = 'none';
9505: }
9506: }
9507: }
9508: }
9509: my $rownum = 0;
9510: foreach my $item (@creators) {
9511: $rownum ++;
1.224 raeburn 9512: if ($checked{$item} eq '') {
9513: $checked{$item} = 'any';
1.34 raeburn 9514: }
9515: my $css_class;
9516: if ($rownum%2) {
9517: $css_class = '';
9518: } else {
9519: $css_class = ' class="LC_odd_row" ';
9520: }
9521: $datatable .= '<tr'.$css_class.'>'.
9522: '<td><span class="LC_nobreak">'.$lt{$item}.
1.306 raeburn 9523: '</span></td><td style="text-align: right">';
1.224 raeburn 9524: my @options = ('any');
9525: if (ref($rules) eq 'HASH') {
9526: if (keys(%{$rules}) > 0) {
9527: push(@options,('official','unofficial'));
1.37 raeburn 9528: }
9529: }
1.224 raeburn 9530: push(@options,'none');
1.37 raeburn 9531: foreach my $option (@options) {
1.50 raeburn 9532: my $type = 'radio';
1.34 raeburn 9533: my $check = ' ';
1.224 raeburn 9534: if ($checked{$item} eq $option) {
9535: $check = ' checked="checked" ';
1.34 raeburn 9536: }
9537: $datatable .= '<span class="LC_nobreak"><label>'.
1.50 raeburn 9538: '<input type="'.$type.'" name="can_createuser_'.
1.34 raeburn 9539: $item.'" value="'.$option.'"'.$check.'/> '.
9540: $lt{$option}.'</label> </span>';
9541: }
9542: $datatable .= '</td></tr>';
9543: }
1.28 raeburn 9544: } else {
9545: my @contexts = ('author','course','domain');
1.325 raeburn 9546: my @authtypes = ('int','krb4','krb5','loc','lti');
1.28 raeburn 9547: my %checked;
9548: if (ref($settings) eq 'HASH') {
9549: if (ref($settings->{'authtypes'}) eq 'HASH') {
9550: foreach my $item (@contexts) {
9551: if (ref($settings->{'authtypes'}{$item}) eq 'HASH') {
9552: foreach my $auth (@authtypes) {
9553: if ($settings->{'authtypes'}{$item}{$auth}) {
9554: $checked{$item}{$auth} = ' checked="checked" ';
9555: }
9556: }
9557: }
9558: }
1.27 raeburn 9559: }
1.35 raeburn 9560: } else {
9561: foreach my $item (@contexts) {
1.36 raeburn 9562: foreach my $auth (@authtypes) {
1.35 raeburn 9563: $checked{$item}{$auth} = ' checked="checked" ';
9564: }
9565: }
1.27 raeburn 9566: }
1.28 raeburn 9567: my %title = &context_names();
9568: my %authname = &authtype_names();
9569: my $rownum = 0;
9570: my $css_class;
9571: foreach my $item (@contexts) {
9572: if ($rownum%2) {
9573: $css_class = '';
9574: } else {
9575: $css_class = ' class="LC_odd_row" ';
9576: }
1.30 raeburn 9577: $datatable .= '<tr'.$css_class.'>'.
1.28 raeburn 9578: '<td>'.$title{$item}.
9579: '</td><td class="LC_left_item">'.
9580: '<span class="LC_nobreak">';
9581: foreach my $auth (@authtypes) {
9582: $datatable .= '<label>'.
9583: '<input type="checkbox" name="'.$item.'_auth" '.
9584: $checked{$item}{$auth}.' value="'.$auth.'" />'.
9585: $authname{$auth}.'</label> ';
9586: }
9587: $datatable .= '</span></td></tr>';
9588: $rownum ++;
1.27 raeburn 9589: }
1.30 raeburn 9590: $$rowtotal += $rownum;
1.27 raeburn 9591: }
9592: return $datatable;
9593: }
9594:
1.224 raeburn 9595: sub print_selfcreation {
9596: my ($position,$dom,$settings,$rowtotal) = @_;
1.305 raeburn 9597: my (@selfcreate,$createsettings,$processing,$emailoptions,$emailverified,
9598: $emaildomain,$datatable);
1.224 raeburn 9599: if (ref($settings) eq 'HASH') {
9600: if (ref($settings->{'cancreate'}) eq 'HASH') {
9601: $createsettings = $settings->{'cancreate'};
1.236 raeburn 9602: if (ref($createsettings) eq 'HASH') {
9603: if (ref($createsettings->{'selfcreate'}) eq 'ARRAY') {
9604: @selfcreate = @{$createsettings->{'selfcreate'}};
9605: } elsif ($createsettings->{'selfcreate'} ne '') {
9606: if ($settings->{'cancreate'}{'selfcreate'} eq 'any') {
9607: @selfcreate = ('email','login','sso');
9608: } elsif ($createsettings->{'selfcreate'} ne 'none') {
9609: @selfcreate = ($createsettings->{'selfcreate'});
9610: }
9611: }
9612: if (ref($createsettings->{'selfcreateprocessing'}) eq 'HASH') {
9613: $processing = $createsettings->{'selfcreateprocessing'};
1.224 raeburn 9614: }
1.305 raeburn 9615: if (ref($createsettings->{'emailoptions'}) eq 'HASH') {
9616: $emailoptions = $createsettings->{'emailoptions'};
9617: }
1.303 raeburn 9618: if (ref($createsettings->{'emailverified'}) eq 'HASH') {
9619: $emailverified = $createsettings->{'emailverified'};
9620: }
9621: if (ref($createsettings->{'emaildomain'}) eq 'HASH') {
9622: $emaildomain = $createsettings->{'emaildomain'};
9623: }
1.224 raeburn 9624: }
9625: }
9626: }
9627: my %radiohash;
9628: my $numinrow = 4;
9629: map { $radiohash{'cancreate_'.$_} = 1; } @selfcreate;
1.302 raeburn 9630: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.224 raeburn 9631: if ($position eq 'top') {
9632: my %choices = &Apache::lonlocal::texthash (
9633: cancreate_login => 'Institutional Login',
9634: cancreate_sso => 'Institutional Single Sign On',
9635: );
9636: my @toggles = sort(keys(%choices));
9637: my %defaultchecked = (
9638: 'cancreate_login' => 'off',
9639: 'cancreate_sso' => 'off',
9640: );
1.228 raeburn 9641: my ($onclick,$itemcount);
1.224 raeburn 9642: ($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
9643: \%choices,$itemcount,$onclick);
1.228 raeburn 9644: $$rowtotal += $itemcount;
1.425 raeburn 9645:
1.224 raeburn 9646: if (ref($usertypes) eq 'HASH') {
9647: if (keys(%{$usertypes}) > 0) {
9648: $datatable .= &insttypes_row($createsettings,$types,$usertypes,
9649: $dom,$numinrow,$othertitle,
1.305 raeburn 9650: 'statustocreate',$rowtotal);
1.224 raeburn 9651: $$rowtotal ++;
9652: }
9653: }
1.240 raeburn 9654: my @fields = ('lastname','firstname','middlename','permanentemail','id','inststatus');
9655: my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
9656: $fieldtitles{'inststatus'} = &mt('Institutional status');
9657: my $rem;
9658: my $numperrow = 2;
9659: my $css_class = $$rowtotal%2?' class="LC_odd_row"':'';
9660: $datatable .= '<tr'.$css_class.'>'.
1.241 raeburn 9661: '<td class="LC_left_item">'.&mt('Mapping of Shibboleth environment variable names to user data fields (SSO auth)').'</td>'.
1.240 raeburn 9662: '<td class="LC_left_item">'."\n".
1.334 raeburn 9663: '<table>'."\n";
1.240 raeburn 9664: for (my $i=0; $i<@fields; $i++) {
9665: $rem = $i%($numperrow);
9666: if ($rem == 0) {
9667: if ($i > 0) {
9668: $datatable .= '</tr>';
9669: }
9670: $datatable .= '<tr>';
9671: }
9672: my $currval;
1.248 raeburn 9673: if (ref($createsettings) eq 'HASH') {
9674: if (ref($createsettings->{'shibenv'}) eq 'HASH') {
9675: $currval = $createsettings->{'shibenv'}{$fields[$i]};
9676: }
1.240 raeburn 9677: }
9678: $datatable .= '<td class="LC_left_item">'.
9679: '<span class="LC_nobreak">'.
9680: '<input type="text" name="shibenv_'.$fields[$i].'" '.
9681: 'value="'.$currval.'" size="10" /> '.
9682: $fieldtitles{$fields[$i]}.'</span></td>';
9683: }
9684: my $colsleft = $numperrow - $rem;
9685: if ($colsleft > 1 ) {
9686: $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
9687: ' </td>';
9688: } elsif ($colsleft == 1) {
9689: $datatable .= '<td class="LC_left_item"> </td>';
9690: }
9691: $datatable .= '</tr></table></td></tr>';
9692: $$rowtotal ++;
1.224 raeburn 9693: } elsif ($position eq 'middle') {
9694: my %domconf = &Apache::lonnet::get_dom('configuration',['usermodification'],$dom);
1.302 raeburn 9695: my @posstypes;
1.224 raeburn 9696: if (ref($types) eq 'ARRAY') {
1.302 raeburn 9697: @posstypes = @{$types};
9698: }
9699: unless (grep(/^default$/,@posstypes)) {
9700: push(@posstypes,'default');
9701: }
9702: my %usertypeshash;
9703: if (ref($usertypes) eq 'HASH') {
9704: %usertypeshash = %{$usertypes};
9705: }
9706: $usertypeshash{'default'} = $othertitle;
9707: foreach my $status (@posstypes) {
9708: $datatable .= &modifiable_userdata_row('selfcreate',$status,$domconf{'usermodification'},
9709: $numinrow,$$rowtotal,\%usertypeshash);
9710: $$rowtotal ++;
1.224 raeburn 9711: }
9712: } else {
1.236 raeburn 9713: my %choices = &Apache::lonlocal::texthash (
1.305 raeburn 9714: 'cancreate_email' => 'Non-institutional username (via e-mail verification)',
1.236 raeburn 9715: );
9716: my @toggles = sort(keys(%choices));
9717: my %defaultchecked = (
9718: 'cancreate_email' => 'off',
9719: );
1.305 raeburn 9720: my $customclass = 'LC_selfcreate_email';
9721: my $classprefix = 'LC_canmodify_emailusername_';
9722: my $optionsprefix = 'LC_options_emailusername_';
1.236 raeburn 9723: my $display = 'none';
1.305 raeburn 9724: my $rowstyle = 'display:none';
1.236 raeburn 9725: if (grep(/^\Qemail\E$/,@selfcreate)) {
9726: $display = 'block';
1.305 raeburn 9727: $rowstyle = 'display:table-row';
1.236 raeburn 9728: }
1.305 raeburn 9729: my $onclick = "toggleRows(this.form,'cancreate_email','selfassign','$customclass','$classprefix','$optionsprefix');";
9730: ($datatable,$$rowtotal) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
9731: \%choices,$$rowtotal,$onclick);
9732: $datatable .= &print_requestmail($dom,'selfcreation',$createsettings,$rowtotal,$customclass,
9733: $rowstyle);
9734: $$rowtotal ++;
9735: $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal,$customclass,
9736: $rowstyle);
9737: $$rowtotal ++;
9738: my (@ordered,@posstypes,%usertypeshash);
1.236 raeburn 9739: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
1.305 raeburn 9740: my ($emailrules,$emailruleorder) =
9741: &Apache::lonnet::inst_userrules($dom,'email');
9742: my $primary_id = &Apache::lonnet::domain($dom,'primary');
9743: my $intdom = &Apache::lonnet::internet_dom($primary_id);
9744: if (ref($types) eq 'ARRAY') {
9745: @posstypes = @{$types};
9746: }
9747: if (@posstypes) {
9748: unless (grep(/^default$/,@posstypes)) {
9749: push(@posstypes,'default');
1.302 raeburn 9750: }
9751: if (ref($usertypes) eq 'HASH') {
9752: %usertypeshash = %{$usertypes};
9753: }
1.305 raeburn 9754: my $currassign;
9755: if (ref($domdefaults{'inststatusguest'}) eq 'ARRAY') {
9756: $currassign = {
9757: selfassign => $domdefaults{'inststatusguest'},
9758: };
9759: @ordered = @{$domdefaults{'inststatusguest'}};
9760: } else {
9761: $currassign = { selfassign => [] };
9762: }
9763: my $onclicktypes = "toggleDataRow(this.form,'selfassign','$customclass','$optionsprefix',);".
9764: "toggleDataRow(this.form,'selfassign','$customclass','$classprefix',1);";
9765: $datatable .= &insttypes_row($currassign,$types,$usertypes,$dom,
9766: $numinrow,$othertitle,'selfassign',
9767: $rowtotal,$onclicktypes,$customclass,
9768: $rowstyle);
9769: $$rowtotal ++;
1.302 raeburn 9770: $usertypeshash{'default'} = $othertitle;
1.305 raeburn 9771: foreach my $status (@posstypes) {
9772: my $css_class;
9773: if ($$rowtotal%2) {
9774: $css_class = 'LC_odd_row ';
9775: }
9776: $css_class .= $customclass;
9777: my $rowid = $optionsprefix.$status;
9778: my $hidden = 1;
9779: my $currstyle = 'display:none';
9780: if (grep(/^\Q$status\E$/,@ordered)) {
9781: $currstyle = $rowstyle;
1.425 raeburn 9782: $hidden = 0;
1.305 raeburn 9783: }
9784: $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,
9785: $emailrules,$emailruleorder,$settings,$status,$rowid,
9786: $usertypeshash{$status},$css_class,$currstyle,$intdom);
9787: unless ($hidden) {
9788: $$rowtotal ++;
9789: }
1.224 raeburn 9790: }
1.302 raeburn 9791: } else {
1.305 raeburn 9792: my $css_class;
9793: if ($$rowtotal%2) {
9794: $css_class = 'LC_odd_row ';
9795: }
9796: $css_class .= $customclass;
1.302 raeburn 9797: $usertypeshash{'default'} = $othertitle;
1.305 raeburn 9798: $datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,
9799: $emailrules,$emailruleorder,$settings,'default','',
9800: $othertitle,$css_class,$rowstyle,$intdom);
9801: $$rowtotal ++;
1.224 raeburn 9802: }
9803: my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
1.228 raeburn 9804: $numinrow = 1;
1.305 raeburn 9805: if (@posstypes) {
9806: foreach my $status (@posstypes) {
9807: my $rowid = $classprefix.$status;
9808: my $datarowstyle = 'display:none';
1.425 raeburn 9809: if (grep(/^\Q$status\E$/,@ordered)) {
9810: $datarowstyle = $rowstyle;
1.305 raeburn 9811: }
9812: $datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
9813: $numinrow,$$rowtotal,\%usertypeshash,$infofields,
9814: $infotitles,$rowid,$customclass,$datarowstyle);
9815: unless ($datarowstyle eq 'display:none') {
9816: $$rowtotal ++;
9817: }
1.224 raeburn 9818: }
1.305 raeburn 9819: } else {
9820: $datatable .= &modifiable_userdata_row('cancreate','emailusername_default',$settings,
9821: $numinrow,$$rowtotal,\%usertypeshash,$infofields,
9822: $infotitles,'',$customclass,$rowstyle);
1.224 raeburn 9823: }
9824: }
9825: return $datatable;
9826: }
9827:
1.305 raeburn 9828: sub selfcreate_javascript {
9829: return <<"ENDSCRIPT";
9830:
9831: <script type="text/javascript">
9832: // <![CDATA[
9833:
9834: function toggleRows(form,radio,checkbox,target,prefix,altprefix) {
9835: var x = document.getElementsByClassName(target);
9836: var insttypes = 0;
9837: var insttypeRegExp = new RegExp(prefix);
9838: if ((x.length != undefined) && (x.length > 0)) {
9839: if (form.elements[radio].length != undefined) {
9840: for (var i=0; i<form.elements[radio].length; i++) {
9841: if (form.elements[radio][i].checked) {
9842: if (form.elements[radio][i].value == 1) {
9843: for (var j=0; j<x.length; j++) {
9844: if (x[j].id == 'undefined') {
9845: x[j].style.display = 'table-row';
9846: } else if (insttypeRegExp.test(x[j].id)) {
9847: insttypes ++;
9848: } else {
9849: x[j].style.display = 'table-row';
9850: }
9851: }
9852: } else {
9853: for (var j=0; j<x.length; j++) {
9854: x[j].style.display = 'none';
9855: }
1.236 raeburn 9856: }
1.305 raeburn 9857: break;
9858: }
9859: }
9860: if (insttypes > 0) {
9861: toggleDataRow(form,checkbox,target,altprefix);
9862: toggleDataRow(form,checkbox,target,prefix,1);
9863: }
9864: }
9865: }
9866: return;
9867: }
9868:
9869: function toggleDataRow(form,checkbox,target,prefix,docount) {
9870: if (form.elements[checkbox].length != undefined) {
9871: var count = 0;
9872: if (docount) {
9873: for (var i=0; i<form.elements[checkbox].length; i++) {
9874: if (form.elements[checkbox][i].checked) {
9875: count ++;
1.236 raeburn 9876: }
1.305 raeburn 9877: }
9878: }
9879: for (var i=0; i<form.elements[checkbox].length; i++) {
9880: var type = form.elements[checkbox][i].value;
9881: if (document.getElementById(prefix+type)) {
9882: if (form.elements[checkbox][i].checked) {
9883: document.getElementById(prefix+type).style.display = 'table-row';
9884: if (count % 2 == 1) {
9885: document.getElementById(prefix+type).className = target+' LC_odd_row';
9886: } else {
9887: document.getElementById(prefix+type).className = target;
1.236 raeburn 9888: }
1.305 raeburn 9889: count ++;
1.236 raeburn 9890: } else {
1.305 raeburn 9891: document.getElementById(prefix+type).style.display = 'none';
9892: }
9893: }
9894: }
9895: }
9896: return;
9897: }
9898:
9899: function toggleEmailOptions(form,radio,prefix,altprefix,status) {
9900: var caller = radio+'_'+status;
9901: if (form.elements[caller].length != undefined) {
9902: for (var i=0; i<form.elements[caller].length; i++) {
9903: if (form.elements[caller][i].checked) {
9904: if (document.getElementById(altprefix+'_inst_'+status)) {
9905: var curr = form.elements[caller][i].value;
9906: if (prefix) {
9907: document.getElementById(prefix+'_'+status).style.display = 'none';
9908: }
9909: document.getElementById(altprefix+'_inst_'+status).style.display = 'none';
9910: document.getElementById(altprefix+'_noninst_'+status).style.display = 'none';
9911: if (curr == 'custom') {
1.425 raeburn 9912: if (prefix) {
1.305 raeburn 9913: document.getElementById(prefix+'_'+status).style.display = 'inline';
9914: }
9915: } else if (curr == 'inst') {
9916: document.getElementById(altprefix+'_inst_'+status).style.display = 'inline';
9917: } else if (curr == 'noninst') {
9918: document.getElementById(altprefix+'_noninst_'+status).style.display = 'inline';
1.236 raeburn 9919: }
1.305 raeburn 9920: break;
1.236 raeburn 9921: }
9922: }
9923: }
9924: }
9925: }
9926:
1.305 raeburn 9927: // ]]>
9928: </script>
9929:
9930: ENDSCRIPT
9931: }
9932:
9933: sub noninst_users {
9934: my ($processing,$emailverified,$emailoptions,$emaildomain,$emailrules,
1.425 raeburn 9935: $emailruleorder,$settings,$type,$rowid,$typetitle,$css_class,$rowstyle,$intdom) = @_;
1.305 raeburn 9936: my $class = 'LC_left_item';
9937: if ($css_class) {
1.425 raeburn 9938: $css_class = ' class="'.$css_class.'"';
1.305 raeburn 9939: }
9940: if ($rowid) {
9941: $rowid = ' id="'.$rowid.'"';
9942: }
9943: if ($rowstyle) {
9944: $rowstyle = ' style="'.$rowstyle.'"';
9945: }
9946: my ($output,$description);
9947: if ($type eq 'default') {
9948: $description = &mt('Requests for: [_1]',$typetitle);
9949: } else {
9950: $description = &mt('Requests for: [_1] (status self-reported)',$typetitle);
9951: }
9952: $output = '<tr'.$css_class.$rowid.$rowstyle.'>'.
1.425 raeburn 9953: "<td>$description</td>\n".
1.305 raeburn 9954: '<td class="'.$class.'" colspan="2">'.
9955: '<table><tr>';
1.425 raeburn 9956: my %headers = &Apache::lonlocal::texthash(
1.305 raeburn 9957: approve => 'Processing',
9958: email => 'E-mail',
9959: username => 'Username',
9960: );
9961: foreach my $item ('approve','email','username') {
9962: $output .= '<th>'.$headers{$item}.'</th>';
1.303 raeburn 9963: }
1.305 raeburn 9964: $output .= '</tr><tr>';
9965: foreach my $item ('approve','email','username') {
1.306 raeburn 9966: $output .= '<td style="vertical-align: top">';
1.305 raeburn 9967: my (%choices,@options,$hashref,$defoption,$name,$onclick,$hascustom);
9968: if ($item eq 'approve') {
9969: %choices = &Apache::lonlocal::texthash (
9970: automatic => 'Automatically approved',
9971: approval => 'Queued for approval',
9972: );
9973: @options = ('automatic','approval');
9974: $hashref = $processing;
9975: $defoption = 'automatic';
9976: $name = 'cancreate_emailprocess_'.$type;
9977: } elsif ($item eq 'email') {
9978: %choices = &Apache::lonlocal::texthash (
9979: any => 'Any e-mail',
9980: inst => 'Institutional only',
9981: noninst => 'Non-institutional only',
9982: custom => 'Custom restrictions',
9983: );
9984: @options = ('any','inst','noninst');
9985: my $showcustom;
9986: if (ref($emailrules) eq 'HASH') {
9987: if (keys(%{$emailrules}) > 0) {
9988: push(@options,'custom');
9989: $showcustom = 'cancreate_emailrule';
9990: if (ref($settings) eq 'HASH') {
9991: if (ref($settings->{'email_rule'}) eq 'ARRAY') {
9992: foreach my $rule (@{$settings->{'email_rule'}}) {
9993: if (exists($emailrules->{$rule})) {
9994: $hascustom ++;
9995: }
9996: }
9997: } elsif (ref($settings->{'email_rule'}) eq 'HASH') {
9998: if (ref($settings->{'email_rule'}{$type}) eq 'ARRAY') {
9999: foreach my $rule (@{$settings->{'email_rule'}{$type}}) {
10000: if (exists($emailrules->{$rule})) {
10001: $hascustom ++;
10002: }
10003: }
10004: }
10005: }
10006: }
10007: }
10008: }
10009: $onclick = ' onclick="toggleEmailOptions(this.form,'."'cancreate_emailoptions','$showcustom',".
10010: "'cancreate_emaildomain','$type'".');"';
10011: $hashref = $emailoptions;
10012: $defoption = 'any';
10013: $name = 'cancreate_emailoptions_'.$type;
10014: } elsif ($item eq 'username') {
10015: %choices = &Apache::lonlocal::texthash (
10016: all => 'Same as e-mail',
10017: first => 'Omit @domain',
10018: free => 'Free to choose',
10019: );
10020: @options = ('all','first','free');
10021: $hashref = $emailverified;
10022: $defoption = 'all';
10023: $name = 'cancreate_usernameoptions_'.$type;
10024: }
10025: foreach my $option (@options) {
10026: my $checked;
10027: if (ref($hashref) eq 'HASH') {
10028: if ($type eq '') {
10029: if (!exists($hashref->{'default'})) {
10030: if ($option eq $defoption) {
10031: $checked = ' checked="checked"';
10032: }
10033: } else {
10034: if ($hashref->{'default'} eq $option) {
10035: $checked = ' checked="checked"';
10036: }
1.303 raeburn 10037: }
10038: } else {
1.305 raeburn 10039: if (!exists($hashref->{$type})) {
10040: if ($option eq $defoption) {
10041: $checked = ' checked="checked"';
10042: }
10043: } else {
10044: if ($hashref->{$type} eq $option) {
10045: $checked = ' checked="checked"';
10046: }
1.303 raeburn 10047: }
10048: }
1.305 raeburn 10049: } elsif (($item eq 'email') && ($hascustom)) {
10050: if ($option eq 'custom') {
10051: $checked = ' checked="checked"';
10052: }
10053: } elsif ($option eq $defoption) {
10054: $checked = ' checked="checked"';
10055: }
10056: $output .= '<span class="LC_nobreak"><label>'.
10057: '<input type="radio" name="'.$name.'"'.
10058: $checked.' value="'.$option.'"'.$onclick.' />'.
10059: $choices{$option}.'</label></span><br />';
10060: if ($item eq 'email') {
10061: if ($option eq 'custom') {
10062: my $id = 'cancreate_emailrule_'.$type;
10063: my $display = 'none';
10064: if ($checked) {
10065: $display = 'inline';
1.303 raeburn 10066: }
1.305 raeburn 10067: my $numinrow = 2;
10068: $output .= '<fieldset id="'.$id.'" style="display:'.$display.';">'.
10069: '<legend>'.&mt('Disallow').'</legend><table>'.
10070: &user_formats_row('email',$settings,$emailrules,
10071: $emailruleorder,$numinrow,'',$type);
10072: '</table></fieldset>';
10073: } elsif (($option eq 'inst') || ($option eq 'noninst')) {
10074: my %text = &Apache::lonlocal::texthash (
10075: inst => 'must end:',
10076: noninst => 'cannot end:',
10077: );
10078: my $value;
10079: if (ref($emaildomain) eq 'HASH') {
10080: if (ref($emaildomain->{$type}) eq 'HASH') {
1.425 raeburn 10081: $value = $emaildomain->{$type}->{$option};
1.303 raeburn 10082: }
10083: }
1.305 raeburn 10084: if ($value eq '') {
10085: $value = '@'.$intdom;
10086: }
10087: my $condition = 'cancreate_emaildomain_'.$option.'_'.$type;
10088: my $display = 'none';
10089: if ($checked) {
10090: $display = 'inline';
10091: }
10092: $output .= '<div id="'.$condition.'" style="display:'.$display.';">'.
10093: '<span class="LC_domprefs_email">'.$text{$option}.'</span> '.
10094: '<input type="text" name="'.$condition.'" value="'.$value.'" size="10" />'.
10095: '</div>';
1.303 raeburn 10096: }
10097: }
10098: }
1.305 raeburn 10099: $output .= '</td>'."\n";
1.303 raeburn 10100: }
1.305 raeburn 10101: $output .= "</tr></table></td></tr>\n";
1.303 raeburn 10102: return $output;
10103: }
10104:
1.165 raeburn 10105: sub captcha_choice {
1.305 raeburn 10106: my ($context,$settings,$itemcount,$customcss,$rowstyle) = @_;
1.269 raeburn 10107: my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext,
10108: $vertext,$currver);
1.165 raeburn 10109: my %lt = &captcha_phrases();
10110: $keyentry = 'hidden';
1.354 raeburn 10111: my $colspan=2;
1.165 raeburn 10112: if ($context eq 'cancreate') {
1.224 raeburn 10113: $rowname = &mt('CAPTCHA validation');
1.169 raeburn 10114: } elsif ($context eq 'login') {
10115: $rowname = &mt('"Contact helpdesk" CAPTCHA validation');
1.354 raeburn 10116: } elsif ($context eq 'passwords') {
10117: $rowname = &mt('"Forgot Password" CAPTCHA validation');
10118: $colspan=1;
1.165 raeburn 10119: }
10120: if (ref($settings) eq 'HASH') {
10121: if ($settings->{'captcha'}) {
10122: $checked{$settings->{'captcha'}} = ' checked="checked"';
10123: } else {
10124: $checked{'original'} = ' checked="checked"';
10125: }
10126: if ($settings->{'captcha'} eq 'recaptcha') {
10127: $pubtext = $lt{'pub'};
10128: $privtext = $lt{'priv'};
10129: $keyentry = 'text';
1.269 raeburn 10130: $vertext = $lt{'ver'};
10131: $currver = $settings->{'recaptchaversion'};
10132: if ($currver ne '2') {
10133: $currver = 1;
10134: }
1.165 raeburn 10135: }
10136: if (ref($settings->{'recaptchakeys'}) eq 'HASH') {
10137: $currpub = $settings->{'recaptchakeys'}{'public'};
10138: $currpriv = $settings->{'recaptchakeys'}{'private'};
10139: }
10140: } else {
10141: $checked{'original'} = ' checked="checked"';
10142: }
1.305 raeburn 10143: my $css_class;
10144: if ($itemcount%2) {
10145: $css_class = 'LC_odd_row';
10146: }
10147: if ($customcss) {
10148: $css_class .= " $customcss";
10149: }
10150: $css_class =~ s/^\s+//;
10151: if ($css_class) {
10152: $css_class = ' class="'.$css_class.'"';
10153: }
10154: if ($rowstyle) {
10155: $css_class .= ' style="'.$rowstyle.'"';
10156: }
1.169 raeburn 10157: my $output = '<tr'.$css_class.'>'.
1.354 raeburn 10158: '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="'.$colspan.'">'."\n".
1.165 raeburn 10159: '<table><tr><td>'."\n";
10160: foreach my $option ('original','recaptcha','notused') {
10161: $output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.
10162: $option.'" '.$checked{$option}.' onchange="javascript:updateCaptcha('."this,'$context'".');" />'.
10163: $lt{$option}.'</label></span>';
10164: unless ($option eq 'notused') {
10165: $output .= (' 'x2)."\n";
10166: }
10167: }
10168: #
10169: # Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit:
10170: # https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple
1.210 raeburn 10171: # servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu)
1.165 raeburn 10172: # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain.
1.210 raeburn 10173: #
1.165 raeburn 10174: $output .= '</td></tr>'."\n".
1.305 raeburn 10175: '<tr><td class="LC_zero_height">'."\n".
1.165 raeburn 10176: '<span class="LC_nobreak"><span id="'.$context.'_recaptchapubtxt">'.$pubtext.'</span> '."\n".
10177: '<input type="'.$keyentry.'" id="'.$context.'_recaptchapub" name="'.$context.'_recaptchapub" value="'.
10178: $currpub.'" size="40" /></span><br />'."\n".
10179: '<span class="LC_nobreak"><span id="'.$context.'_recaptchaprivtxt">'.$privtext.'</span> '."\n".
10180: '<input type="'.$keyentry.'" id="'.$context.'_recaptchapriv" name="'.$context.'_recaptchapriv" value="'.
1.269 raeburn 10181: $currpriv.'" size="40" /></span><br />'.
10182: '<span class="LC_nobreak"><span id="'.$context.'_recaptchavertxt">'.$vertext.'</span> '."\n".
10183: '<input type="'.$keyentry.'" id="'.$context.'_recaptchaversion" name="'.$context.'_recaptchaversion" value="'.
10184: $currver.'" size="3" /></span><br />'.
10185: '</td></tr></table>'."\n".
1.165 raeburn 10186: '</td></tr>';
10187: return $output;
10188: }
10189:
1.32 raeburn 10190: sub user_formats_row {
1.305 raeburn 10191: my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount,$status) = @_;
1.32 raeburn 10192: my $output;
10193: my %text = (
10194: 'username' => 'new usernames',
10195: 'id' => 'IDs',
10196: );
1.409 raeburn 10197: unless (($type eq 'email') || ($type eq 'unamemap')) {
1.305 raeburn 10198: my $css_class = $rowcount%2?' class="LC_odd_row"':'';
10199: $output = '<tr '.$css_class.'>'.
10200: '<td><span class="LC_nobreak">'.
10201: &mt("Format rules to check for $text{$type}: ").
10202: '</td><td class="LC_left_item" colspan="2"><table>';
1.63 raeburn 10203: }
1.27 raeburn 10204: my $rem;
10205: if (ref($ruleorder) eq 'ARRAY') {
10206: for (my $i=0; $i<@{$ruleorder}; $i++) {
10207: if (ref($rules->{$ruleorder->[$i]}) eq 'HASH') {
10208: my $rem = $i%($numinrow);
10209: if ($rem == 0) {
10210: if ($i > 0) {
10211: $output .= '</tr>';
10212: }
10213: $output .= '<tr>';
10214: }
10215: my $check = ' ';
1.39 raeburn 10216: if (ref($settings) eq 'HASH') {
10217: if (ref($settings->{$type.'_rule'}) eq 'ARRAY') {
10218: if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}})) {
10219: $check = ' checked="checked" ';
10220: }
1.305 raeburn 10221: } elsif ((ref($settings->{$type.'_rule'}) eq 'HASH') && ($status ne '')) {
10222: if (ref($settings->{$type.'_rule'}->{$status}) eq 'ARRAY') {
10223: if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}->{$status}})) {
10224: $check = ' checked="checked" ';
10225: }
10226: }
1.27 raeburn 10227: }
10228: }
1.305 raeburn 10229: my $name = $type.'_rule';
10230: if ($type eq 'email') {
10231: $name .= '_'.$status;
10232: }
1.27 raeburn 10233: $output .= '<td class="LC_left_item">'.
10234: '<span class="LC_nobreak"><label>'.
1.311 raeburn 10235: '<input type="checkbox" name="'.$name.'" '.
1.27 raeburn 10236: 'value="'.$ruleorder->[$i].'"'.$check.'/>'.
10237: $rules->{$ruleorder->[$i]}{'name'}.'</label></span></td>';
10238: }
10239: }
10240: $rem = @{$ruleorder}%($numinrow);
10241: }
1.305 raeburn 10242: my $colsleft;
10243: if ($rem) {
10244: $colsleft = $numinrow - $rem;
10245: }
1.27 raeburn 10246: if ($colsleft > 1 ) {
10247: $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
10248: ' </td>';
10249: } elsif ($colsleft == 1) {
10250: $output .= '<td class="LC_left_item"> </td>';
10251: }
1.409 raeburn 10252: $output .= '</tr>';
10253: unless (($type eq 'email') || ($type eq 'unamemap')) {
10254: $output .= '</table></td></tr>';
1.305 raeburn 10255: }
1.27 raeburn 10256: return $output;
10257: }
10258:
1.34 raeburn 10259: sub usercreation_types {
10260: my %lt = &Apache::lonlocal::texthash (
10261: author => 'When adding a co-author',
10262: course => 'When adding a user to a course',
1.100 raeburn 10263: requestcrs => 'When requesting a course',
1.34 raeburn 10264: any => 'Any',
10265: official => 'Institutional only ',
10266: unofficial => 'Non-institutional only',
10267: none => 'None',
10268: );
10269: return %lt;
1.48 raeburn 10270: }
1.34 raeburn 10271:
1.224 raeburn 10272: sub selfcreation_types {
10273: my %lt = &Apache::lonlocal::texthash (
10274: selfcreate => 'User creates own account',
10275: any => 'Any',
10276: official => 'Institutional only ',
10277: unofficial => 'Non-institutional only',
10278: email => 'E-mail address',
10279: login => 'Institutional Login',
10280: sso => 'SSO',
10281: );
10282: }
10283:
1.28 raeburn 10284: sub authtype_names {
10285: my %lt = &Apache::lonlocal::texthash(
10286: int => 'Internal',
10287: krb4 => 'Kerberos 4',
10288: krb5 => 'Kerberos 5',
10289: loc => 'Local',
1.325 raeburn 10290: lti => 'LTI',
1.28 raeburn 10291: );
10292: return %lt;
10293: }
10294:
10295: sub context_names {
10296: my %context_title = &Apache::lonlocal::texthash(
10297: author => 'Creating users when an Author',
10298: course => 'Creating users when in a course',
10299: domain => 'Creating users when a Domain Coordinator',
10300: );
10301: return %context_title;
10302: }
10303:
1.33 raeburn 10304: sub print_usermodification {
10305: my ($position,$dom,$settings,$rowtotal) = @_;
10306: my $numinrow = 4;
10307: my ($context,$datatable,$rowcount);
10308: if ($position eq 'top') {
10309: $rowcount = 0;
10310: $context = 'author';
10311: foreach my $role ('ca','aa') {
10312: $datatable .= &modifiable_userdata_row($context,$role,$settings,
10313: $numinrow,$rowcount);
10314: $$rowtotal ++;
10315: $rowcount ++;
10316: }
1.230 raeburn 10317: } elsif ($position eq 'bottom') {
1.33 raeburn 10318: $context = 'course';
10319: $rowcount = 0;
10320: foreach my $role ('st','ep','ta','in','cr') {
10321: $datatable .= &modifiable_userdata_row($context,$role,$settings,
10322: $numinrow,$rowcount);
10323: $$rowtotal ++;
10324: $rowcount ++;
10325: }
10326: }
10327: return $datatable;
10328: }
10329:
1.43 raeburn 10330: sub print_defaults {
1.236 raeburn 10331: my ($position,$dom,$settings,$rowtotal) = @_;
1.43 raeburn 10332: my $rownum = 0;
1.294 raeburn 10333: my ($datatable,$css_class,$titles);
10334: unless ($position eq 'bottom') {
10335: $titles = &defaults_titles($dom);
10336: }
1.236 raeburn 10337: if ($position eq 'top') {
10338: my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
10339: 'datelocale_def','portal_def');
10340: my %defaults;
10341: if (ref($settings) eq 'HASH') {
10342: %defaults = %{$settings};
1.43 raeburn 10343: } else {
1.236 raeburn 10344: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
10345: foreach my $item (@items) {
10346: $defaults{$item} = $domdefaults{$item};
10347: }
1.43 raeburn 10348: }
1.236 raeburn 10349: foreach my $item (@items) {
10350: if ($rownum%2) {
10351: $css_class = '';
10352: } else {
10353: $css_class = ' class="LC_odd_row" ';
10354: }
10355: $datatable .= '<tr'.$css_class.'>'.
10356: '<td><span class="LC_nobreak">'.$titles->{$item}.
10357: '</span></td><td class="LC_right_item" colspan="3">';
10358: if ($item eq 'auth_def') {
1.325 raeburn 10359: my @authtypes = ('internal','krb4','krb5','localauth','lti');
1.236 raeburn 10360: my %shortauth = (
10361: internal => 'int',
10362: krb4 => 'krb4',
10363: krb5 => 'krb5',
1.325 raeburn 10364: localauth => 'loc',
10365: lti => 'lti',
1.236 raeburn 10366: );
10367: my %authnames = &authtype_names();
10368: foreach my $auth (@authtypes) {
10369: my $checked = ' ';
10370: if ($defaults{$item} eq $auth) {
10371: $checked = ' checked="checked" ';
10372: }
10373: $datatable .= '<label><input type="radio" name="'.$item.
10374: '" value="'.$auth.'"'.$checked.'/>'.
10375: $authnames{$shortauth{$auth}}.'</label> ';
10376: }
10377: } elsif ($item eq 'timezone_def') {
10378: my $includeempty = 1;
10379: $datatable .= &Apache::loncommon::select_timezone($item,$defaults{$item},undef,$includeempty);
10380: } elsif ($item eq 'datelocale_def') {
10381: my $includeempty = 1;
10382: $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);
10383: } elsif ($item eq 'lang_def') {
1.263 raeburn 10384: my $includeempty = 1;
10385: $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);
1.414 raeburn 10386: } elsif ($item eq 'portal_def') {
10387: $datatable .= '<input type="text" name="'.$item.'" value="'.
10388: $defaults{$item}.'" size="25" onkeyup="portalExtras(this);" />';
10389: my $portalsty = 'none';
10390: if ($defaults{$item}) {
10391: $portalsty = 'block';
10392: }
10393: foreach my $field ('email','web') {
10394: my $checkedoff = ' checked="checked"';
10395: my $checkedon;
10396: if ($defaults{$item.'_'.$field}) {
10397: $checkedon = $checkedoff;
10398: $checkedoff = '';
1.425 raeburn 10399: }
1.414 raeburn 10400: $datatable .= '<div id="'.$item.'_'.$field.'_div" style="display:'.$portalsty.'">'.
10401: '<span class="LC_nobreak">'.$titles->{$field}.' '.
10402: '<label><input type="radio" name="'.$item.'_'.$field.'" value="1"'.$checkedon.'/>'.&mt('Yes').'</label>'.
10403: (' 'x2).
10404: '<label><input type="radio" name="'.$item.'_'.$field.'" value="0"'.$checkedoff.'/>'.&mt('No').'</label>'.
10405: '</div>';
10406: }
1.236 raeburn 10407: } else {
1.414 raeburn 10408: $datatable .= '<input type="text" name="'.$item.'" value="'.$defaults{$item}.'" />';
1.43 raeburn 10409: }
1.236 raeburn 10410: $datatable .= '</td></tr>';
10411: $rownum ++;
10412: }
1.409 raeburn 10413: } elsif ($position eq 'middle') {
1.294 raeburn 10414: my %defaults;
10415: if (ref($settings) eq 'HASH') {
1.354 raeburn 10416: if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
10417: my $maxnum = @{$settings->{'inststatusorder'}};
10418: for (my $i=0; $i<$maxnum; $i++) {
10419: $css_class = $rownum%2?' class="LC_odd_row"':'';
10420: my $item = $settings->{'inststatusorder'}->[$i];
10421: my $title = $settings->{'inststatustypes'}->{$item};
10422: my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'$item'".');"';
10423: $datatable .= '<tr'.$css_class.'>'.
10424: '<td><span class="LC_nobreak">'.
10425: '<select name="inststatus_pos_'.$item.'"'.$chgstr.'>';
10426: for (my $k=0; $k<=$maxnum; $k++) {
10427: my $vpos = $k+1;
10428: my $selstr;
10429: if ($k == $i) {
10430: $selstr = ' selected="selected" ';
10431: }
10432: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
10433: }
10434: $datatable .= '</select> '.&mt('Internal ID:').' <b>'.$item.'</b> '.
10435: '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.
10436: &mt('delete').'</span></td>'.
1.380 raeburn 10437: '<td class="LC_left_item" colspan="2"><span class="LC_nobreak">'.&mt('Name displayed').':'.
1.354 raeburn 10438: '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.
10439: '</span></td></tr>';
10440: }
10441: $css_class = $rownum%2?' class="LC_odd_row"':'';
10442: my $chgstr = ' onchange="javascript:reorderTypes(this.form,'."'addinststatus_pos'".');"';
10443: $datatable .= '<tr '.$css_class.'>'.
10444: '<td><span class="LC_nobreak"><select name="addinststatus_pos"'.$chgstr.'>';
10445: for (my $k=0; $k<=$maxnum; $k++) {
10446: my $vpos = $k+1;
10447: my $selstr;
10448: if ($k == $maxnum) {
10449: $selstr = ' selected="selected" ';
10450: }
10451: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
10452: }
10453: $datatable .= '</select> '.&mt('Internal ID:').
10454: '<input type="text" size="10" name="addinststatus" value="" />'.
10455: ' '.&mt('(new)').
10456: '</span></td><td class="LC_left_item" colspan="2"><span class="LC_nobreak">'.
1.380 raeburn 10457: &mt('Name displayed').':'.
1.354 raeburn 10458: '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.
10459: '</tr>'."\n";
10460: $rownum ++;
1.294 raeburn 10461: }
1.354 raeburn 10462: }
1.409 raeburn 10463: } else {
10464: my ($unamemaprules,$ruleorder) =
10465: &Apache::lonnet::inst_userrules($dom,'unamemap');
10466: $css_class = $rownum%2?' class="LC_odd_row"':'';
10467: if ((ref($unamemaprules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {
10468: my $numinrow = 2;
10469: $datatable .= '<tr'.$css_class.'><td>'.&mt('Available conversions').'</td><td><table>'.
10470: &user_formats_row('unamemap',$settings,$unamemaprules,
10471: $ruleorder,$numinrow).
10472: '</table></td></tr>';
10473: }
10474: if ($datatable eq '') {
10475: $datatable .= '<tr'.$css_class.'><td colspan="2">'.
10476: &mt('No rules set for domain in customized localenroll.pm').
10477: '</td></tr>';
10478: }
1.354 raeburn 10479: }
10480: $$rowtotal += $rownum;
1.43 raeburn 10481: return $datatable;
10482: }
10483:
1.168 raeburn 10484: sub get_languages_hash {
10485: my %langchoices;
10486: foreach my $id (&Apache::loncommon::languageids()) {
10487: my $code = &Apache::loncommon::supportedlanguagecode($id);
10488: if ($code ne '') {
10489: $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id);
10490: }
10491: }
10492: return %langchoices;
10493: }
10494:
1.43 raeburn 10495: sub defaults_titles {
1.141 raeburn 10496: my ($dom) = @_;
1.43 raeburn 10497: my %titles = &Apache::lonlocal::texthash (
10498: 'auth_def' => 'Default authentication type',
10499: 'auth_arg_def' => 'Default authentication argument',
10500: 'lang_def' => 'Default language',
1.54 raeburn 10501: 'timezone_def' => 'Default timezone',
1.68 raeburn 10502: 'datelocale_def' => 'Default locale for dates',
1.141 raeburn 10503: 'portal_def' => 'Portal/Default URL',
1.414 raeburn 10504: 'email' => 'Email links use portal URL',
10505: 'web' => 'Public web links use portal URL',
1.294 raeburn 10506: 'intauth_cost' => 'Encryption cost for bcrypt (positive integer)',
10507: 'intauth_check' => 'Check bcrypt cost if authenticated',
10508: 'intauth_switch' => 'Existing crypt-based switched to bcrypt on authentication',
1.43 raeburn 10509: );
1.141 raeburn 10510: if ($dom) {
10511: my $uprimary_id = &Apache::lonnet::domain($dom,'primary');
10512: my $uint_dom = &Apache::lonnet::internet_dom($uprimary_id);
10513: my $protocol = $Apache::lonnet::protocol{$uprimary_id};
10514: $protocol = 'http' if ($protocol ne 'https');
10515: if ($uint_dom) {
10516: $titles{'portal_def'} .= ' '.&mt('(for example: [_1])',$protocol.'://loncapa.'.
10517: $uint_dom);
10518: }
10519: }
1.43 raeburn 10520: return (\%titles);
10521: }
10522:
1.346 raeburn 10523: sub print_scantron {
10524: my ($r,$position,$dom,$confname,$settings,$rowtotal) = @_;
10525: if ($position eq 'top') {
10526: return &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
10527: } else {
10528: return &print_scantronconfig($dom,$settings,\$rowtotal);
10529: }
10530: }
10531:
10532: sub scantron_javascript {
10533: return <<"ENDSCRIPT";
10534:
10535: <script type="text/javascript">
10536: // <![CDATA[
10537:
10538: function toggleScantron(form) {
1.347 raeburn 10539: var csvfieldset = new Array();
1.346 raeburn 10540: if (document.getElementById('scantroncsv_cols')) {
1.347 raeburn 10541: csvfieldset.push(document.getElementById('scantroncsv_cols'));
10542: }
10543: if (document.getElementById('scantroncsv_options')) {
10544: csvfieldset.push(document.getElementById('scantroncsv_options'));
10545: }
10546: if (csvfieldset.length) {
1.346 raeburn 10547: if (document.getElementById('scantronconfcsv')) {
1.347 raeburn 10548: var scantroncsv = document.getElementById('scantronconfcsv');
1.346 raeburn 10549: if (scantroncsv.checked) {
1.347 raeburn 10550: for (var i=0; i<csvfieldset.length; i++) {
10551: csvfieldset[i].style.display = 'block';
10552: }
1.346 raeburn 10553: } else {
1.347 raeburn 10554: for (var i=0; i<csvfieldset.length; i++) {
10555: csvfieldset[i].style.display = 'none';
10556: }
1.346 raeburn 10557: var csvselects = document.getElementsByClassName('scantronconfig_csv');
10558: if (csvselects.length) {
10559: for (var j=0; j<csvselects.length; j++) {
10560: csvselects[j].selectedIndex = 0;
10561: }
10562: }
10563: }
10564: }
10565: }
10566: return;
10567: }
10568: // ]]>
10569: </script>
10570:
10571: ENDSCRIPT
10572:
10573: }
10574:
1.46 raeburn 10575: sub print_scantronformat {
10576: my ($r,$dom,$confname,$settings,$rowtotal) = @_;
10577: my $itemcount = 1;
1.60 raeburn 10578: my ($datatable,$css_class,$scantronurl,$is_custom,%error,%scantronurls,
10579: %confhash);
1.46 raeburn 10580: my $switchserver = &check_switchserver($dom,$confname);
10581: my %lt = &Apache::lonlocal::texthash (
1.95 www 10582: default => 'Default bubblesheet format file error',
10583: custom => 'Custom bubblesheet format file error',
1.46 raeburn 10584: );
10585: my %scantronfiles = (
10586: default => 'default.tab',
10587: custom => 'custom.tab',
10588: );
10589: foreach my $key (keys(%scantronfiles)) {
10590: $scantronurls{$key} = '/res/'.$dom.'/'.$confname.'/scantron/'
10591: .$scantronfiles{$key};
10592: }
10593: my @defaultinfo = &Apache::lonnet::stat_file($scantronurls{'default'});
10594: if ((!@defaultinfo) || ($defaultinfo[0] eq 'no_such_dir')) {
10595: if (!$switchserver) {
10596: my $servadm = $r->dir_config('lonAdmEMail');
10597: my ($configuserok,$author_ok) = &config_check($dom,$confname,$servadm);
10598: if ($configuserok eq 'ok') {
10599: if ($author_ok eq 'ok') {
10600: my %legacyfile = (
1.346 raeburn 10601: default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',
10602: custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',
1.46 raeburn 10603: );
10604: my %md5chk;
10605: foreach my $type (keys(%legacyfile)) {
1.60 raeburn 10606: ($md5chk{$type}) = split(/ /,`md5sum $legacyfile{$type}`);
10607: chomp($md5chk{$type});
1.46 raeburn 10608: }
10609: if ($md5chk{'default'} ne $md5chk{'custom'}) {
10610: foreach my $type (keys(%legacyfile)) {
1.346 raeburn 10611: ($scantronurls{$type},my $error) =
1.46 raeburn 10612: &legacy_scantronformat($r,$dom,$confname,
10613: $type,$legacyfile{$type},
10614: $scantronurls{$type},
10615: $scantronfiles{$type});
1.60 raeburn 10616: if ($error ne '') {
10617: $error{$type} = $error;
10618: }
10619: }
10620: if (keys(%error) == 0) {
10621: $is_custom = 1;
1.346 raeburn 10622: $confhash{'scantron'}{'scantronformat'} =
1.60 raeburn 10623: $scantronurls{'custom'};
1.346 raeburn 10624: my $putresult =
1.60 raeburn 10625: &Apache::lonnet::put_dom('configuration',
10626: \%confhash,$dom);
10627: if ($putresult ne 'ok') {
1.346 raeburn 10628: $error{'custom'} =
1.60 raeburn 10629: '<span class="LC_error">'.
10630: &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
10631: }
1.46 raeburn 10632: }
10633: } else {
1.60 raeburn 10634: ($scantronurls{'default'},my $error) =
1.46 raeburn 10635: &legacy_scantronformat($r,$dom,$confname,
10636: 'default',$legacyfile{'default'},
10637: $scantronurls{'default'},
10638: $scantronfiles{'default'});
1.60 raeburn 10639: if ($error eq '') {
10640: $confhash{'scantron'}{'scantronformat'} = '';
10641: my $putresult =
10642: &Apache::lonnet::put_dom('configuration',
10643: \%confhash,$dom);
10644: if ($putresult ne 'ok') {
10645: $error{'default'} =
10646: '<span class="LC_error">'.
10647: &mt('An error occurred updating the domain configuration: [_1]',$putresult).'</span>';
10648: }
10649: } else {
10650: $error{'default'} = $error;
10651: }
1.46 raeburn 10652: }
10653: }
10654: }
10655: } else {
1.95 www 10656: $error{'default'} = &mt("Unable to copy default bubblesheet formatfile to domain's RES space: [_1]",$switchserver);
1.46 raeburn 10657: }
10658: }
10659: if (ref($settings) eq 'HASH') {
10660: if ($settings->{'scantronformat'} eq "/res/$dom/$confname/scantron/custom.tab") {
10661: my @info = &Apache::lonnet::stat_file($settings->{'scantronformat'});
10662: if ((!@info) || ($info[0] eq 'no_such_dir')) {
10663: $scantronurl = '';
10664: } else {
10665: $scantronurl = $settings->{'scantronformat'};
10666: }
10667: $is_custom = 1;
10668: } else {
10669: $scantronurl = $scantronurls{'default'};
10670: }
10671: } else {
1.60 raeburn 10672: if ($is_custom) {
10673: $scantronurl = $scantronurls{'custom'};
10674: } else {
10675: $scantronurl = $scantronurls{'default'};
10676: }
1.46 raeburn 10677: }
10678: $css_class = $itemcount%2?' class="LC_odd_row"':'';
10679: $datatable .= '<tr'.$css_class.'>';
10680: if (!$is_custom) {
1.65 raeburn 10681: $datatable .= '<td>'.&mt('Default in use:').'<br />'.
10682: '<span class="LC_nobreak">';
1.46 raeburn 10683: if ($scantronurl) {
1.199 raeburn 10684: $datatable .= &Apache::loncommon::modal_link($scantronurl,&mt('Default bubblesheet format file'),600,500,
10685: undef,undef,undef,undef,'background-color:#ffffff');
1.46 raeburn 10686: } else {
10687: $datatable = &mt('File unavailable for display');
10688: }
1.65 raeburn 10689: $datatable .= '</span></td>';
1.60 raeburn 10690: if (keys(%error) == 0) {
1.306 raeburn 10691: $datatable .= '<td style="vertical-align: bottom">';
1.60 raeburn 10692: if (!$switchserver) {
10693: $datatable .= &mt('Upload:').'<br />';
10694: }
10695: } else {
10696: my $errorstr;
10697: foreach my $key (sort(keys(%error))) {
10698: $errorstr .= $lt{$key}.': '.$error{$key}.'<br />';
10699: }
10700: $datatable .= '<td>'.$errorstr;
10701: }
1.46 raeburn 10702: } else {
10703: if (keys(%error) > 0) {
10704: my $errorstr;
10705: foreach my $key (sort(keys(%error))) {
10706: $errorstr .= $lt{$key}.': '.$error{$key}.'<br />';
10707: }
1.60 raeburn 10708: $datatable .= '<td>'.$errorstr.'</td><td> ';
1.46 raeburn 10709: } elsif ($scantronurl) {
1.199 raeburn 10710: my $link = &Apache::loncommon::modal_link($scantronurl,&mt('Custom bubblesheet format file'),600,500,
10711: undef,undef,undef,undef,'background-color:#ffffff');
1.65 raeburn 10712: $datatable .= '<td><span class="LC_nobreak">'.
1.199 raeburn 10713: $link.
10714: '<label><input type="checkbox" name="scantronformat_del"'.
10715: ' value="1" />'.&mt('Delete?').'</label></span></td>'.
1.65 raeburn 10716: '<td><span class="LC_nobreak"> '.
10717: &mt('Replace:').'</span><br />';
1.46 raeburn 10718: }
10719: }
10720: if (keys(%error) == 0) {
10721: if ($switchserver) {
10722: $datatable .= &mt('Upload to library server: [_1]',$switchserver);
10723: } else {
1.65 raeburn 10724: $datatable .='<span class="LC_nobreak"> '.
10725: '<input type="file" name="scantronformat" /></span>';
1.46 raeburn 10726: }
10727: }
10728: $datatable .= '</td></tr>';
10729: $$rowtotal ++;
10730: return $datatable;
10731: }
10732:
10733: sub legacy_scantronformat {
10734: my ($r,$dom,$confname,$file,$legacyfile,$newurl,$newfile) = @_;
10735: my ($url,$error);
10736: my @statinfo = &Apache::lonnet::stat_file($newurl);
10737: if ((!@statinfo) || ($statinfo[0] eq 'no_such_dir')) {
1.421 raeburn 10738: my $modified = [];
1.46 raeburn 10739: (my $result,$url) =
1.421 raeburn 10740: &Apache::lonconfigsettings::publishlogo($r,'copy',$legacyfile,$dom,$confname,
10741: 'scantron','','',$newfile,$modified);
10742: if ($result eq 'ok') {
10743: &update_modify_urls($r,$modified);
10744: } else {
1.130 raeburn 10745: $error = &mt("An error occurred publishing the [_1] bubblesheet format file in RES space. Error was: [_2].",$newfile,$result);
1.46 raeburn 10746: }
10747: }
10748: return ($url,$error);
10749: }
1.43 raeburn 10750:
1.346 raeburn 10751: sub print_scantronconfig {
10752: my ($dom,$settings,$rowtotal) = @_;
10753: my $itemcount = 2;
10754: my $is_checked = ' checked="checked"';
1.347 raeburn 10755: my %optionson = (
10756: hdr => ' checked="checked"',
10757: pad => ' checked="checked"',
10758: rem => ' checked="checked"',
10759: );
10760: my %optionsoff = (
10761: hdr => '',
10762: pad => '',
10763: rem => '',
10764: );
1.346 raeburn 10765: my $currcsvsty = 'none';
1.347 raeburn 10766: my ($datatable,%csvfields,%checked,%onclick,%csvoptions);
1.346 raeburn 10767: my @fields = &scantroncsv_fields();
10768: my %titles = &scantronconfig_titles();
10769: if (ref($settings) eq 'HASH') {
10770: if (ref($settings->{config}) eq 'HASH') {
10771: if ($settings->{config}->{dat}) {
10772: $checked{'dat'} = $is_checked;
10773: }
10774: if (ref($settings->{config}->{csv}) eq 'HASH') {
1.347 raeburn 10775: if (ref($settings->{config}->{csv}->{fields}) eq 'HASH') {
10776: %csvfields = %{$settings->{config}->{csv}->{fields}};
10777: if (keys(%csvfields) > 0) {
10778: $checked{'csv'} = $is_checked;
10779: $currcsvsty = 'block';
10780: }
10781: }
10782: if (ref($settings->{config}->{csv}->{options}) eq 'HASH') {
10783: %csvoptions = %{$settings->{config}->{csv}->{options}};
10784: foreach my $option (keys(%optionson)) {
10785: unless ($csvoptions{$option}) {
10786: $optionsoff{$option} = $optionson{$option};
10787: $optionson{$option} = '';
10788: }
10789: }
1.346 raeburn 10790: }
10791: }
10792: } else {
10793: $checked{'dat'} = $is_checked;
10794: }
10795: } else {
10796: $checked{'dat'} = $is_checked;
10797: }
10798: $onclick{'csv'} = ' onclick="toggleScantron(this.form);"';
10799: my $css_class = $itemcount%2? ' class="LC_odd_row"':'';
10800: $datatable = '<tr '.$css_class.'><td>'.&mt('Supported formats').'</td>'.
10801: '<td class="LC_left_item" valign="top"><span class="LC_nobreak">';
10802: foreach my $item ('dat','csv') {
10803: my $id;
10804: if ($item eq 'csv') {
10805: $id = 'id="scantronconfcsv" ';
1.347 raeburn 10806: }
1.346 raeburn 10807: $datatable .= '<label><input type="checkbox" name="scantronconfig" '.$id.'value="'.$item.'"'.$checked{$item}.$onclick{$item}.' />'.
10808: $titles{$item}.'</label>'.(' 'x3);
10809: if ($item eq 'csv') {
10810: $datatable .= '<fieldset style="display:'.$currcsvsty.'" id="scantroncsv_cols">'.
10811: '<legend>'.&mt('CSV Column Mapping').'</legend>'.
10812: '<table><tr><th>'.&mt('Field').'</th><th>'.&mt('Location').'</th></tr>'."\n";
10813: foreach my $col (@fields) {
10814: my $selnone;
10815: if ($csvfields{$col} eq '') {
10816: $selnone = ' selected="selected"';
10817: }
10818: $datatable .= '<tr><td>'.$titles{$col}.'</td>'.
10819: '<td><select name="scantronconfig_csv_'.$col.'" class="scantronconfig_csv">'.
10820: '<option value=""'.$selnone.'></option>';
10821: for (my $i=0; $i<20; $i++) {
10822: my $shown = $i+1;
10823: my $sel;
10824: unless ($selnone) {
10825: if (exists($csvfields{$col})) {
10826: if ($csvfields{$col} == $i) {
10827: $sel = ' selected="selected"';
10828: }
10829: }
10830: }
10831: $datatable .= '<option value="'.$i.'"'.$sel.'>'.$shown.'</option>';
10832: }
10833: $datatable .= '</select></td></tr>';
10834: }
1.347 raeburn 10835: $datatable .= '</table></fieldset>'.
10836: '<fieldset style="display:'.$currcsvsty.'" id="scantroncsv_options">'.
10837: '<legend>'.&mt('CSV Options').'</legend>';
10838: foreach my $option ('hdr','pad','rem') {
10839: $datatable .= '<span class="LC_nobreak">'.$titles{$option}.':'.
10840: '<label><input type="radio" name="scantroncsv_'.$option.'" value="1"'.$optionson{$option}.' />'.
10841: &mt('Yes').'</label>'.(' 'x2)."\n".
10842: '<label><input type="radio" name="scantroncsv_'.$option.'" value="0"'.$optionsoff{$option}.' />'.&mt('No').'</label></span><br />';
10843: }
10844: $datatable .= '</fieldset>';
1.346 raeburn 10845: $itemcount ++;
10846: }
10847: }
10848: $datatable .= '</td></tr>';
10849: $$rowtotal ++;
10850: return $datatable;
10851: }
10852:
10853: sub scantronconfig_titles {
10854: return &Apache::lonlocal::texthash(
10855: dat => 'Standard format (.dat)',
10856: csv => 'Comma separated values (.csv)',
1.347 raeburn 10857: hdr => 'Remove first line in file (contains column titles)',
10858: pad => 'Prepend 0s to PaperID',
1.348 raeburn 10859: rem => 'Remove leading spaces (except Question Response columns)',
1.346 raeburn 10860: CODE => 'CODE',
10861: ID => 'Student ID',
10862: PaperID => 'Paper ID',
10863: FirstName => 'First Name',
10864: LastName => 'Last Name',
10865: FirstQuestion => 'First Question Response',
10866: Section => 'Section',
10867: );
10868: }
10869:
10870: sub scantroncsv_fields {
10871: return ('PaperID','LastName','FirstName','ID','Section','CODE','FirstQuestion');
10872: }
10873:
1.49 raeburn 10874: sub print_coursecategories {
1.57 raeburn 10875: my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
10876: my $datatable;
10877: if ($position eq 'top') {
1.238 raeburn 10878: my (%checked);
10879: my @catitems = ('unauth','auth');
10880: my @cattypes = ('std','domonly','codesrch','none');
10881: $checked{'unauth'} = 'std';
10882: $checked{'auth'} = 'std';
10883: if (ref($settings) eq 'HASH') {
10884: foreach my $type (@cattypes) {
10885: if ($type eq $settings->{'unauth'}) {
10886: $checked{'unauth'} = $type;
10887: }
10888: if ($type eq $settings->{'auth'}) {
10889: $checked{'auth'} = $type;
10890: }
10891: }
10892: }
10893: my %lt = &Apache::lonlocal::texthash (
10894: unauth => 'Catalog type for unauthenticated users',
10895: auth => 'Catalog type for authenticated users',
10896: none => 'No catalog',
10897: std => 'Standard catalog',
10898: domonly => 'Domain-only catalog',
10899: codesrch => "Code search form",
10900: );
10901: my $itemcount = 0;
10902: foreach my $item (@catitems) {
10903: my $css_class = $itemcount%2? ' class="LC_odd_row"':'';
10904: $datatable .= '<tr '.$css_class.'>'.
10905: '<td>'.$lt{$item}.'</td>'.
10906: '<td class="LC_right_item"><span class="LC_nobreak">';
10907: foreach my $type (@cattypes) {
10908: my $ischecked;
10909: if ($checked{$item} eq $type) {
10910: $ischecked=' checked="checked"';
10911: }
10912: $datatable .= '<label>'.
10913: '<input type="radio" name="coursecat_'.$item.'" value="'.$type.'"'.$ischecked.
10914: ' />'.$lt{$type}.'</label> ';
10915: }
1.327 raeburn 10916: $datatable .= '</span></td></tr>';
1.238 raeburn 10917: $itemcount ++;
10918: }
10919: $$rowtotal += $itemcount;
10920: } elsif ($position eq 'middle') {
1.57 raeburn 10921: my $toggle_cats_crs = ' ';
10922: my $toggle_cats_dom = ' checked="checked" ';
10923: my $can_cat_crs = ' ';
10924: my $can_cat_dom = ' checked="checked" ';
1.120 raeburn 10925: my $toggle_catscomm_comm = ' ';
10926: my $toggle_catscomm_dom = ' checked="checked" ';
10927: my $can_catcomm_comm = ' ';
10928: my $can_catcomm_dom = ' checked="checked" ';
1.272 raeburn 10929: my $toggle_catsplace_place = ' ';
10930: my $toggle_catsplace_dom = ' checked="checked" ';
10931: my $can_catplace_place = ' ';
10932: my $can_catplace_dom = ' checked="checked" ';
1.120 raeburn 10933:
1.57 raeburn 10934: if (ref($settings) eq 'HASH') {
10935: if ($settings->{'togglecats'} eq 'crs') {
10936: $toggle_cats_crs = $toggle_cats_dom;
10937: $toggle_cats_dom = ' ';
10938: }
10939: if ($settings->{'categorize'} eq 'crs') {
10940: $can_cat_crs = $can_cat_dom;
10941: $can_cat_dom = ' ';
10942: }
1.120 raeburn 10943: if ($settings->{'togglecatscomm'} eq 'comm') {
10944: $toggle_catscomm_comm = $toggle_catscomm_dom;
10945: $toggle_catscomm_dom = ' ';
10946: }
10947: if ($settings->{'categorizecomm'} eq 'comm') {
10948: $can_catcomm_comm = $can_catcomm_dom;
10949: $can_catcomm_dom = ' ';
10950: }
1.272 raeburn 10951: if ($settings->{'togglecatsplace'} eq 'place') {
10952: $toggle_catsplace_place = $toggle_catsplace_dom;
10953: $toggle_catsplace_dom = ' ';
10954: }
10955: if ($settings->{'categorizeplace'} eq 'place') {
10956: $can_catplace_place = $can_catplace_dom;
10957: $can_catplace_dom = ' ';
10958: }
1.57 raeburn 10959: }
10960: my %title = &Apache::lonlocal::texthash (
1.272 raeburn 10961: togglecats => 'Show/Hide a course in catalog',
10962: togglecatscomm => 'Show/Hide a community in catalog',
10963: togglecatsplace => 'Show/Hide a placement test in catalog',
10964: categorize => 'Assign a category to a course',
10965: categorizecomm => 'Assign a category to a community',
10966: categorizeplace => 'Assign a category to a placement test',
1.57 raeburn 10967: );
10968: my %level = &Apache::lonlocal::texthash (
1.272 raeburn 10969: dom => 'Set in Domain',
10970: crs => 'Set in Course',
10971: comm => 'Set in Community',
10972: place => 'Set in Placement Test',
1.57 raeburn 10973: );
10974: $datatable = '<tr class="LC_odd_row">'.
10975: '<td>'.$title{'togglecats'}.'</td>'.
10976: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
10977: '<input type="radio" name="togglecats"'.
10978: $toggle_cats_dom.' value="dom" />'.$level{'dom'}.'</label> '.
10979: '<label><input type="radio" name="togglecats"'.
10980: $toggle_cats_crs.' value="crs" />'.$level{'crs'}.'</label></span></td>'.
10981: '</tr><tr>'.
10982: '<td>'.$title{'categorize'}.'</td>'.
10983: '<td class="LC_right_item"><span class="LC_nobreak">'.
10984: '<label><input type="radio" name="categorize"'.
10985: $can_cat_dom.' value="dom" />'.$level{'dom'}.'</label> '.
10986: '<label><input type="radio" name="categorize"'.
10987: $can_cat_crs.'value="crs" />'.$level{'crs'}.'</label></span></td>'.
1.120 raeburn 10988: '</tr><tr class="LC_odd_row">'.
10989: '<td>'.$title{'togglecatscomm'}.'</td>'.
10990: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
10991: '<input type="radio" name="togglecatscomm"'.
10992: $toggle_catscomm_dom.' value="dom" />'.$level{'dom'}.'</label> '.
10993: '<label><input type="radio" name="togglecatscomm"'.
10994: $toggle_catscomm_comm.' value="comm" />'.$level{'comm'}.'</label></span></td>'.
10995: '</tr><tr>'.
10996: '<td>'.$title{'categorizecomm'}.'</td>'.
10997: '<td class="LC_right_item"><span class="LC_nobreak">'.
10998: '<label><input type="radio" name="categorizecomm"'.
10999: $can_catcomm_dom.' value="dom" />'.$level{'dom'}.'</label> '.
11000: '<label><input type="radio" name="categorizecomm"'.
11001: $can_catcomm_comm.'value="comm" />'.$level{'comm'}.'</label></span></td>'.
1.327 raeburn 11002: '</tr><tr class="LC_odd_row">'.
1.272 raeburn 11003: '<td>'.$title{'togglecatsplace'}.'</td>'.
11004: '<td class="LC_right_item"><span class="LC_nobreak"><label>'.
11005: '<input type="radio" name="togglecatsplace"'.
11006: $toggle_catsplace_dom.' value="dom" />'.$level{'dom'}.'</label> '.
11007: '<label><input type="radio" name="togglecatscomm"'.
11008: $toggle_catsplace_place.' value="comm" />'.$level{'place'}.'</label></span></td>'.
11009: '</tr><tr>'.
11010: '<td>'.$title{'categorizeplace'}.'</td>'.
11011: '<td class="LC_right_item"><span class="LC_nobreak">'.
11012: '<label><input type="radio" name="categorizeplace"'.
11013: $can_catplace_dom.' value="dom" />'.$level{'dom'}.'</label> '.
11014: '<label><input type="radio" name="categorizeplace"'.
11015: $can_catplace_place.'value="place" />'.$level{'place'}.'</label></span></td>'.
1.57 raeburn 11016: '</tr>';
1.272 raeburn 11017: $$rowtotal += 6;
1.57 raeburn 11018: } else {
11019: my $css_class;
11020: my $itemcount = 1;
11021: my $cathash;
11022: if (ref($settings) eq 'HASH') {
11023: $cathash = $settings->{'cats'};
11024: }
11025: if (ref($cathash) eq 'HASH') {
11026: my (@cats,@trails,%allitems,%idx,@jsarray);
11027: &Apache::loncommon::extract_categories($cathash,\@cats,\@trails,
11028: \%allitems,\%idx,\@jsarray);
11029: my $maxdepth = scalar(@cats);
11030: my $colattrib = '';
11031: if ($maxdepth > 2) {
11032: $colattrib = ' colspan="2" ';
11033: }
11034: my @path;
11035: if (@cats > 0) {
11036: if (ref($cats[0]) eq 'ARRAY') {
11037: my $numtop = @{$cats[0]};
11038: my $maxnum = $numtop;
1.120 raeburn 11039: my %default_names = (
11040: instcode => &mt('Official courses'),
11041: communities => &mt('Communities'),
1.272 raeburn 11042: placement => &mt('Placement Tests'),
1.120 raeburn 11043: );
11044:
11045: if ((!grep(/^instcode$/,@{$cats[0]})) ||
11046: ($cathash->{'instcode::0'} eq '') ||
11047: (!grep(/^communities$/,@{$cats[0]})) ||
1.272 raeburn 11048: ($cathash->{'communities::0'} eq '') ||
11049: (!grep(/^placement$/,@{$cats[0]})) ||
11050: ($cathash->{'placement::0'} eq '')) {
1.57 raeburn 11051: $maxnum ++;
11052: }
11053: my $lastidx;
11054: for (my $i=0; $i<$numtop; $i++) {
11055: my $parent = $cats[0][$i];
11056: $css_class = $itemcount%2?' class="LC_odd_row"':'';
11057: my $item = &escape($parent).'::0';
11058: my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$item','$idx{$item}'".');"';
11059: $lastidx = $idx{$item};
11060: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
11061: .'<select name="'.$item.'"'.$chgstr.'>';
11062: for (my $k=0; $k<=$maxnum; $k++) {
11063: my $vpos = $k+1;
11064: my $selstr;
11065: if ($k == $i) {
11066: $selstr = ' selected="selected" ';
11067: }
11068: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
11069: }
1.214 raeburn 11070: $datatable .= '</select></span></td><td>';
1.272 raeburn 11071: if ($parent eq 'instcode' || $parent eq 'communities' || $parent eq 'placement') {
1.120 raeburn 11072: $datatable .= '<span class="LC_nobreak">'
11073: .$default_names{$parent}.'</span>';
11074: if ($parent eq 'instcode') {
11075: $datatable .= '<br /><span class="LC_nobreak">('
11076: .&mt('with institutional codes')
11077: .')</span></td><td'.$colattrib.'>';
11078: } else {
11079: $datatable .= '<table><tr><td>';
11080: }
11081: $datatable .= '<span class="LC_nobreak">'
11082: .'<label><input type="radio" name="'
11083: .$parent.'" value="1" checked="checked" />'
11084: .&mt('Display').'</label>';
11085: if ($parent eq 'instcode') {
11086: $datatable .= ' ';
11087: } else {
11088: $datatable .= '</span></td></tr><tr><td>'
11089: .'<span class="LC_nobreak">';
11090: }
11091: $datatable .= '<label><input type="radio" name="'
11092: .$parent.'" value="0" />'
11093: .&mt('Do not display').'</label></span>';
1.272 raeburn 11094: if (($parent eq 'communities') || ($parent eq 'placement')) {
1.120 raeburn 11095: $datatable .= '</td></tr></table>';
11096: }
11097: $datatable .= '</td>';
1.57 raeburn 11098: } else {
11099: $datatable .= $parent
1.214 raeburn 11100: .' <span class="LC_nobreak"><label>'
11101: .'<input type="checkbox" name="deletecategory" '
1.57 raeburn 11102: .'value="'.$item.'" />'.&mt('Delete').'</label></span></td>';
11103: }
11104: my $depth = 1;
11105: push(@path,$parent);
11106: $datatable .= &build_category_rows($itemcount,\@cats,$depth,$parent,\@path,\%idx);
11107: pop(@path);
11108: $datatable .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';
11109: $itemcount ++;
11110: }
1.48 raeburn 11111: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.57 raeburn 11112: my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','$lastidx'".');"';
11113: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak"><select name="addcategory_pos"'.$chgstr.'>';
1.48 raeburn 11114: for (my $k=0; $k<=$maxnum; $k++) {
11115: my $vpos = $k+1;
11116: my $selstr;
1.57 raeburn 11117: if ($k == $numtop) {
1.48 raeburn 11118: $selstr = ' selected="selected" ';
11119: }
11120: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
11121: }
1.59 bisitz 11122: $datatable .= '</select></span></td><td colspan="2">'.&mt('Add category:').' '
1.57 raeburn 11123: .'<input type="text" size="20" name="addcategory_name" value="" /></td>'
11124: .'</tr>'."\n";
1.48 raeburn 11125: $itemcount ++;
1.272 raeburn 11126: foreach my $default ('instcode','communities','placement') {
1.120 raeburn 11127: if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {
11128: $css_class = $itemcount%2?' class="LC_odd_row"':'';
11129: my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';
11130: $datatable .= '<tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr><tr '.$css_class.'><td>'.
11131: '<span class="LC_nobreak"><select name="'.$default.'_pos"'.$chgstr.'>';
11132: for (my $k=0; $k<=$maxnum; $k++) {
11133: my $vpos = $k+1;
11134: my $selstr;
11135: if ($k == $maxnum) {
11136: $selstr = ' selected="selected" ';
11137: }
11138: $datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>';
1.57 raeburn 11139: }
1.120 raeburn 11140: $datatable .= '</select></span></td>'.
11141: '<td><span class="LC_nobreak">'.
11142: $default_names{$default}.'</span>';
11143: if ($default eq 'instcode') {
11144: $datatable .= '<br /><span class="LC_nobreak">('
11145: .&mt('with institutional codes').')</span>';
11146: }
11147: $datatable .= '</td>'
11148: .'<td><span class="LC_nobreak"><label><input type="radio" name="'.$default.'" value="1" />'
11149: .&mt('Display').'</label> '
11150: .'<label><input type="radio" name="'.$default.'" value="0" checked="checked"/>'
11151: .&mt('Do not display').'</label></span></td></tr>';
1.48 raeburn 11152: }
11153: }
11154: }
1.57 raeburn 11155: } else {
11156: $datatable .= &initialize_categories($itemcount);
1.48 raeburn 11157: }
11158: } else {
1.327 raeburn 11159: $datatable .= '<tr><td class="LC_right_item">'.$hdritem->{'header'}->[1]->{'col2'}.'</td></tr>'
1.57 raeburn 11160: .&initialize_categories($itemcount);
1.48 raeburn 11161: }
1.57 raeburn 11162: $$rowtotal += $itemcount;
1.48 raeburn 11163: }
11164: return $datatable;
11165: }
11166:
1.69 raeburn 11167: sub print_serverstatuses {
11168: my ($dom,$settings,$rowtotal) = @_;
11169: my $datatable;
11170: my @pages = &serverstatus_pages();
11171: my (%namedaccess,%machineaccess);
11172: foreach my $type (@pages) {
11173: $namedaccess{$type} = '';
11174: $machineaccess{$type}= '';
11175: }
11176: if (ref($settings) eq 'HASH') {
11177: foreach my $type (@pages) {
11178: if (exists($settings->{$type})) {
11179: if (ref($settings->{$type}) eq 'HASH') {
11180: foreach my $key (keys(%{$settings->{$type}})) {
11181: if ($key eq 'namedusers') {
11182: $namedaccess{$type} = $settings->{$type}->{$key};
11183: } elsif ($key eq 'machines') {
11184: $machineaccess{$type} = $settings->{$type}->{$key};
11185: }
11186: }
11187: }
11188: }
11189: }
11190: }
1.81 raeburn 11191: my $titles= &LONCAPA::lonauthcgi::serverstatus_titles();
1.69 raeburn 11192: my $rownum = 0;
11193: my $css_class;
11194: foreach my $type (@pages) {
11195: $rownum ++;
11196: $css_class = $rownum%2?' class="LC_odd_row"':'';
11197: $datatable .= '<tr'.$css_class.'>'.
11198: '<td><span class="LC_nobreak">'.
11199: $titles->{$type}.'</span></td>'.
11200: '<td class="LC_left_item">'.
11201: '<input type="text" name="'.$type.'_namedusers" '.
11202: 'value="'.$namedaccess{$type}.'" size="30" /></td>'.
11203: '<td class="LC_right_item">'.
11204: '<span class="LC_nobreak">'.
11205: '<input type="text" name="'.$type.'_machines" '.
11206: 'value="'.$machineaccess{$type}.'" size="10" />'.
1.334 raeburn 11207: '</span></td></tr>'."\n";
1.69 raeburn 11208: }
11209: $$rowtotal += $rownum;
11210: return $datatable;
11211: }
11212:
11213: sub serverstatus_pages {
11214: return ('userstatus','lonstatus','loncron','server-status','codeversions',
1.275 raeburn 11215: 'checksums','clusterstatus','certstatus','metadata_keywords',
11216: 'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
11217: 'ping','domconf','uniquecodes','diskusage','coursecatalog');
1.69 raeburn 11218: }
11219:
1.236 raeburn 11220: sub defaults_javascript {
11221: my ($settings) = @_;
1.354 raeburn 11222: return unless (ref($settings) eq 'HASH');
1.414 raeburn 11223: my $portal_js = <<"ENDPORTAL";
11224:
11225: function portalExtras(caller) {
11226: var x = caller.value;
11227: var y = new Array('email','web');
1.425 raeburn 11228: for (var i=0; i<y.length; i++) {
1.414 raeburn 11229: if (document.getElementById('portal_def_'+y[i]+'_div')) {
11230: var z = document.getElementById('portal_def_'+y[i]+'_div');
11231: if (x.length > 0) {
11232: z.style.display = 'block';
11233: } else {
11234: z.style.display = 'none';
11235: }
11236: }
11237: }
11238: }
11239: ENDPORTAL
1.236 raeburn 11240: if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
11241: my $maxnum = scalar(@{$settings->{'inststatusorder'}});
11242: if ($maxnum eq '') {
11243: $maxnum = 0;
11244: }
11245: $maxnum ++;
1.249 raeburn 11246: my $jstext = ' var inststatuses = Array('."'".join("','",@{$settings->{'inststatusorder'}})."'".');';
1.236 raeburn 11247: return <<"ENDSCRIPT";
11248: <script type="text/javascript">
11249: // <![CDATA[
11250: function reorderTypes(form,caller) {
11251: var changedVal;
11252: $jstext
11253: var newpos = 'addinststatus_pos';
11254: var current = new Array;
11255: var maxh = $maxnum;
11256: var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
11257: var oldVal;
11258: if (caller == newpos) {
11259: changedVal = newitemVal;
11260: } else {
11261: var curritem = 'inststatus_pos_'+caller;
11262: changedVal = form.elements[curritem].options[form.elements[curritem].selectedIndex].value;
11263: current[newitemVal] = newpos;
11264: }
11265: for (var i=0; i<inststatuses.length; i++) {
11266: if (inststatuses[i] != caller) {
11267: var elementName = 'inststatus_pos_'+inststatuses[i];
11268: if (form.elements[elementName]) {
11269: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
11270: current[currVal] = elementName;
11271: }
11272: }
11273: }
11274: for (var j=0; j<maxh; j++) {
11275: if (current[j] == undefined) {
11276: oldVal = j;
11277: }
11278: }
11279: if (oldVal < changedVal) {
11280: for (var k=oldVal+1; k<=changedVal ; k++) {
11281: var elementName = current[k];
11282: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
11283: }
11284: } else {
11285: for (var k=changedVal; k<oldVal; k++) {
11286: var elementName = current[k];
11287: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
11288: }
11289: }
11290: return;
11291: }
11292:
1.414 raeburn 11293: $portal_js
11294:
11295: // ]]>
11296: </script>
11297:
11298: ENDSCRIPT
11299: } else {
11300: return <<"ENDSCRIPT";
11301: <script type="text/javascript">
11302: // <![CDATA[
11303: $portal_js
1.236 raeburn 11304: // ]]>
11305: </script>
11306:
11307: ENDSCRIPT
11308: }
1.354 raeburn 11309: return;
11310: }
11311:
11312: sub passwords_javascript {
1.405 raeburn 11313: my ($prefix) = @_;
11314: my %intalert;
11315: if ($prefix eq 'passwords') {
11316: %intalert = &Apache::lonlocal::texthash (
11317: authcheck => 'Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.',
11318: authcost => 'Warning: bcrypt encryption cost for internal authentication must be an integer.',
11319: passmin => 'Warning: minimum password length must be a positive integer greater than 6.',
11320: passmax => 'Warning: maximum password length must be a positive integer (or blank).',
11321: passexp => 'Warning: days before password expiration must be a positive integer (or blank).',
11322: passnum => 'Warning: number of previous passwords to save must be a positive integer (or blank).',
11323: );
1.421 raeburn 11324: } elsif (($prefix eq 'ltisecrets') || ($prefix eq 'toolsecrets')) {
1.405 raeburn 11325: %intalert = &Apache::lonlocal::texthash (
11326: passmin => 'Warning: minimum secret length must be a positive integer greater than 6.',
11327: passmax => 'Warning: maximum secret length must be a positive integer (or blank).',
11328: );
11329: }
1.365 raeburn 11330: &js_escape(\%intalert);
11331: my $defmin = $Apache::lonnet::passwdmin;
1.425 raeburn 11332: my $intauthjs;
1.405 raeburn 11333: if ($prefix eq 'passwords') { $intauthjs = <<"ENDSCRIPT";
1.354 raeburn 11334:
11335: function warnIntAuth(field) {
11336: if (field.name == 'intauth_check') {
11337: if (field.value == '2') {
1.365 raeburn 11338: alert('$intalert{authcheck}');
1.354 raeburn 11339: }
11340: }
11341: if (field.name == 'intauth_cost') {
11342: field.value.replace(/\s/g,'');
11343: if (field.value != '') {
11344: var regexdigit=/^\\d+\$/;
11345: if (!regexdigit.test(field.value)) {
1.365 raeburn 11346: alert('$intalert{authcost}');
11347: }
11348: }
11349: }
11350: return;
11351: }
11352:
1.405 raeburn 11353: ENDSCRIPT
11354:
11355: }
11356:
11357: $intauthjs .= <<"ENDSCRIPT";
11358:
11359: function warnInt$prefix(field) {
1.365 raeburn 11360: field.value.replace(/^\s+/,'');
11361: field.value.replace(/\s+\$/,'');
11362: var regexdigit=/^\\d+\$/;
1.408 raeburn 11363: if (field.name == '${prefix}_min') {
1.365 raeburn 11364: if (field.value == '') {
11365: alert('$intalert{passmin}');
11366: field.value = '$defmin';
11367: } else {
11368: if (!regexdigit.test(field.value)) {
11369: alert('$intalert{passmin}');
11370: field.value = '$defmin';
11371: }
1.366 raeburn 11372: var minval = parseInt(field.value,10);
1.365 raeburn 11373: if (minval < $defmin) {
11374: alert('$intalert{passmin}');
11375: field.value = '$defmin';
11376: }
11377: }
11378: } else {
11379: if (field.value == '0') {
11380: field.value = '';
11381: }
11382: if (field.value != '') {
1.408 raeburn 11383: if (field.name == '${prefix}_expire') {
1.365 raeburn 11384: var regexpposnum=/^\\d+(|\\.\\d*)\$/;
11385: if (!regexpposnum.test(field.value)) {
11386: alert('$intalert{passexp}');
11387: field.value = '';
11388: } else {
11389: var expval = parseFloat(field.value);
11390: if (expval == 0) {
11391: alert('$intalert{passexp}');
11392: field.value = '';
11393: }
11394: }
11395: } else {
11396: if (!regexdigit.test(field.value)) {
1.408 raeburn 11397: if (field.name == '${prefix}_max') {
1.365 raeburn 11398: alert('$intalert{passmax}');
11399: } else {
1.408 raeburn 11400: if (field.name == '${prefix}_numsaved') {
1.365 raeburn 11401: alert('$intalert{passnum}');
11402: }
11403: }
1.370 raeburn 11404: field.value = '';
1.365 raeburn 11405: }
1.354 raeburn 11406: }
11407: }
11408: }
11409: return;
11410: }
11411:
11412: ENDSCRIPT
11413: return &Apache::lonhtmlcommon::scripttag($intauthjs);
1.236 raeburn 11414: }
11415:
1.49 raeburn 11416: sub coursecategories_javascript {
11417: my ($settings) = @_;
1.57 raeburn 11418: my ($output,$jstext,$cathash);
1.49 raeburn 11419: if (ref($settings) eq 'HASH') {
1.57 raeburn 11420: $cathash = $settings->{'cats'};
11421: }
11422: if (ref($cathash) eq 'HASH') {
1.49 raeburn 11423: my (@cats,@jsarray,%idx);
1.57 raeburn 11424: &Apache::loncommon::gather_categories($cathash,\@cats,\%idx,\@jsarray);
1.49 raeburn 11425: if (@jsarray > 0) {
11426: $jstext = ' var categories = Array('.scalar(@jsarray).');'."\n";
11427: for (my $i=0; $i<@jsarray; $i++) {
11428: if (ref($jsarray[$i]) eq 'ARRAY') {
11429: my $catstr = join('","',@{$jsarray[$i]});
11430: $jstext .= ' categories['.$i.'] = Array("'.$catstr.'");'."\n";
11431: }
11432: }
11433: }
11434: } else {
11435: $jstext = ' var categories = Array(1);'."\n".
11436: ' categories[0] = Array("instcode_pos");'."\n";
11437: }
1.237 bisitz 11438: my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
11439: my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
1.272 raeburn 11440: my $placement_reserved = &mt('The name: [_1] is a reserved category.','"placement"');
1.265 damieng 11441: my $choose_again = "\n".&mt('Please use a different name for the new top level category.');
11442: &js_escape(\$instcode_reserved);
11443: &js_escape(\$communities_reserved);
1.272 raeburn 11444: &js_escape(\$placement_reserved);
1.265 damieng 11445: &js_escape(\$choose_again);
1.49 raeburn 11446: $output = <<"ENDSCRIPT";
11447: <script type="text/javascript">
1.109 raeburn 11448: // <![CDATA[
1.49 raeburn 11449: function reorderCats(form,parent,item,idx) {
11450: var changedVal;
11451: $jstext
11452: var newpos = 'addcategory_pos';
11453: if (parent == '') {
11454: var has_instcode = 0;
11455: var maxtop = categories[idx].length;
11456: for (var j=0; j<maxtop; j++) {
11457: if (categories[idx][j] == 'instcode::0') {
11458: has_instcode == 1;
11459: }
11460: }
11461: if (has_instcode == 0) {
11462: categories[idx][maxtop] = 'instcode_pos';
11463: }
11464: } else {
11465: newpos += '_'+parent;
11466: }
11467: var maxh = 1 + categories[idx].length;
11468: var current = new Array;
11469: var newitemVal = form.elements[newpos].options[form.elements[newpos].selectedIndex].value;
11470: if (item == newpos) {
11471: changedVal = newitemVal;
11472: } else {
11473: changedVal = form.elements[item].options[form.elements[item].selectedIndex].value;
11474: current[newitemVal] = newpos;
11475: }
11476: for (var i=0; i<categories[idx].length; i++) {
11477: var elementName = categories[idx][i];
11478: if (elementName != item) {
11479: if (form.elements[elementName]) {
11480: var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value;
11481: current[currVal] = elementName;
11482: }
11483: }
11484: }
11485: var oldVal;
11486: for (var j=0; j<maxh; j++) {
11487: if (current[j] == undefined) {
11488: oldVal = j;
11489: }
11490: }
11491: if (oldVal < changedVal) {
11492: for (var k=oldVal+1; k<=changedVal ; k++) {
11493: var elementName = current[k];
11494: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1;
11495: }
11496: } else {
11497: for (var k=changedVal; k<oldVal; k++) {
11498: var elementName = current[k];
11499: form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1;
11500: }
11501: }
11502: return;
11503: }
1.120 raeburn 11504:
11505: function categoryCheck(form) {
11506: if (form.elements['addcategory_name'].value == 'instcode') {
11507: alert('$instcode_reserved\\n$choose_again');
11508: return false;
11509: }
11510: if (form.elements['addcategory_name'].value == 'communities') {
11511: alert('$communities_reserved\\n$choose_again');
11512: return false;
11513: }
1.272 raeburn 11514: if (form.elements['addcategory_name'].value == 'placement') {
11515: alert('$placement_reserved\\n$choose_again');
11516: return false;
11517: }
1.120 raeburn 11518: return true;
11519: }
11520:
1.109 raeburn 11521: // ]]>
1.49 raeburn 11522: </script>
11523:
11524: ENDSCRIPT
11525: return $output;
11526: }
11527:
1.48 raeburn 11528: sub initialize_categories {
11529: my ($itemcount) = @_;
1.120 raeburn 11530: my ($datatable,$css_class,$chgstr);
1.380 raeburn 11531: my %default_names = &Apache::lonlocal::texthash (
1.120 raeburn 11532: instcode => 'Official courses (with institutional codes)',
11533: communities => 'Communities',
1.272 raeburn 11534: placement => 'Placement Tests',
1.120 raeburn 11535: );
1.328 raeburn 11536: my %selnum = (
11537: instcode => '0',
11538: communities => '1',
11539: placement => '2',
11540: );
11541: my %selected;
1.272 raeburn 11542: foreach my $default ('instcode','communities','placement') {
1.120 raeburn 11543: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.327 raeburn 11544: $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','0'".');"';
1.328 raeburn 11545: map { $selected{$selnum{$_}} = '' } keys(%selnum);
11546: $selected{$selnum{$default}} = ' selected="selected"';
1.120 raeburn 11547: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
1.328 raeburn 11548: .'<select name="'.$default.'_pos"'.$chgstr.'>'
11549: .'<option value="0"'.$selected{'0'}.'>1</option>'
11550: .'<option value="1"'.$selected{'1'}.'>2</option>'
11551: .'<option value="2"'.$selected{'2'}.'>3</option>'
11552: .'<option value="3">4</option></select> '
1.120 raeburn 11553: .$default_names{$default}
11554: .'</span></td><td><span class="LC_nobreak">'
11555: .'<label><input type="radio" name="'.$default.'" value="1" checked="checked" />'
11556: .&mt('Display').'</label> <label>'
11557: .'<input type="radio" name="'.$default.'" value="0" />'.&mt('Do not display')
1.48 raeburn 11558: .'</label></span></td></tr>';
1.120 raeburn 11559: $itemcount ++;
11560: }
1.48 raeburn 11561: $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.49 raeburn 11562: $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','0'".');"';
1.48 raeburn 11563: $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'
1.120 raeburn 11564: .'<select name="addcategory_pos"'.$chgstr.'>'
11565: .'<option value="0">1</option>'
11566: .'<option value="1">2</option>'
1.328 raeburn 11567: .'<option value="2">3</option>'
11568: .'<option value="3" selected="selected">4</option></select> '
1.327 raeburn 11569: .&mt('Add category').'</span></td><td><span class="LC_nobreak">'.&mt('Name:')
11570: .' <input type="text" size="20" name="addcategory_name" value="" /></span>'
11571: .'</td></tr>';
1.48 raeburn 11572: return $datatable;
11573: }
11574:
11575: sub build_category_rows {
1.49 raeburn 11576: my ($itemcount,$cats,$depth,$parent,$path,$idx) = @_;
11577: my ($text,$name,$item,$chgstr);
1.48 raeburn 11578: if (ref($cats) eq 'ARRAY') {
11579: my $maxdepth = scalar(@{$cats});
11580: if (ref($cats->[$depth]) eq 'HASH') {
11581: if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
11582: my $numchildren = @{$cats->[$depth]{$parent}};
11583: my $css_class = $itemcount%2?' class="LC_odd_row"':'';
1.204 raeburn 11584: $text .= '<td><table class="LC_data_table">';
1.49 raeburn 11585: my ($idxnum,$parent_name,$parent_item);
11586: my $higher = $depth - 1;
11587: if ($higher == 0) {
11588: $parent_name = &escape($parent).'::'.$higher;
11589: } else {
11590: if (ref($path) eq 'ARRAY') {
11591: $parent_name = &escape($parent).':'.&escape($path->[-2]).':'.$higher;
11592: }
11593: }
11594: $parent_item = 'addcategory_pos_'.$parent_name;
1.48 raeburn 11595: for (my $j=0; $j<=$numchildren; $j++) {
1.49 raeburn 11596: if ($j < $numchildren) {
1.48 raeburn 11597: $name = $cats->[$depth]{$parent}[$j];
11598: $item = &escape($name).':'.&escape($parent).':'.$depth;
1.49 raeburn 11599: $idxnum = $idx->{$item};
11600: } else {
11601: $name = $parent_name;
11602: $item = $parent_item;
1.48 raeburn 11603: }
1.49 raeburn 11604: $chgstr = ' onchange="javascript:reorderCats(this.form,'."'$parent_name','$item','$idxnum'".');"';
11605: $text .= '<tr '.$css_class.'><td><span class="LC_nobreak"><select name="'.$item.'"'.$chgstr.'>';
1.48 raeburn 11606: for (my $i=0; $i<=$numchildren; $i++) {
11607: my $vpos = $i+1;
11608: my $selstr;
11609: if ($j == $i) {
11610: $selstr = ' selected="selected" ';
11611: }
11612: $text .= '<option value="'.$i.'"'.$selstr.'>'.$vpos.'</option>';
11613: }
11614: $text .= '</select> ';
11615: if ($j < $numchildren) {
11616: my $deeper = $depth+1;
11617: $text .= $name.' '
11618: .'<label><input type="checkbox" name="deletecategory" value="'
11619: .$item.'" />'.&mt('Delete').'</label></span></td><td>';
11620: if(ref($path) eq 'ARRAY') {
11621: push(@{$path},$name);
1.49 raeburn 11622: $text .= &build_category_rows($itemcount,$cats,$deeper,$name,$path,$idx);
1.48 raeburn 11623: pop(@{$path});
11624: }
11625: } else {
1.330 raeburn 11626: $text .= &mt('Add subcategory:').' </span><input type="text" size="20" name="addcategory_name_';
1.48 raeburn 11627: if ($j == $numchildren) {
11628: $text .= $name;
11629: } else {
11630: $text .= $item;
11631: }
11632: $text .= '" value="" />';
11633: }
11634: $text .= '</td></tr>';
11635: }
11636: $text .= '</table></td>';
11637: } else {
11638: my $higher = $depth-1;
11639: if ($higher == 0) {
11640: $name = &escape($parent).'::'.$higher;
11641: } else {
11642: if (ref($path) eq 'ARRAY') {
11643: $name = &escape($parent).':'.&escape($path->[-2]).':'.$higher;
11644: }
11645: }
11646: my $colspan;
11647: if ($parent ne 'instcode') {
11648: $colspan = $maxdepth - $depth - 1;
1.330 raeburn 11649: $text .= '<td colspan="'.$colspan.'">'.&mt('Add subcategory:').'<input type="text" size="20" name="subcat_'.$name.'" value="" /></td>';
1.48 raeburn 11650: }
11651: }
11652: }
11653: }
11654: return $text;
11655: }
11656:
1.33 raeburn 11657: sub modifiable_userdata_row {
1.305 raeburn 11658: my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref,
1.357 raeburn 11659: $rowid,$customcss,$rowstyle,$itemdesc) = @_;
1.228 raeburn 11660: my ($role,$rolename,$statustype);
11661: $role = $item;
1.224 raeburn 11662: if ($context eq 'cancreate') {
1.305 raeburn 11663: if ($item =~ /^(emailusername)_(.+)$/) {
11664: $role = $1;
11665: $statustype = $2;
1.228 raeburn 11666: if (ref($usertypes) eq 'HASH') {
11667: if ($usertypes->{$statustype}) {
11668: $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype});
11669: } else {
11670: $rolename = &mt('Data provided by user');
11671: }
11672: }
1.224 raeburn 11673: }
11674: } elsif ($context eq 'selfcreate') {
1.63 raeburn 11675: if (ref($usertypes) eq 'HASH') {
11676: $rolename = $usertypes->{$role};
11677: } else {
11678: $rolename = $role;
11679: }
1.325 raeburn 11680: } elsif ($context eq 'lti') {
11681: $rolename = &mt('Institutional data used (if available)');
1.357 raeburn 11682: } elsif ($context eq 'privacy') {
11683: $rolename = $itemdesc;
1.33 raeburn 11684: } else {
1.63 raeburn 11685: if ($role eq 'cr') {
11686: $rolename = &mt('Custom role');
11687: } else {
11688: $rolename = &Apache::lonnet::plaintext($role);
11689: }
1.33 raeburn 11690: }
1.224 raeburn 11691: my (@fields,%fieldtitles);
11692: if (ref($fieldsref) eq 'ARRAY') {
11693: @fields = @{$fieldsref};
11694: } else {
11695: @fields = ('lastname','firstname','middlename','generation',
11696: 'permanentemail','id');
11697: }
11698: if ((ref($titlesref) eq 'HASH')) {
11699: %fieldtitles = %{$titlesref};
11700: } else {
11701: %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
11702: }
1.33 raeburn 11703: my $output;
1.305 raeburn 11704: my $css_class;
11705: if ($rowcount%2) {
11706: $css_class = 'LC_odd_row';
11707: }
11708: if ($customcss) {
11709: $css_class .= " $customcss";
11710: }
11711: $css_class =~ s/^\s+//;
11712: if ($css_class) {
11713: $css_class = ' class="'.$css_class.'"';
11714: }
11715: if ($rowstyle) {
11716: $css_class .= ' style="'.$rowstyle.'"';
11717: }
11718: if ($rowid) {
11719: $rowid = ' id="'.$rowid.'"';
11720: }
11721: $output = '<tr '.$css_class.$rowid.'>'.
1.33 raeburn 11722: '<td><span class="LC_nobreak">'.$rolename.'</span></td>'.
11723: '<td class="LC_left_item" colspan="2"><table>';
11724: my $rem;
11725: my %checks;
11726: if (ref($settings) eq 'HASH') {
1.325 raeburn 11727: my $hashref;
11728: if ($context eq 'lti') {
11729: if (ref($settings) eq 'HASH') {
11730: $hashref = $settings->{'instdata'};
11731: }
1.357 raeburn 11732: } elsif ($context eq 'privacy') {
11733: my ($key,$inner) = split(/_/,$role);
11734: if (ref($settings) eq 'HASH') {
11735: if (ref($settings->{$key}) eq 'HASH') {
11736: $hashref = $settings->{$key}->{$inner};
11737: }
11738: }
1.325 raeburn 11739: } elsif (ref($settings->{$context}) eq 'HASH') {
1.33 raeburn 11740: if (ref($settings->{$context}->{$role}) eq 'HASH') {
1.325 raeburn 11741: $hashref = $settings->{'lti_instdata'};
11742: }
11743: if ($role eq 'emailusername') {
11744: if ($statustype) {
11745: if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
11746: $hashref = $settings->{$context}->{$role}->{$statustype};
1.228 raeburn 11747: }
1.325 raeburn 11748: }
11749: }
11750: }
1.425 raeburn 11751: if (ref($hashref) eq 'HASH') {
1.325 raeburn 11752: foreach my $field (@fields) {
11753: if ($hashref->{$field}) {
11754: if ($role eq 'emailusername') {
11755: $checks{$field} = $hashref->{$field};
11756: } else {
11757: $checks{$field} = ' checked="checked" ';
1.33 raeburn 11758: }
11759: }
11760: }
11761: }
11762: }
1.305 raeburn 11763: my $total = scalar(@fields);
11764: for (my $i=0; $i<$total; $i++) {
11765: $rem = $i%($numinrow);
1.33 raeburn 11766: if ($rem == 0) {
11767: if ($i > 0) {
11768: $output .= '</tr>';
11769: }
11770: $output .= '<tr>';
11771: }
11772: my $check = ' ';
1.228 raeburn 11773: unless ($role eq 'emailusername') {
11774: if (exists($checks{$fields[$i]})) {
1.354 raeburn 11775: $check = $checks{$fields[$i]};
1.357 raeburn 11776: } elsif ($context eq 'privacy') {
11777: if ($role =~ /^priv_(domain|course)$/) {
11778: if (ref($settings) ne 'HASH') {
11779: $check = ' checked="checked" ';
11780: }
11781: } elsif ($role =~ /^priv_(author|community)$/) {
11782: if (ref($settings) ne 'HASH') {
11783: unless ($fields[$i] eq 'id') {
11784: $check = ' checked="checked" ';
11785: }
11786: }
11787: } elsif ($role =~ /^(unpriv|othdom)_/) {
11788: if (ref($settings) ne 'HASH') {
11789: if (($fields[$i] eq 'lastname') || ($fields[$i] eq 'firstname')) {
11790: $check = ' checked="checked" ';
11791: }
11792: }
11793: }
1.325 raeburn 11794: } elsif ($context ne 'lti') {
1.228 raeburn 11795: if ($role eq 'st') {
11796: if (ref($settings) ne 'HASH') {
11797: $check = ' checked="checked" ';
11798: }
1.33 raeburn 11799: }
11800: }
11801: }
11802: $output .= '<td class="LC_left_item">'.
1.228 raeburn 11803: '<span class="LC_nobreak">';
1.325 raeburn 11804: my $prefix = 'canmodify';
1.228 raeburn 11805: if ($role eq 'emailusername') {
11806: unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {
11807: $checks{$fields[$i]} = 'omit';
11808: }
11809: foreach my $option ('required','optional','omit') {
11810: my $checked='';
11811: if ($checks{$fields[$i]} eq $option) {
11812: $checked='checked="checked" ';
11813: }
11814: $output .= '<label>'.
1.325 raeburn 11815: '<input type="radio" name="'.$prefix.'_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.
1.228 raeburn 11816: &mt($option).'</label>'.(' ' x2);
11817: }
11818: $output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';
11819: } else {
1.325 raeburn 11820: if ($context eq 'lti') {
11821: $prefix = 'lti';
1.357 raeburn 11822: } elsif ($context eq 'privacy') {
11823: $prefix = 'privacy';
1.325 raeburn 11824: }
1.228 raeburn 11825: $output .= '<label>'.
1.325 raeburn 11826: '<input type="checkbox" name="'.$prefix.'_'.$role.'" '.
1.228 raeburn 11827: 'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.
11828: '</label>';
11829: }
11830: $output .= '</span></td>';
1.33 raeburn 11831: }
1.305 raeburn 11832: $rem = $total%$numinrow;
11833: my $colsleft;
11834: if ($rem) {
11835: $colsleft = $numinrow - $rem;
11836: }
11837: if ($colsleft > 1) {
1.33 raeburn 11838: $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
11839: ' </td>';
11840: } elsif ($colsleft == 1) {
11841: $output .= '<td class="LC_left_item"> </td>';
11842: }
11843: $output .= '</tr></table></td></tr>';
11844: return $output;
11845: }
1.28 raeburn 11846:
1.93 raeburn 11847: sub insttypes_row {
1.305 raeburn 11848: my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rowtotal,$onclick,
11849: $customcss,$rowstyle) = @_;
1.93 raeburn 11850: my %lt = &Apache::lonlocal::texthash (
11851: cansearch => 'Users allowed to search',
11852: statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
1.131 raeburn 11853: lockablenames => 'User preference to lock name',
1.305 raeburn 11854: selfassign => 'Self-reportable affiliations',
1.315 raeburn 11855: overrides => "Override domain's helpdesk settings based on requester's affiliation",
1.93 raeburn 11856: );
11857: my $showdom;
11858: if ($context eq 'cansearch') {
11859: $showdom = ' ('.$dom.')';
11860: }
1.165 raeburn 11861: my $class = 'LC_left_item';
11862: if ($context eq 'statustocreate') {
11863: $class = 'LC_right_item';
11864: }
1.305 raeburn 11865: my $css_class;
11866: if ($$rowtotal%2) {
11867: $css_class = 'LC_odd_row';
11868: }
11869: if ($customcss) {
11870: $css_class .= ' '.$customcss;
11871: }
11872: $css_class =~ s/^\s+//;
11873: if ($css_class) {
11874: $css_class = ' class="'.$css_class.'"';
11875: }
11876: if ($rowstyle) {
11877: $css_class .= ' style="'.$rowstyle.'"';
11878: }
11879: if ($onclick) {
11880: $onclick = 'onclick="'.$onclick.'" ';
1.224 raeburn 11881: }
11882: my $output = '<tr'.$css_class.'>'.
11883: '<td>'.$lt{$context}.$showdom.
11884: '</td><td class="'.$class.'" colspan="2"><table>';
1.26 raeburn 11885: my $rem;
11886: if (ref($types) eq 'ARRAY') {
11887: for (my $i=0; $i<@{$types}; $i++) {
11888: if (defined($usertypes->{$types->[$i]})) {
11889: my $rem = $i%($numinrow);
11890: if ($rem == 0) {
11891: if ($i > 0) {
11892: $output .= '</tr>';
11893: }
11894: $output .= '<tr>';
1.23 raeburn 11895: }
1.26 raeburn 11896: my $check = ' ';
1.99 raeburn 11897: if (ref($settings) eq 'HASH') {
11898: if (ref($settings->{$context}) eq 'ARRAY') {
11899: if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {
11900: $check = ' checked="checked" ';
11901: }
1.315 raeburn 11902: } elsif (ref($settings->{$context}) eq 'HASH') {
11903: if (ref($settings->{$context}->{$types->[$i]}) eq 'HASH') {
11904: $check = ' checked="checked" ';
11905: }
1.99 raeburn 11906: } elsif ($context eq 'statustocreate') {
1.26 raeburn 11907: $check = ' checked="checked" ';
11908: }
1.23 raeburn 11909: }
1.26 raeburn 11910: $output .= '<td class="LC_left_item">'.
11911: '<span class="LC_nobreak"><label>'.
1.93 raeburn 11912: '<input type="checkbox" name="'.$context.'" '.
1.305 raeburn 11913: 'value="'.$types->[$i].'"'.$check.$onclick.' />'.
1.26 raeburn 11914: $usertypes->{$types->[$i]}.'</label></span></td>';
1.23 raeburn 11915: }
11916: }
1.26 raeburn 11917: $rem = @{$types}%($numinrow);
1.23 raeburn 11918: }
11919: my $colsleft = $numinrow - $rem;
1.315 raeburn 11920: if ($context eq 'overrides') {
11921: if ($colsleft > 1) {
11922: $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
11923: } else {
11924: $output .= '<td class="LC_left_item">';
11925: }
1.425 raeburn 11926: $output .= ' ';
1.23 raeburn 11927: } else {
1.334 raeburn 11928: if ($rem == 0) {
1.315 raeburn 11929: $output .= '<tr>';
11930: }
11931: if ($colsleft > 1) {
11932: $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">';
11933: } else {
11934: $output .= '<td class="LC_left_item">';
11935: }
11936: my $defcheck = ' ';
11937: if (ref($settings) eq 'HASH') {
11938: if (ref($settings->{$context}) eq 'ARRAY') {
11939: if (grep(/^default$/,@{$settings->{$context}})) {
11940: $defcheck = ' checked="checked" ';
11941: }
11942: } elsif ($context eq 'statustocreate') {
1.99 raeburn 11943: $defcheck = ' checked="checked" ';
11944: }
1.26 raeburn 11945: }
1.315 raeburn 11946: $output .= '<span class="LC_nobreak"><label>'.
11947: '<input type="checkbox" name="'.$context.'" '.
11948: 'value="default"'.$defcheck.$onclick.' />'.
11949: $othertitle.'</label></span>';
1.23 raeburn 11950: }
1.315 raeburn 11951: $output .= '</td></tr></table></td></tr>';
1.25 raeburn 11952: return $output;
1.23 raeburn 11953: }
11954:
11955: sub sorted_searchtitles {
11956: my %searchtitles = &Apache::lonlocal::texthash(
11957: 'uname' => 'username',
11958: 'lastname' => 'last name',
11959: 'lastfirst' => 'last name, first name',
11960: );
11961: my @titleorder = ('uname','lastname','lastfirst');
11962: return (\%searchtitles,\@titleorder);
11963: }
11964:
1.25 raeburn 11965: sub sorted_searchtypes {
11966: my %srchtypes_desc = (
11967: exact => 'is exact match',
11968: contains => 'contains ..',
11969: begins => 'begins with ..',
11970: );
11971: my @srchtypeorder = ('exact','begins','contains');
11972: return (\%srchtypes_desc,\@srchtypeorder);
11973: }
11974:
1.3 raeburn 11975: sub usertype_update_row {
11976: my ($settings,$usertypes,$fieldtitles,$fields,$types,$rownums) = @_;
11977: my $datatable;
11978: my $numinrow = 4;
11979: foreach my $type (@{$types}) {
11980: if (defined($usertypes->{$type})) {
11981: $$rownums ++;
11982: my $css_class = $$rownums%2?' class="LC_odd_row"':'';
11983: $datatable .= '<tr'.$css_class.'><td>'.$usertypes->{$type}.
11984: '</td><td class="LC_left_item"><table>';
11985: for (my $i=0; $i<@{$fields}; $i++) {
11986: my $rem = $i%($numinrow);
11987: if ($rem == 0) {
11988: if ($i > 0) {
11989: $datatable .= '</tr>';
11990: }
11991: $datatable .= '<tr>';
11992: }
11993: my $check = ' ';
1.39 raeburn 11994: if (ref($settings) eq 'HASH') {
11995: if (ref($settings->{'fields'}) eq 'HASH') {
11996: if (ref($settings->{'fields'}{$type}) eq 'ARRAY') {
11997: if (grep(/^\Q$fields->[$i]\E$/,@{$settings->{'fields'}{$type}})) {
11998: $check = ' checked="checked" ';
11999: }
1.3 raeburn 12000: }
12001: }
12002: }
12003:
12004: if ($i == @{$fields}-1) {
12005: my $colsleft = $numinrow - $rem;
12006: if ($colsleft > 1) {
12007: $datatable .= '<td colspan="'.$colsleft.'">';
12008: } else {
12009: $datatable .= '<td>';
12010: }
12011: } else {
12012: $datatable .= '<td>';
12013: }
1.8 raeburn 12014: $datatable .= '<span class="LC_nobreak"><label>'.
12015: '<input type="checkbox" name="updateable_'.$type.
12016: '_'.$fields->[$i].'" value="1"'.$check.'/>'.
12017: $fieldtitles->{$fields->[$i]}.'</label></span></td>';
1.3 raeburn 12018: }
12019: $datatable .= '</tr></table></td></tr>';
12020: }
12021: }
12022: return $datatable;
1.1 raeburn 12023: }
12024:
12025: sub modify_login {
1.205 raeburn 12026: my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
1.168 raeburn 12027: my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl,
1.386 raeburn 12028: %curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon,
1.412 raeburn 12029: %currsaml,%saml,%samltext,%samlimg,%samlalt,%samlurl,%samltitle,%samlwindow,%samlnotsso);
1.168 raeburn 12030: %title = ( coursecatalog => 'Display course catalog',
12031: adminmail => 'Display administrator E-mail address',
1.188 raeburn 12032: helpdesk => 'Display "Contact Helpdesk" link',
1.168 raeburn 12033: newuser => 'Link for visitors to create a user account',
1.386 raeburn 12034: loginheader => 'Log-in box header',
12035: saml => 'Dual SSO and non-SSO login');
1.168 raeburn 12036: @offon = ('off','on');
1.112 raeburn 12037: if (ref($domconfig{login}) eq 'HASH') {
12038: if (ref($domconfig{login}{loginvia}) eq 'HASH') {
12039: foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) {
12040: $curr_loginvia{$lonhost} = $domconfig{login}{loginvia}{$lonhost};
12041: }
12042: }
1.386 raeburn 12043: if (ref($domconfig{login}{'saml'}) eq 'HASH') {
12044: foreach my $lonhost (keys(%{$domconfig{login}{'saml'}})) {
12045: if (ref($domconfig{login}{'saml'}{$lonhost}) eq 'HASH') {
12046: $currsaml{$lonhost} = $domconfig{login}{'saml'}{$lonhost};
12047: $saml{$lonhost} = 1;
12048: $samltext{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'text'};
12049: $samlurl{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'url'};
12050: $samlalt{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'alt'};
12051: $samlimg{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'img'};
12052: $samltitle{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'title'};
1.412 raeburn 12053: $samlwindow{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'window'};
1.386 raeburn 12054: $samlnotsso{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'notsso'};
12055: }
12056: }
12057: }
1.112 raeburn 12058: }
1.9 raeburn 12059: ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'],
12060: \%domconfig,\%loginhash);
1.188 raeburn 12061: my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
1.42 raeburn 12062: foreach my $item (@toggles) {
12063: $loginhash{login}{$item} = $env{'form.'.$item};
12064: }
1.41 raeburn 12065: $loginhash{login}{loginheader} = $env{'form.loginheader'};
1.6 raeburn 12066: if (ref($colchanges{'login'}) eq 'HASH') {
12067: $colchgtext = &display_colorchgs($dom,\%colchanges,['login'],
12068: \%loginhash);
12069: }
1.110 raeburn 12070:
1.149 raeburn 12071: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.256 raeburn 12072: my %domservers = &Apache::lonnet::get_servers($dom);
1.128 raeburn 12073: my @loginvia_attribs = ('serverpath','custompath','exempt');
1.110 raeburn 12074: if (keys(%servers) > 1) {
12075: foreach my $lonhost (keys(%servers)) {
1.128 raeburn 12076: next if ($env{'form.'.$lonhost.'_server'} eq $lonhost);
12077: if (ref($curr_loginvia{$lonhost}) eq 'HASH') {
12078: if ($env{'form.'.$lonhost.'_server'} eq $curr_loginvia{$lonhost}{'server'}) {
12079: $loginhash{login}{loginvia}{$lonhost}{'server'} = $curr_loginvia{$lonhost}{'server'};
12080: } elsif ($curr_loginvia{$lonhost}{'server'} ne '') {
12081: if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
12082: $loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
12083: $changes{'loginvia'}{$lonhost} = 1;
12084: } else {
12085: $loginhash{login}{loginvia}{$lonhost}{'server'} = '';
12086: $changes{'loginvia'}{$lonhost} = 1;
12087: }
12088: } else {
12089: if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
12090: $loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
12091: $changes{'loginvia'}{$lonhost} = 1;
12092: }
12093: }
12094: if ($loginhash{login}{loginvia}{$lonhost}{'server'} eq '') {
12095: foreach my $item (@loginvia_attribs) {
12096: $loginhash{login}{loginvia}{$lonhost}{$item} = '';
12097: }
12098: } else {
12099: foreach my $item (@loginvia_attribs) {
12100: my $new = $env{'form.'.$lonhost.'_'.$item};
12101: if (($item eq 'serverpath') && ($new eq 'custom')) {
12102: $env{'form.'.$lonhost.'_custompath'} =~ s/\s+//g;
12103: if ($env{'form.'.$lonhost.'_custompath'} eq '') {
12104: $new = '/';
12105: }
12106: }
12107: if (($item eq 'custompath') &&
12108: ($env{'form.'.$lonhost.'_serverpath'} ne 'custom')) {
12109: $new = '';
12110: }
12111: if ($new ne $curr_loginvia{$lonhost}{$item}) {
12112: $changes{'loginvia'}{$lonhost} = 1;
12113: }
12114: if ($item eq 'exempt') {
1.256 raeburn 12115: $new = &check_exempt_addresses($new);
1.128 raeburn 12116: }
12117: $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
12118: }
12119: }
1.112 raeburn 12120: } else {
1.128 raeburn 12121: if (defined($servers{$env{'form.'.$lonhost.'_server'}})) {
12122: $loginhash{login}{loginvia}{$lonhost}{'server'} = $env{'form.'.$lonhost.'_server'};
1.112 raeburn 12123: $changes{'loginvia'}{$lonhost} = 1;
1.128 raeburn 12124: foreach my $item (@loginvia_attribs) {
12125: my $new = $env{'form.'.$lonhost.'_'.$item};
12126: if (($item eq 'serverpath') && ($new eq 'custom')) {
12127: if ($env{'form.'.$lonhost.'_custompath'} eq '') {
12128: $new = '/';
12129: }
12130: }
12131: if (($item eq 'custompath') &&
12132: ($env{'form.'.$lonhost.'_serverpath'} ne 'custom')) {
12133: $new = '';
12134: }
12135: $loginhash{login}{loginvia}{$lonhost}{$item} = $new;
12136: }
1.110 raeburn 12137: }
12138: }
12139: }
12140: }
1.119 raeburn 12141:
1.168 raeburn 12142: my $servadm = $r->dir_config('lonAdmEMail');
12143: my %langchoices = &Apache::lonlocal::texthash(&get_languages_hash());
12144: if (ref($domconfig{'login'}) eq 'HASH') {
12145: if (ref($domconfig{'login'}{'helpurl'}) eq 'HASH') {
12146: foreach my $lang (sort(keys(%{$domconfig{'login'}{'helpurl'}}))) {
12147: if ($lang eq 'nolang') {
12148: push(@currlangs,$lang);
12149: } elsif (defined($langchoices{$lang})) {
12150: push(@currlangs,$lang);
12151: } else {
12152: next;
12153: }
12154: }
12155: }
12156: }
12157: my @delurls = &Apache::loncommon::get_env_multiple('form.loginhelpurl_del');
12158: if (@currlangs > 0) {
12159: foreach my $lang (@currlangs) {
12160: if (grep(/^\Q$lang\E$/,@delurls)) {
12161: $changes{'helpurl'}{$lang} = 1;
12162: } elsif ($env{'form.loginhelpurl_'.$lang.'.filename'}) {
12163: $changes{'helpurl'}{$lang} = 1;
12164: $newfile{$lang} = $env{'form.loginhelpurl_'.$lang.'.filename'};
12165: push(@newlangs,$lang);
12166: } else {
12167: $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
12168: }
12169: }
12170: }
12171: unless (grep(/^nolang$/,@currlangs)) {
12172: if ($env{'form.loginhelpurl_nolang.filename'}) {
12173: $changes{'helpurl'}{'nolang'} = 1;
12174: $newfile{'nolang'} = $env{'form.loginhelpurl_nolang.filename'};
12175: push(@newlangs,'nolang');
12176: }
12177: }
12178: if ($env{'form.loginhelpurl_add_lang'}) {
12179: if ((defined($langchoices{$env{'form.loginhelpurl_add_lang'}})) &&
12180: ($env{'form.loginhelpurl_add_file.filename'})) {
12181: $newfile{$env{'form.loginhelpurl_add_lang'}} = $env{'form.loginhelpurl_add_file.filename'};
12182: $addedfile = $env{'form.loginhelpurl_add_lang'};
12183: }
12184: }
12185: if ((@newlangs > 0) || ($addedfile)) {
12186: my $error;
12187: my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
12188: if ($configuserok eq 'ok') {
12189: if ($switchserver) {
12190: $error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver);
12191: } elsif ($author_ok eq 'ok') {
12192: my @allnew = @newlangs;
12193: if ($addedfile ne '') {
12194: push(@allnew,$addedfile);
12195: }
1.421 raeburn 12196: my $modified = [];
1.168 raeburn 12197: foreach my $lang (@allnew) {
12198: my $formelem = 'loginhelpurl_'.$lang;
12199: if ($lang eq $env{'form.loginhelpurl_add_lang'}) {
12200: $formelem = 'loginhelpurl_add_file';
12201: }
1.425 raeburn 12202: (my $result,$newurl{$lang}) =
1.421 raeburn 12203: &Apache::lonconfigsettings::publishlogo($r,'upload',$formelem,$dom,$confname,
12204: "help/$lang",'','',$newfile{$lang},
12205: $modified);
1.168 raeburn 12206: if ($result eq 'ok') {
12207: $loginhash{'login'}{'helpurl'}{$lang} = $newurl{$lang};
12208: $changes{'helpurl'}{$lang} = 1;
12209: } else {
12210: my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$newfile{$lang},$result);
12211: $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
1.210 raeburn 12212: if ((grep(/^\Q$lang\E$/,@currlangs)) &&
1.168 raeburn 12213: (!grep(/^\Q$lang\E$/,@delurls))) {
12214: $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang};
12215: }
12216: }
12217: }
1.421 raeburn 12218: &update_modify_urls($r,$modified);
1.168 raeburn 12219: } else {
12220: $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);
12221: }
12222: } else {
12223: $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);
12224: }
12225: if ($error) {
12226: &Apache::lonnet::logthis($error);
12227: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
12228: }
12229: }
1.256 raeburn 12230:
12231: my (%currheadtagurls,%currexempt,@newhosts,%newheadtagurls,%possexempt);
12232: if (ref($domconfig{'login'}) eq 'HASH') {
12233: if (ref($domconfig{'login'}{'headtag'}) eq 'HASH') {
12234: foreach my $lonhost (keys(%{$domconfig{'login'}{'headtag'}})) {
12235: if ($domservers{$lonhost}) {
12236: if (ref($domconfig{'login'}{'headtag'}{$lonhost}) eq 'HASH') {
12237: $currheadtagurls{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'url'};
1.268 raeburn 12238: $currexempt{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'exempt'};
1.256 raeburn 12239: }
12240: }
12241: }
12242: }
12243: }
12244: my @delheadtagurls = &Apache::loncommon::get_env_multiple('form.loginheadtag_del');
12245: foreach my $lonhost (sort(keys(%domservers))) {
12246: if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {
12247: $changes{'headtag'}{$lonhost} = 1;
12248: } else {
12249: if ($env{'form.loginheadtagexempt_'.$lonhost}) {
12250: $possexempt{$lonhost} = &check_exempt_addresses($env{'form.loginheadtagexempt_'.$lonhost});
12251: }
12252: if ($env{'form.loginheadtag_'.$lonhost.'.filename'}) {
12253: push(@newhosts,$lonhost);
12254: } elsif ($currheadtagurls{$lonhost}) {
12255: $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $currheadtagurls{$lonhost};
12256: if ($currexempt{$lonhost}) {
1.289 raeburn 12257: if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) {
1.256 raeburn 12258: $changes{'headtag'}{$lonhost} = 1;
12259: }
12260: } elsif ($possexempt{$lonhost}) {
12261: $changes{'headtag'}{$lonhost} = 1;
12262: }
12263: if ($possexempt{$lonhost}) {
12264: $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};
12265: }
12266: }
12267: }
12268: }
12269: if (@newhosts) {
12270: my $error;
12271: my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
12272: if ($configuserok eq 'ok') {
12273: if ($switchserver) {
12274: $error = &mt("Upload of custom markup is not permitted to this server: [_1]",$switchserver);
12275: } elsif ($author_ok eq 'ok') {
1.421 raeburn 12276: my $modified = [];
1.256 raeburn 12277: foreach my $lonhost (@newhosts) {
12278: my $formelem = 'loginheadtag_'.$lonhost;
1.425 raeburn 12279: (my $result,$newheadtagurls{$lonhost}) =
1.421 raeburn 12280: &Apache::lonconfigsettings::publishlogo($r,'upload',$formelem,$dom,$confname,
12281: "login/headtag/$lonhost",'','',
12282: $env{'form.loginheadtag_'.$lonhost.'.filename'},
12283: $modified);
1.256 raeburn 12284: if ($result eq 'ok') {
12285: $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $newheadtagurls{$lonhost};
12286: $changes{'headtag'}{$lonhost} = 1;
12287: if ($possexempt{$lonhost}) {
12288: $loginhash{'login'}{'headtag'}{$lonhost}{'exempt'} = $possexempt{$lonhost};
12289: }
12290: } else {
12291: my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",
12292: $newheadtagurls{$lonhost},$result);
12293: $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
12294: if ((grep(/^\Q$lonhost\E$/,keys(%currheadtagurls))) &&
12295: (!grep(/^\Q$lonhost\E$/,@delheadtagurls))) {
12296: $loginhash{'login'}{'headtag'}{$lonhost} = $currheadtagurls{$lonhost};
12297: }
12298: }
12299: }
1.421 raeburn 12300: &update_modify_urls($r,$modified);
1.256 raeburn 12301: } else {
12302: $error = &mt("Upload of custom markup 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);
12303: }
12304: } else {
12305: $error = &mt("Upload of custom markup file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2]. Error was: [_3].",$confname,$dom,$configuserok);
12306: }
12307: if ($error) {
12308: &Apache::lonnet::logthis($error);
12309: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
12310: }
12311: }
1.386 raeburn 12312: my @delsamlimg = &Apache::loncommon::get_env_multiple('form.saml_img_del');
12313: my @newsamlimgs;
12314: foreach my $lonhost (keys(%domservers)) {
12315: if ($env{'form.saml_'.$lonhost}) {
12316: if ($env{'form.saml_img_'.$lonhost.'.filename'}) {
12317: push(@newsamlimgs,$lonhost);
12318: }
1.412 raeburn 12319: foreach my $item ('text','alt','url','title','window','notsso') {
1.386 raeburn 12320: $env{'form.saml_'.$item.'_'.$lonhost} =~ s/^\s+|\s+$//g;
12321: }
12322: if ($saml{$lonhost}) {
1.412 raeburn 12323: if ($env{'form.saml_window_'.$lonhost} ne '1') {
12324: $env{'form.saml_window_'.$lonhost} = '';
12325: }
1.386 raeburn 12326: if (grep(/^\Q$lonhost\E$/,@delsamlimg)) {
12327: #FIXME Need to obsolete published image
12328: delete($currsaml{$lonhost}{'img'});
12329: $changes{'saml'}{$lonhost} = 1;
12330: }
12331: if ($env{'form.saml_alt_'.$lonhost} ne $samlalt{$lonhost}) {
12332: $changes{'saml'}{$lonhost} = 1;
12333: }
12334: if ($env{'form.saml_text_'.$lonhost} ne $samltext{$lonhost}) {
12335: $changes{'saml'}{$lonhost} = 1;
12336: }
12337: if ($env{'form.saml_url_'.$lonhost} ne $samlurl{$lonhost}) {
12338: $changes{'saml'}{$lonhost} = 1;
12339: }
12340: if ($env{'form.saml_title_'.$lonhost} ne $samltitle{$lonhost}) {
12341: $changes{'saml'}{$lonhost} = 1;
12342: }
1.412 raeburn 12343: if ($env{'form.saml_window_'.$lonhost} ne $samlwindow{$lonhost}) {
12344: $changes{'saml'}{$lonhost} = 1;
12345: }
1.386 raeburn 12346: if ($env{'form.saml_notsso_'.$lonhost} ne $samlnotsso{$lonhost}) {
12347: $changes{'saml'}{$lonhost} = 1;
12348: }
12349: } else {
12350: $changes{'saml'}{$lonhost} = 1;
12351: }
1.412 raeburn 12352: foreach my $item ('text','alt','url','title','window','notsso') {
1.386 raeburn 12353: $currsaml{$lonhost}{$item} = $env{'form.saml_'.$item.'_'.$lonhost};
12354: }
12355: } else {
1.425 raeburn 12356: if ($saml{$lonhost}) {
1.389 raeburn 12357: $changes{'saml'}{$lonhost} = 1;
12358: delete($currsaml{$lonhost});
12359: }
1.386 raeburn 12360: }
12361: }
12362: foreach my $posshost (keys(%currsaml)) {
1.425 raeburn 12363: unless (exists($domservers{$posshost})) {
12364: delete($currsaml{$posshost});
1.386 raeburn 12365: }
12366: }
12367: %{$loginhash{'login'}{'saml'}} = %currsaml;
12368: if (@newsamlimgs) {
12369: my $error;
12370: my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
12371: if ($configuserok eq 'ok') {
12372: if ($switchserver) {
12373: $error = &mt("Upload of SSO Button Image is not permitted to this server: [_1].",$switchserver);
12374: } elsif ($author_ok eq 'ok') {
1.421 raeburn 12375: my $modified = [];
1.386 raeburn 12376: foreach my $lonhost (@newsamlimgs) {
12377: my $formelem = 'saml_img_'.$lonhost;
1.425 raeburn 12378: my ($result,$imgurl) =
1.421 raeburn 12379: &Apache::lonconfigsettings::publishlogo($r,'upload',$formelem,$dom,$confname,
12380: "login/saml/$lonhost",'','',
12381: $env{'form.saml_img_'.$lonhost.'.filename'},
12382: $modified);
1.386 raeburn 12383: if ($result eq 'ok') {
12384: $currsaml{$lonhost}{'img'} = $imgurl;
12385: $loginhash{'login'}{'saml'}{$lonhost}{'img'} = $imgurl;
12386: $changes{'saml'}{$lonhost} = 1;
12387: } else {
12388: my $puberror = &mt("Upload of SSO button image failed for [_1] because an error occurred publishing the file in RES space. Error was: [_2].",
12389: $lonhost,$result);
12390: $errors .= '<li><span class="LC_error">'.$puberror.'</span></li>';
12391: }
12392: }
1.421 raeburn 12393: &update_modify_urls($r,$modified);
1.386 raeburn 12394: } else {
12395: $error = &mt("Upload of SSO button image 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);
12396: }
12397: } else {
12398: $error = &mt("Upload of SSO button image file(s) failed because a Domain Configuration user ([_1]) could not be created in domain: [_2]. Error was: [_3].",$confname,$dom,$configuserok);
12399: }
12400: if ($error) {
12401: &Apache::lonnet::logthis($error);
12402: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
12403: }
12404: }
1.169 raeburn 12405: &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'});
1.168 raeburn 12406:
12407: my $defaulthelpfile = '/adm/loginproblems.html';
12408: my $defaulttext = &mt('Default in use');
12409:
1.1 raeburn 12410: my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,
12411: $dom);
12412: if ($putresult eq 'ok') {
1.188 raeburn 12413: my @toggles = ('coursecatalog','adminmail','helpdesk','newuser');
1.42 raeburn 12414: my %defaultchecked = (
12415: 'coursecatalog' => 'on',
1.188 raeburn 12416: 'helpdesk' => 'on',
1.42 raeburn 12417: 'adminmail' => 'off',
1.43 raeburn 12418: 'newuser' => 'off',
1.42 raeburn 12419: );
1.55 raeburn 12420: if (ref($domconfig{'login'}) eq 'HASH') {
12421: foreach my $item (@toggles) {
12422: if ($defaultchecked{$item} eq 'on') {
12423: if (($domconfig{'login'}{$item} eq '0') &&
12424: ($env{'form.'.$item} eq '1')) {
12425: $changes{$item} = 1;
12426: } elsif (($domconfig{'login'}{$item} eq '' ||
12427: $domconfig{'login'}{$item} eq '1') &&
12428: ($env{'form.'.$item} eq '0')) {
12429: $changes{$item} = 1;
12430: }
12431: } elsif ($defaultchecked{$item} eq 'off') {
12432: if (($domconfig{'login'}{$item} eq '1') &&
12433: ($env{'form.'.$item} eq '0')) {
12434: $changes{$item} = 1;
12435: } elsif (($domconfig{'login'}{$item} eq '' ||
12436: $domconfig{'login'}{$item} eq '0') &&
12437: ($env{'form.'.$item} eq '1')) {
12438: $changes{$item} = 1;
12439: }
1.42 raeburn 12440: }
12441: }
1.41 raeburn 12442: }
1.6 raeburn 12443: if (keys(%changes) > 0 || $colchgtext) {
1.41 raeburn 12444: &Apache::loncommon::devalidate_domconfig_cache($dom);
1.386 raeburn 12445: if (exists($changes{'saml'})) {
12446: my $hostid_in_use;
12447: my @hosts = &Apache::lonnet::current_machine_ids();
12448: if (@hosts > 1) {
12449: foreach my $hostid (@hosts) {
12450: if (&Apache::lonnet::host_domain($hostid) eq $dom) {
12451: $hostid_in_use = $hostid;
12452: last;
12453: }
12454: }
12455: } else {
12456: $hostid_in_use = $r->dir_config('lonHostID');
12457: }
12458: if (($hostid_in_use) &&
12459: (&Apache::lonnet::host_domain($hostid_in_use) eq $dom)) {
1.387 raeburn 12460: &Apache::lonnet::devalidate_cache_new('samllanding',$hostid_in_use);
1.386 raeburn 12461: }
12462: if (ref($lastactref) eq 'HASH') {
12463: if (ref($changes{'saml'}) eq 'HASH') {
12464: my %updates;
12465: map { $updates{$_} = 1; } keys(%{$changes{'saml'}});
12466: $lastactref->{'samllanding'} = \%updates;
12467: }
12468: }
12469: }
1.212 raeburn 12470: if (ref($lastactref) eq 'HASH') {
12471: $lastactref->{'domainconfig'} = 1;
12472: }
1.1 raeburn 12473: $resulttext = &mt('Changes made:').'<ul>';
12474: foreach my $item (sort(keys(%changes))) {
1.135 bisitz 12475: if ($item eq 'loginvia') {
1.112 raeburn 12476: if (ref($changes{$item}) eq 'HASH') {
12477: $resulttext .= '<li>'.&mt('Log-in page availability:').'<ul>';
12478: foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
1.128 raeburn 12479: if (defined($servers{$loginhash{login}{loginvia}{$lonhost}{'server'}})) {
12480: if (ref($loginhash{login}{loginvia}{$lonhost}) eq 'HASH') {
12481: my $protocol = $Apache::lonnet::protocol{$env{'form.'.$lonhost.'_server'}};
12482: $protocol = 'http' if ($protocol ne 'https');
12483: my $target = $protocol.'://'.$servers{$env{'form.'.$lonhost.'_server'}};
12484:
12485: if ($loginhash{login}{loginvia}{$lonhost}{'serverpath'} eq 'custom') {
12486: $target .= $loginhash{login}{loginvia}{$lonhost}{'custompath'};
12487: } else {
12488: $target .= $loginhash{login}{loginvia}{$lonhost}{'serverpath'};
12489: }
12490: $resulttext .= '<li>'.&mt('Server: [_1] log-in page redirects to [_2].',$servers{$lonhost},'<a href="'.$target.'">'.$target.'</a>');
12491: if ($loginhash{login}{loginvia}{$lonhost}{'exempt'} ne '') {
12492: $resulttext .= ' '.&mt('No redirection for clients from following IPs:').' '.$loginhash{login}{loginvia}{$lonhost}{'exempt'};
12493: }
12494: $resulttext .= '</li>';
12495: } else {
12496: $resulttext .= '<li>'.&mt('Server: [_1] has standard log-in page.',$lonhost).'</li>';
12497: }
1.112 raeburn 12498: } else {
1.128 raeburn 12499: $resulttext .= '<li>'.&mt('Server: [_1] has standard log-in page.',$servers{$lonhost}).'</li>';
1.112 raeburn 12500: }
12501: }
1.128 raeburn 12502: $resulttext .= '</ul></li>';
1.112 raeburn 12503: }
1.168 raeburn 12504: } elsif ($item eq 'helpurl') {
12505: if (ref($changes{$item}) eq 'HASH') {
12506: foreach my $lang (sort(keys(%{$changes{$item}}))) {
12507: if (grep(/^\Q$lang\E$/,@delurls)) {
12508: my ($chg,$link);
12509: $link = &Apache::loncommon::modal_link($defaulthelpfile,$defaulttext,600,500);
12510: if ($lang eq 'nolang') {
12511: $chg = &mt('custom log-in help file removed for no preferred language; [_1]',$link);
12512: } else {
12513: $chg = &mt('custom log-in help file removed for specific language: [_1]; [_2]',$langchoices{$lang},$link);
12514: }
12515: $resulttext .= '<li>'.$chg.'</li>';
12516: } else {
12517: my $chg;
12518: if ($lang eq 'nolang') {
12519: $chg = &mt('custom log-in help file for no preferred language');
12520: } else {
12521: $chg = &mt('custom log-in help file for specific language: [_1]',$langchoices{$lang});
12522: }
12523: $resulttext .= '<li>'.&Apache::loncommon::modal_link(
12524: $loginhash{'login'}{'helpurl'}{$lang}.
12525: '?inhibitmenu=yes',$chg,600,500).
12526: '</li>';
12527: }
12528: }
12529: }
1.256 raeburn 12530: } elsif ($item eq 'headtag') {
12531: if (ref($changes{$item}) eq 'HASH') {
12532: foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
12533: if (grep(/^\Q$lonhost\E$/,@delheadtagurls)) {
12534: $resulttext .= '<li>'.&mt('custom markup file removed for [_1]',$domservers{$lonhost}).'</li>';
12535: } elsif (ref($loginhash{'login'}{'headtag'}{$lonhost}) eq 'HASH') {
12536: $resulttext .= '<li><a href="'.
12537: "javascript:void(open('$loginhash{'login'}{'headtag'}{$lonhost}{'url'}?inhibitmenu=yes','Custom_HeadTag',
12538: 'menubar=0,toolbar=1,scrollbars=1,width=600,height=500,resizable=yes'))".
12539: '">'.&mt('custom markup').'</a> '.&mt('(for [_1])',$servers{$lonhost}).' ';
12540: if ($possexempt{$lonhost}) {
12541: $resulttext .= &mt('not included for client IP(s): [_1]',$possexempt{$lonhost});
12542: } else {
12543: $resulttext .= &mt('included for any client IP');
12544: }
12545: $resulttext .= '</li>';
12546: }
12547: }
12548: }
1.386 raeburn 12549: } elsif ($item eq 'saml') {
12550: if (ref($changes{$item}) eq 'HASH') {
12551: my %notlt = (
12552: text => 'Text for log-in by SSO',
12553: img => 'SSO button image',
12554: alt => 'Alt text for button image',
12555: url => 'SSO URL',
12556: title => 'Tooltip for SSO link',
1.412 raeburn 12557: window => 'Pop-up window if iframe',
1.386 raeburn 12558: notsso => 'Text for non-SSO log-in',
12559: );
12560: foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
12561: if (ref($currsaml{$lonhost}) eq 'HASH') {
12562: $resulttext .= '<li>'.&mt("$title{$item} in use for [_1]","<b>$lonhost</b>").
12563: '<ul>';
1.412 raeburn 12564: foreach my $key ('text','img','alt','url','title','window','notsso') {
1.386 raeburn 12565: if ($currsaml{$lonhost}{$key} eq '') {
12566: $resulttext .= '<li>'.&mt("$notlt{$key} not in use").'</li>';
12567: } else {
12568: my $value = "'$currsaml{$lonhost}{$key}'";
12569: if ($key eq 'img') {
12570: $value = '<img src="'.$currsaml{$lonhost}{$key}.'" />';
1.412 raeburn 12571: } elsif ($key eq 'window') {
12572: $value = 'On';
1.386 raeburn 12573: }
12574: $resulttext .= '<li>'.&mt("$notlt{$key} set to: [_1]",
12575: $value).'</li>';
12576: }
12577: }
12578: $resulttext .= '</ul></li>';
12579: } else {
12580: $resulttext .= '<li>'.&mt("$title{$item} not in use for [_1]",$lonhost).'</li>';
12581: }
12582: }
12583: }
1.169 raeburn 12584: } elsif ($item eq 'captcha') {
12585: if (ref($loginhash{'login'}) eq 'HASH') {
1.210 raeburn 12586: my $chgtxt;
1.169 raeburn 12587: if ($loginhash{'login'}{$item} eq 'notused') {
12588: $chgtxt .= &mt('No CAPTCHA validation in use for helpdesk form.');
12589: } else {
12590: my %captchas = &captcha_phrases();
12591: if ($captchas{$loginhash{'login'}{$item}}) {
12592: $chgtxt .= &mt("Validation for helpdesk form set to $captchas{$loginhash{'login'}{$item}}.");
12593: } else {
12594: $chgtxt .= &mt('Validation for helpdesk form set to unknown type.');
12595: }
12596: }
12597: $resulttext .= '<li>'.$chgtxt.'</li>';
12598: }
12599: } elsif ($item eq 'recaptchakeys') {
12600: if (ref($loginhash{'login'}) eq 'HASH') {
12601: my ($privkey,$pubkey);
12602: if (ref($loginhash{'login'}{$item}) eq 'HASH') {
12603: $pubkey = $loginhash{'login'}{$item}{'public'};
12604: $privkey = $loginhash{'login'}{$item}{'private'};
12605: }
12606: my $chgtxt .= &mt('ReCAPTCHA keys changes').'<ul>';
12607: if (!$pubkey) {
12608: $chgtxt .= '<li>'.&mt('Public key deleted').'</li>';
12609: } else {
12610: $chgtxt .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';
12611: }
12612: if (!$privkey) {
12613: $chgtxt .= '<li>'.&mt('Private key deleted').'</li>';
12614: } else {
1.251 raeburn 12615: $chgtxt .= '<li>'.&mt('Private key set to [_1]',$privkey).'</li>';
1.169 raeburn 12616: }
12617: $chgtxt .= '</ul>';
12618: $resulttext .= '<li>'.$chgtxt.'</li>';
12619: }
1.269 raeburn 12620: } elsif ($item eq 'recaptchaversion') {
12621: if (ref($loginhash{'login'}) eq 'HASH') {
12622: if ($loginhash{'login'}{'captcha'} eq 'recaptcha') {
1.270 raeburn 12623: $resulttext .= '<li>'.&mt('ReCAPTCHA for helpdesk form set to version [_1]',$loginhash{'login'}{'recaptchaversion'}).
1.269 raeburn 12624: '</li>';
12625: }
12626: }
1.41 raeburn 12627: } else {
12628: $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';
12629: }
1.1 raeburn 12630: }
1.6 raeburn 12631: $resulttext .= $colchgtext.'</ul>';
1.1 raeburn 12632: } else {
12633: $resulttext = &mt('No changes made to log-in page settings');
12634: }
12635: } else {
1.11 albertel 12636: $resulttext = '<span class="LC_error">'.
12637: &mt('An error occurred: [_1]',$putresult).'</span>';
1.1 raeburn 12638: }
1.6 raeburn 12639: if ($errors) {
1.9 raeburn 12640: $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
1.6 raeburn 12641: $errors.'</ul>';
12642: }
12643: return $resulttext;
12644: }
12645:
1.256 raeburn 12646: sub check_exempt_addresses {
12647: my ($iplist) = @_;
12648: $iplist =~ s/^\s+//;
12649: $iplist =~ s/\s+$//;
12650: my @poss_ips = split(/\s*[,:]\s*/,$iplist);
12651: my (@okips,$new);
12652: foreach my $ip (@poss_ips) {
12653: if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
12654: if (($1 <= 255) && ($2 <= 255) && ($3 <= 255) && ($4 <= 255)) {
12655: push(@okips,$ip);
12656: }
12657: }
12658: }
12659: if (@okips > 0) {
12660: $new = join(',',@okips);
12661: } else {
12662: $new = '';
12663: }
12664: return $new;
12665: }
12666:
1.6 raeburn 12667: sub color_font_choices {
12668: my %choices =
12669: &Apache::lonlocal::texthash (
12670: img => "Header",
12671: bgs => "Background colors",
12672: links => "Link colors",
1.55 raeburn 12673: images => "Images",
1.6 raeburn 12674: font => "Font color",
1.201 raeburn 12675: fontmenu => "Font menu",
1.76 raeburn 12676: pgbg => "Page",
1.6 raeburn 12677: tabbg => "Header",
12678: sidebg => "Border",
12679: link => "Link",
12680: alink => "Active link",
12681: vlink => "Visited link",
12682: );
12683: return %choices;
12684: }
12685:
1.394 raeburn 12686: sub modify_ipaccess {
12687: my ($dom,$lastactref,%domconfig) = @_;
12688: my (@allpos,%changes,%confhash,$errors,$resulttext);
12689: my (@items,%deletions,%itemids,@warnings);
12690: my ($typeorder,$types) = &commblocktype_text();
12691: if ($env{'form.ipaccess_add'}) {
12692: my $name = $env{'form.ipaccess_name_add'};
12693: my ($newid,$error) = &get_ipaccess_id($dom,$name);
12694: if ($newid) {
12695: $itemids{'add'} = $newid;
12696: push(@items,'add');
12697: $changes{$newid} = 1;
12698: } else {
12699: $error = &mt('Failed to acquire unique ID for new IP access control item');
12700: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
12701: }
12702: }
12703: if (ref($domconfig{'ipaccess'}) eq 'HASH') {
12704: my @todelete = &Apache::loncommon::get_env_multiple('form.ipaccess_del');
12705: if (@todelete) {
12706: map { $deletions{$_} = 1; } @todelete;
12707: }
12708: my $maxnum = $env{'form.ipaccess_maxnum'};
12709: for (my $i=0; $i<$maxnum; $i++) {
12710: my $itemid = $env{'form.ipaccess_id_'.$i};
12711: $itemid =~ s/\D+//g;
12712: if (ref($domconfig{'ipaccess'}{$itemid}) eq 'HASH') {
12713: if ($deletions{$itemid}) {
12714: $changes{$itemid} = $domconfig{'ipaccess'}{$itemid}{'name'};
12715: } else {
12716: push(@items,$i);
12717: $itemids{$i} = $itemid;
12718: }
12719: }
12720: }
12721: }
12722: foreach my $idx (@items) {
12723: my $itemid = $itemids{$idx};
12724: next unless ($itemid);
12725: my %current;
12726: unless ($idx eq 'add') {
12727: if (ref($domconfig{'ipaccess'}{$itemid}) eq 'HASH') {
12728: %current = %{$domconfig{'ipaccess'}{$itemid}};
12729: }
12730: }
12731: my $position = $env{'form.ipaccess_pos_'.$itemid};
12732: $position =~ s/\D+//g;
12733: if ($position ne '') {
12734: $allpos[$position] = $itemid;
12735: }
12736: my $name = $env{'form.ipaccess_name_'.$idx};
12737: $name =~ s/^\s+|\s+$//g;
12738: $confhash{$itemid}{'name'} = $name;
12739: my $possrange = $env{'form.ipaccess_range_'.$idx};
12740: $possrange =~ s/^\s+|\s+$//g;
12741: unless ($possrange eq '') {
12742: $possrange =~ s/[\r\n]+/\s/g;
12743: $possrange =~ s/\s*-\s*/-/g;
12744: $possrange =~ s/\s+/,/g;
12745: $possrange =~ s/,+/,/g;
12746: if ($possrange ne '') {
12747: my (@ok,$count);
1.425 raeburn 12748: $count = 0;
1.394 raeburn 12749: foreach my $poss (split(/\,/,$possrange)) {
12750: $count ++;
12751: $poss = &validate_ip_pattern($poss);
12752: if ($poss ne '') {
12753: push(@ok,$poss);
12754: }
12755: }
12756: my $diff = $count - scalar(@ok);
12757: if ($diff) {
12758: $errors .= '<li><span class="LC_error">'.
12759: &mt('[quant,_1,IP] invalid and excluded from saved value for IP range(s) for [_2]',
12760: $diff,$name).
12761: '</span></li>';
12762: }
12763: if (@ok) {
12764: my @cidr_list;
12765: foreach my $item (@ok) {
12766: @cidr_list = &Net::CIDR::cidradd($item,@cidr_list);
12767: }
12768: $confhash{$itemid}{'ip'} = join(',',@cidr_list);
12769: }
12770: }
12771: }
12772: foreach my $field ('name','ip') {
12773: unless (($idx eq 'add') || ($changes{$itemid})) {
12774: if ($current{$field} ne $confhash{$itemid}{$field}) {
12775: $changes{$itemid} = 1;
12776: last;
12777: }
12778: }
12779: }
12780: $confhash{$itemid}{'commblocks'} = {};
1.425 raeburn 12781:
1.394 raeburn 12782: my %commblocks;
1.425 raeburn 12783: map { $commblocks{$_} = 1; } &Apache::loncommon::get_env_multiple('form.ipaccess_block_'.$idx);
1.394 raeburn 12784: foreach my $type (@{$typeorder}) {
12785: if ($commblocks{$type}) {
12786: $confhash{$itemid}{'commblocks'}{$type} = 'on';
12787: }
12788: unless (($idx eq 'add') || ($changes{$itemid})) {
12789: if (ref($current{'commblocks'}) eq 'HASH') {
12790: if ($confhash{$itemid}{'commblocks'}{$type} ne $current{'commblocks'}{$type}) {
12791: $changes{$itemid} = 1;
12792: }
12793: } elsif ($confhash{$itemid}{'commblocks'}{$type}) {
12794: $changes{$itemid} = 1;
12795: }
12796: }
12797: }
12798: $confhash{$itemid}{'courses'} = {};
12799: my %crsdeletions;
12800: my @delcrs = &Apache::loncommon::get_env_multiple('form.ipaccess_course_delete_'.$idx);
12801: if (@delcrs) {
12802: map { $crsdeletions{$_} = 1; } @delcrs;
12803: }
12804: if (ref($current{'courses'}) eq 'HASH') {
12805: foreach my $cid (sort(keys(%{$current{'courses'}}))) {
12806: if ($crsdeletions{$cid}) {
12807: $changes{$itemid} = 1;
12808: } else {
12809: $confhash{$itemid}{'courses'}{$cid} = 1;
12810: }
12811: }
12812: }
12813: $env{'form.ipaccess_cnum_'.$idx} =~ s/^\s+|\s+$//g;
12814: $env{'form.ipaccess_cdom_'.$idx} =~ s/^\s+|\s+$//g;
1.425 raeburn 12815: if (($env{'form.ipaccess_cnum_'.$idx} =~ /^$match_courseid$/) &&
1.394 raeburn 12816: ($env{'form.ipaccess_cdom_'.$idx} =~ /^$match_domain$/)) {
12817: if (&Apache::lonnet::homeserver($env{'form.ipaccess_cnum_'.$idx},
12818: $env{'form.ipaccess_cdom_'.$idx}) eq 'no_host') {
12819: $errors .= '<li><span class="LC_error">'.
12820: &mt('Invalid courseID [_1] omitted from list of allowed courses',
12821: $env{'form.ipaccess_cdom_'.$idx}.'_'.$env{'form.ipaccess_cnum_'.$idx}).
12822: '</span></li>';
12823: } else {
12824: $confhash{$itemid}{'courses'}{$env{'form.ipaccess_cdom_'.$idx}.'_'.$env{'form.ipaccess_cnum_'.$idx}} = 1;
12825: $changes{$itemid} = 1;
12826: }
12827: }
12828: }
12829: if (@allpos > 0) {
12830: my $idx = 0;
12831: foreach my $itemid (@allpos) {
12832: if ($itemid ne '') {
12833: $confhash{$itemid}{'order'} = $idx;
12834: unless ($changes{$itemid}) {
12835: if (ref($domconfig{'ipaccess'}) eq 'HASH') {
12836: if (ref($domconfig{'ipaccess'}{$itemid}) eq 'HASH') {
12837: if ($domconfig{'ipaccess'}{$itemid}{'order'} ne $idx) {
12838: $changes{$itemid} = 1;
12839: }
12840: }
12841: }
12842: }
12843: $idx ++;
12844: }
12845: }
12846: }
12847: if (keys(%changes)) {
12848: my %defaultshash = (
12849: ipaccess => \%confhash,
12850: );
12851: my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
12852: $dom);
12853: if ($putresult eq 'ok') {
12854: my $cachetime = 1800;
12855: &Apache::lonnet::do_cache_new('ipaccess',$dom,\%confhash,$cachetime);
12856: if (ref($lastactref) eq 'HASH') {
12857: $lastactref->{'ipaccess'} = 1;
12858: }
12859: $resulttext = &mt('Changes made:').'<ul>';
12860: my %bynum;
12861: foreach my $itemid (sort(keys(%changes))) {
12862: if (ref($confhash{$itemid}) eq 'HASH') {
12863: my $position = $confhash{$itemid}{'order'};
12864: if ($position =~ /^\d+$/) {
12865: $bynum{$position} = $itemid;
12866: }
12867: }
12868: }
12869: if (keys(%deletions)) {
12870: foreach my $itemid (sort { $a <=> $b } keys(%deletions)) {
12871: $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
12872: }
12873: }
12874: foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
12875: my $itemid = $bynum{$pos};
12876: if (ref($confhash{$itemid}) eq 'HASH') {
12877: $resulttext .= '<li><b>'.$confhash{$itemid}{'name'}.'</b><ul>';
12878: my $position = $pos + 1;
12879: $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
12880: if ($confhash{$itemid}{'ip'} eq '') {
12881: $resulttext .= '<li>'.&mt('No IP Range(s) set').'</li>';
12882: } else {
12883: $resulttext .= '<li>'.&mt('IP Range(s): [_1]',$confhash{$itemid}{'ip'}).'</li>';
12884: }
12885: if (keys(%{$confhash{$itemid}{'commblocks'}})) {
12886: $resulttext .= '<li>'.&mt('Functionality Blocked: [_1]',
12887: join(', ', map { $types->{$_}; } sort(keys(%{$confhash{$itemid}{'commblocks'}})))).
12888: '</li>';
12889: } else {
12890: $resulttext .= '<li>'.&mt('No functionality blocked').'</li>';
12891: }
12892: if (keys(%{$confhash{$itemid}{'courses'}})) {
12893: my @courses;
12894: foreach my $cid (sort(keys(%{$confhash{$itemid}{'courses'}}))) {
1.425 raeburn 12895: my %courseinfo = &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
1.394 raeburn 12896: push(@courses,$courseinfo{'description'}.' ('.$cid.')');
12897: }
12898: $resulttext .= '<li>'.&mt('Courses/Communities allowed').':<ul><li>'.
12899: join('</li><li>',@courses).'</li></ul>';
12900: } else {
12901: $resulttext .= '<li>'.&mt('No courses allowed').'</li>';
12902: }
1.395 raeburn 12903: $resulttext .= '</ul></li>';
1.394 raeburn 12904: }
12905: }
1.395 raeburn 12906: $resulttext .= '</ul>';
1.394 raeburn 12907: } else {
12908: $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';
12909: }
12910: } else {
12911: $resulttext = &mt('No changes made');
12912: }
12913: if ($errors) {
12914: $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.
12915: $errors.'</ul></p>';
12916: }
12917: return $resulttext;
12918: }
12919:
12920: sub get_ipaccess_id {
12921: my ($domain,$location) = @_;
12922: # get lock on ipaccess db
12923: my $lockhash = {
12924: lock => $env{'user.name'}.
12925: ':'.$env{'user.domain'},
12926: };
12927: my $tries = 0;
12928: my $gotlock = &Apache::lonnet::newput_dom('ipaccess',$lockhash,$domain);
12929: my ($id,$error);
12930:
12931: while (($gotlock ne 'ok') && ($tries<10)) {
12932: $tries ++;
12933: sleep (0.1);
12934: $gotlock = &Apache::lonnet::newput_dom('ipaccess',$lockhash,$domain);
12935: }
12936: if ($gotlock eq 'ok') {
12937: my %currids = &Apache::lonnet::dump_dom('ipaccess',$domain);
12938: if ($currids{'lock'}) {
12939: delete($currids{'lock'});
12940: if (keys(%currids)) {
12941: my @curr = sort { $a <=> $b } keys(%currids);
12942: if ($curr[-1] =~ /^\d+$/) {
12943: $id = 1 + $curr[-1];
12944: }
12945: } else {
12946: $id = 1;
12947: }
12948: if ($id) {
12949: unless (&Apache::lonnet::newput_dom('ipaccess',{ $id => $location },$domain) eq 'ok') {
12950: $error = 'nostore';
12951: }
12952: } else {
12953: $error = 'nonumber';
12954: }
12955: }
12956: my $dellockoutcome = &Apache::lonnet::del_dom('ipaccess',['lock'],$domain);
12957: } else {
12958: $error = 'nolock';
12959: }
12960: return ($id,$error);
12961: }
12962:
1.6 raeburn 12963: sub modify_rolecolors {
1.205 raeburn 12964: my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_;
1.6 raeburn 12965: my ($resulttext,%rolehash);
12966: $rolehash{'rolecolors'} = {};
1.55 raeburn 12967: if (ref($domconfig{'rolecolors'}) ne 'HASH') {
12968: if ($domconfig{'rolecolors'} eq '') {
12969: $domconfig{'rolecolors'} = {};
12970: }
12971: }
1.9 raeburn 12972: my ($errors,%changes) = &modify_colors($r,$dom,$confname,$roles,
1.6 raeburn 12973: $domconfig{'rolecolors'},$rolehash{'rolecolors'});
12974: my $putresult = &Apache::lonnet::put_dom('configuration',\%rolehash,
12975: $dom);
12976: if ($putresult eq 'ok') {
12977: if (keys(%changes) > 0) {
1.41 raeburn 12978: &Apache::loncommon::devalidate_domconfig_cache($dom);
1.212 raeburn 12979: if (ref($lastactref) eq 'HASH') {
12980: $lastactref->{'domainconfig'} = 1;
12981: }
1.6 raeburn 12982: $resulttext = &display_colorchgs($dom,\%changes,$roles,
12983: $rolehash{'rolecolors'});
12984: } else {
12985: $resulttext = &mt('No changes made to default color schemes');
12986: }
12987: } else {
1.11 albertel 12988: $resulttext = '<span class="LC_error">'.
12989: &mt('An error occurred: [_1]',$putresult).'</span>';
1.6 raeburn 12990: }
12991: if ($errors) {
12992: $resulttext .= &mt('The following errors occurred: ').'<ul>'.
12993: $errors.'</ul>';
12994: }
12995: return $resulttext;
12996: }
12997:
12998: sub modify_colors {
1.9 raeburn 12999: my ($r,$dom,$confname,$roles,$domconfig,$confhash) = @_;
1.12 raeburn 13000: my (%changes,%choices);
1.51 raeburn 13001: my @bgs;
1.6 raeburn 13002: my @links = ('link','alink','vlink');
1.41 raeburn 13003: my @logintext;
1.6 raeburn 13004: my @images;
13005: my $servadm = $r->dir_config('lonAdmEMail');
13006: my $errors;
1.200 raeburn 13007: my %defaults;
1.6 raeburn 13008: foreach my $role (@{$roles}) {
13009: if ($role eq 'login') {
1.12 raeburn 13010: %choices = &login_choices();
1.41 raeburn 13011: @logintext = ('textcol','bgcol');
1.12 raeburn 13012: } else {
13013: %choices = &color_font_choices();
13014: }
13015: if ($role eq 'login') {
1.41 raeburn 13016: @images = ('img','logo','domlogo','login');
1.51 raeburn 13017: @bgs = ('pgbg','mainbg','sidebg');
1.6 raeburn 13018: } else {
13019: @images = ('img');
1.200 raeburn 13020: @bgs = ('pgbg','tabbg','sidebg');
13021: }
13022: my %defaults = &role_defaults($role,\@bgs,\@links,\@images,\@logintext);
13023: unless ($env{'form.'.$role.'_font'} eq $defaults{'font'}) {
13024: $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};
13025: }
13026: if ($role eq 'login') {
13027: foreach my $item (@logintext) {
1.234 raeburn 13028: $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
13029: if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
13030: $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
13031: }
13032: unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'logintext'}{$item})) {
1.200 raeburn 13033: $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
13034: }
13035: }
13036: } else {
1.234 raeburn 13037: $env{'form.'.$role.'_fontmenu'} = lc($env{'form.'.$role.'_fontmenu'});
13038: if ($env{'form.'.$role.'_fontmenu'} =~ /^\w+/) {
13039: $env{'form.'.$role.'_fontmenu'} = '#'.$env{'form.'.$role.'_fontmenu'};
13040: }
13041: unless($env{'form.'.$role.'_fontmenu'} eq lc($defaults{'fontmenu'})) {
1.200 raeburn 13042: $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'};
13043: }
1.6 raeburn 13044: }
1.200 raeburn 13045: foreach my $item (@bgs) {
1.234 raeburn 13046: $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
13047: if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
13048: $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
13049: }
13050: unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'bgs'}{$item})) {
1.200 raeburn 13051: $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
13052: }
13053: }
13054: foreach my $item (@links) {
1.234 raeburn 13055: $env{'form.'.$role.'_'.$item} = lc($env{'form.'.$role.'_'.$item});
13056: if ($env{'form.'.$role.'_'.$item} =~ /^\w+/) {
13057: $env{'form.'.$role.'_'.$item} = '#'.$env{'form.'.$role.'_'.$item};
13058: }
13059: unless ($env{'form.'.$role.'_'.$item} eq lc($defaults{'links'}{$item})) {
1.200 raeburn 13060: $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
13061: }
1.6 raeburn 13062: }
1.46 raeburn 13063: my ($configuserok,$author_ok,$switchserver) =
13064: &config_check($dom,$confname,$servadm);
1.9 raeburn 13065: my ($width,$height) = &thumb_dimensions();
1.40 raeburn 13066: if (ref($domconfig->{$role}) ne 'HASH') {
13067: $domconfig->{$role} = {};
13068: }
1.8 raeburn 13069: foreach my $img (@images) {
1.402 raeburn 13070: if ($role eq 'login') {
13071: if (($img eq 'img') || ($img eq 'logo')) {
13072: if (defined($env{'form.login_showlogo_'.$img})) {
13073: $confhash->{$role}{'showlogo'}{$img} = 1;
13074: } else {
13075: $confhash->{$role}{'showlogo'}{$img} = 0;
13076: }
13077: }
13078: if ($env{'form.login_alt_'.$img} ne '') {
13079: $confhash->{$role}{'alttext'}{$img} = $env{'form.login_alt_'.$img};
1.70 raeburn 13080: }
1.402 raeburn 13081: }
1.18 albertel 13082: if ( ! $env{'form.'.$role.'_'.$img.'.filename'}
13083: && !defined($domconfig->{$role}{$img})
13084: && !$env{'form.'.$role.'_del_'.$img}
13085: && $env{'form.'.$role.'_import_'.$img}) {
13086: # import the old configured image from the .tab setting
13087: # if they haven't provided a new one
13088: $domconfig->{$role}{$img} =
13089: $env{'form.'.$role.'_import_'.$img};
13090: }
1.6 raeburn 13091: if ($env{'form.'.$role.'_'.$img.'.filename'} ne '') {
1.9 raeburn 13092: my $error;
1.6 raeburn 13093: if ($configuserok eq 'ok') {
1.9 raeburn 13094: if ($switchserver) {
1.12 raeburn 13095: $error = &mt("Upload of [_1] image for $role page(s) is not permitted to this server: [_2]",$choices{$img},$switchserver);
1.9 raeburn 13096: } else {
13097: if ($author_ok eq 'ok') {
1.421 raeburn 13098: my $modified = [];
1.9 raeburn 13099: my ($result,$logourl) =
1.421 raeburn 13100: &Apache::lonconfigsettings::publishlogo($r,'upload',$role.'_'.$img,
13101: $dom,$confname,$img,$width,$height,
13102: '',$modified);
1.9 raeburn 13103: if ($result eq 'ok') {
13104: $confhash->{$role}{$img} = $logourl;
1.12 raeburn 13105: $changes{$role}{'images'}{$img} = 1;
1.421 raeburn 13106: &update_modify_urls($r,$modified);
1.9 raeburn 13107: } else {
1.12 raeburn 13108: $error = &mt("Upload of [_1] image for $role page(s) failed because an error occurred publishing the file in RES space. Error was: [_2].",$choices{img},$result);
1.9 raeburn 13109: }
13110: } else {
1.46 raeburn 13111: $error = &mt("Upload of [_1] image for $role page(s) failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$author_ok);
1.6 raeburn 13112: }
13113: }
13114: } else {
1.46 raeburn 13115: $error = &mt("Upload of [_1] image for $role page(s) failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$configuserok);
1.9 raeburn 13116: }
13117: if ($error) {
1.8 raeburn 13118: &Apache::lonnet::logthis($error);
1.11 albertel 13119: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
1.8 raeburn 13120: }
13121: } elsif ($domconfig->{$role}{$img} ne '') {
1.9 raeburn 13122: if ($domconfig->{$role}{$img} !~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) {
13123: my $error;
13124: if ($configuserok eq 'ok') {
13125: # is confname an author?
13126: if ($switchserver eq '') {
13127: if ($author_ok eq 'ok') {
1.421 raeburn 13128: my $modified = [];
1.9 raeburn 13129: my ($result,$logourl) =
1.421 raeburn 13130: &Apache::lonconfigsettings::publishlogo($r,'copy',$domconfig->{$role}{$img},
13131: $dom,$confname,$img,$width,$height,
13132: '',$modified);
1.9 raeburn 13133: if ($result eq 'ok') {
13134: $confhash->{$role}{$img} = $logourl;
1.18 albertel 13135: $changes{$role}{'images'}{$img} = 1;
1.421 raeburn 13136: &update_modify_urls($r,$modified);
1.9 raeburn 13137: }
13138: }
13139: }
13140: }
1.6 raeburn 13141: }
13142: }
13143: }
13144: if (ref($domconfig) eq 'HASH') {
13145: if (ref($domconfig->{$role}) eq 'HASH') {
13146: foreach my $img (@images) {
13147: if ($domconfig->{$role}{$img} ne '') {
13148: if ($env{'form.'.$role.'_del_'.$img}) {
13149: $confhash->{$role}{$img} = '';
1.12 raeburn 13150: $changes{$role}{'images'}{$img} = 1;
1.6 raeburn 13151: } else {
1.9 raeburn 13152: if ($confhash->{$role}{$img} eq '') {
13153: $confhash->{$role}{$img} = $domconfig->{$role}{$img};
13154: }
1.6 raeburn 13155: }
13156: } else {
13157: if ($env{'form.'.$role.'_del_'.$img}) {
13158: $confhash->{$role}{$img} = '';
1.12 raeburn 13159: $changes{$role}{'images'}{$img} = 1;
1.6 raeburn 13160: }
13161: }
1.402 raeburn 13162: if ($role eq 'login') {
13163: if (($img eq 'logo') || ($img eq 'img')) {
13164: if (ref($domconfig->{'login'}{'showlogo'}) eq 'HASH') {
13165: if ($confhash->{$role}{'showlogo'}{$img} ne
13166: $domconfig->{$role}{'showlogo'}{$img}) {
13167: $changes{$role}{'showlogo'}{$img} = 1;
13168: }
13169: } else {
13170: if ($confhash->{$role}{'showlogo'}{$img} == 0) {
13171: $changes{$role}{'showlogo'}{$img} = 1;
13172: }
1.70 raeburn 13173: }
1.402 raeburn 13174: }
13175: if ($img ne 'login') {
13176: if (ref($domconfig->{$role}{'alttext'}) eq 'HASH') {
13177: if ($confhash->{$role}{'alttext'}{$img} ne
13178: $domconfig->{$role}{'alttext'}{$img}) {
13179: $changes{$role}{'alttext'}{$img} = 1;
13180: }
13181: } else {
13182: if ($confhash->{$role}{'alttext'}{$img} ne '') {
13183: $changes{$role}{'alttext'}{$img} = 1;
13184: }
1.70 raeburn 13185: }
13186: }
13187: }
13188: }
1.6 raeburn 13189: if ($domconfig->{$role}{'font'} ne '') {
13190: if ($confhash->{$role}{'font'} ne $domconfig->{$role}{'font'}) {
13191: $changes{$role}{'font'} = 1;
13192: }
13193: } else {
13194: if ($confhash->{$role}{'font'}) {
13195: $changes{$role}{'font'} = 1;
13196: }
13197: }
1.107 raeburn 13198: if ($role ne 'login') {
13199: if ($domconfig->{$role}{'fontmenu'} ne '') {
13200: if ($confhash->{$role}{'fontmenu'} ne $domconfig->{$role}{'fontmenu'}) {
13201: $changes{$role}{'fontmenu'} = 1;
13202: }
13203: } else {
13204: if ($confhash->{$role}{'fontmenu'}) {
13205: $changes{$role}{'fontmenu'} = 1;
13206: }
1.97 tempelho 13207: }
13208: }
1.6 raeburn 13209: foreach my $item (@bgs) {
13210: if ($domconfig->{$role}{$item} ne '') {
13211: if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
13212: $changes{$role}{'bgs'}{$item} = 1;
13213: }
13214: } else {
13215: if ($confhash->{$role}{$item}) {
13216: $changes{$role}{'bgs'}{$item} = 1;
13217: }
13218: }
13219: }
13220: foreach my $item (@links) {
13221: if ($domconfig->{$role}{$item} ne '') {
13222: if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
13223: $changes{$role}{'links'}{$item} = 1;
13224: }
13225: } else {
13226: if ($confhash->{$role}{$item}) {
13227: $changes{$role}{'links'}{$item} = 1;
13228: }
13229: }
13230: }
1.41 raeburn 13231: foreach my $item (@logintext) {
13232: if ($domconfig->{$role}{$item} ne '') {
13233: if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
13234: $changes{$role}{'logintext'}{$item} = 1;
13235: }
13236: } else {
13237: if ($confhash->{$role}{$item}) {
13238: $changes{$role}{'logintext'}{$item} = 1;
13239: }
13240: }
13241: }
1.6 raeburn 13242: } else {
13243: &default_change_checker($role,\@images,\@links,\@bgs,
1.41 raeburn 13244: \@logintext,$confhash,\%changes);
1.6 raeburn 13245: }
13246: } else {
13247: &default_change_checker($role,\@images,\@links,\@bgs,
1.41 raeburn 13248: \@logintext,$confhash,\%changes);
1.6 raeburn 13249: }
13250: }
13251: return ($errors,%changes);
13252: }
13253:
1.46 raeburn 13254: sub config_check {
13255: my ($dom,$confname,$servadm) = @_;
13256: my ($configuserok,$author_ok,$switchserver,%currroles);
13257: my $uhome = &Apache::lonnet::homeserver($confname,$dom,1);
13258: ($configuserok,%currroles) = &check_configuser($uhome,$dom,
13259: $confname,$servadm);
13260: if ($configuserok eq 'ok') {
13261: $switchserver = &check_switchserver($dom,$confname);
13262: if ($switchserver eq '') {
13263: $author_ok = &check_authorstatus($dom,$confname,%currroles);
13264: }
13265: }
13266: return ($configuserok,$author_ok,$switchserver);
13267: }
13268:
1.6 raeburn 13269: sub default_change_checker {
1.41 raeburn 13270: my ($role,$images,$links,$bgs,$logintext,$confhash,$changes) = @_;
1.6 raeburn 13271: foreach my $item (@{$links}) {
13272: if ($confhash->{$role}{$item}) {
13273: $changes->{$role}{'links'}{$item} = 1;
13274: }
13275: }
13276: foreach my $item (@{$bgs}) {
13277: if ($confhash->{$role}{$item}) {
13278: $changes->{$role}{'bgs'}{$item} = 1;
13279: }
13280: }
1.41 raeburn 13281: foreach my $item (@{$logintext}) {
13282: if ($confhash->{$role}{$item}) {
13283: $changes->{$role}{'logintext'}{$item} = 1;
13284: }
13285: }
1.6 raeburn 13286: foreach my $img (@{$images}) {
13287: if ($env{'form.'.$role.'_del_'.$img}) {
13288: $confhash->{$role}{$img} = '';
1.12 raeburn 13289: $changes->{$role}{'images'}{$img} = 1;
1.6 raeburn 13290: }
1.70 raeburn 13291: if ($role eq 'login') {
13292: if ($confhash->{$role}{'showlogo'}{$img} == 0) {
13293: $changes->{$role}{'showlogo'}{$img} = 1;
13294: }
1.402 raeburn 13295: if (ref($confhash->{$role}{'alttext'}) eq 'HASH') {
13296: if ($confhash->{$role}{'alttext'}{$img} ne '') {
13297: $changes->{$role}{'alttext'}{$img} = 1;
13298: }
13299: }
1.70 raeburn 13300: }
1.6 raeburn 13301: }
13302: if ($confhash->{$role}{'font'}) {
13303: $changes->{$role}{'font'} = 1;
13304: }
1.48 raeburn 13305: }
1.6 raeburn 13306:
13307: sub display_colorchgs {
13308: my ($dom,$changes,$roles,$confhash) = @_;
13309: my (%choices,$resulttext);
13310: if (!grep(/^login$/,@{$roles})) {
13311: $resulttext = &mt('Changes made:').'<br />';
13312: }
13313: foreach my $role (@{$roles}) {
13314: if ($role eq 'login') {
13315: %choices = &login_choices();
13316: } else {
13317: %choices = &color_font_choices();
13318: }
13319: if (ref($changes->{$role}) eq 'HASH') {
13320: if ($role ne 'login') {
13321: $resulttext .= '<h4>'.&mt($role).'</h4>';
13322: }
13323: foreach my $key (sort(keys(%{$changes->{$role}}))) {
13324: if ($role ne 'login') {
13325: $resulttext .= '<ul>';
13326: }
13327: if (ref($changes->{$role}{$key}) eq 'HASH') {
13328: if ($role ne 'login') {
13329: $resulttext .= '<li>'.&mt($choices{$key}).':<ul>';
13330: }
13331: foreach my $item (sort(keys(%{$changes->{$role}{$key}}))) {
1.70 raeburn 13332: if (($role eq 'login') && ($key eq 'showlogo')) {
13333: if ($confhash->{$role}{$key}{$item}) {
13334: $resulttext .= '<li>'.&mt("$choices{$item} set to be displayed").'</li>';
13335: } else {
13336: $resulttext .= '<li>'.&mt("$choices{$item} set to not be displayed").'</li>';
13337: }
1.402 raeburn 13338: } elsif (($role eq 'login') && ($key eq 'alttext')) {
13339: if ($confhash->{$role}{$key}{$item} ne '') {
1.403 raeburn 13340: $resulttext .= '<li>'.&mt("$choices{$key} for $choices{$item} set to [_1].",
1.402 raeburn 13341: $confhash->{$role}{$key}{$item}).'</li>';
13342: } else {
13343: $resulttext .= '<li>'.&mt("$choices{$key} for $choices{$item} deleted.").'</li>';
13344: }
1.70 raeburn 13345: } elsif ($confhash->{$role}{$item} eq '') {
1.6 raeburn 13346: $resulttext .= '<li>'.&mt("$choices{$item} set to default").'</li>';
13347: } else {
1.12 raeburn 13348: my $newitem = $confhash->{$role}{$item};
13349: if ($key eq 'images') {
1.306 raeburn 13350: $newitem = '<img src="'.$confhash->{$role}{$item}.'" alt="'.$choices{$item}.'" style="vertical-align: bottom" />';
1.12 raeburn 13351: }
13352: $resulttext .= '<li>'.&mt("$choices{$item} set to [_1]",$newitem).'</li>';
1.6 raeburn 13353: }
13354: }
13355: if ($role ne 'login') {
13356: $resulttext .= '</ul></li>';
13357: }
13358: } else {
13359: if ($confhash->{$role}{$key} eq '') {
13360: $resulttext .= '<li>'.&mt("$choices{$key} set to default").'</li>';
13361: } else {
13362: $resulttext .= '<li>'.&mt("$choices{$key} set to [_1]",$confhash->{$role}{$key}).'</li>';
13363: }
13364: }
13365: if ($role ne 'login') {
13366: $resulttext .= '</ul>';
13367: }
13368: }
13369: }
13370: }
1.3 raeburn 13371: return $resulttext;
1.1 raeburn 13372: }
13373:
1.9 raeburn 13374: sub thumb_dimensions {
13375: return ('200','50');
13376: }
13377:
1.16 raeburn 13378: sub check_dimensions {
13379: my ($inputfile) = @_;
13380: my ($fullwidth,$fullheight);
13381: if ($inputfile =~ m|^[/\w.\-]+$|) {
13382: if (open(PIPE,"identify $inputfile 2>&1 |")) {
13383: my $imageinfo = <PIPE>;
13384: if (!close(PIPE)) {
13385: &Apache::lonnet::logthis("Failed to close PIPE opened to retrieve image information for $inputfile");
13386: }
13387: chomp($imageinfo);
13388: my ($fullsize) =
1.21 raeburn 13389: ($imageinfo =~ /^\Q$inputfile\E\s+\w+\s+(\d+x\d+)/);
1.16 raeburn 13390: if ($fullsize) {
13391: ($fullwidth,$fullheight) = split(/x/,$fullsize);
13392: }
13393: }
13394: }
13395: return ($fullwidth,$fullheight);
13396: }
13397:
1.9 raeburn 13398: sub check_configuser {
13399: my ($uhome,$dom,$confname,$servadm) = @_;
13400: my ($configuserok,%currroles);
13401: if ($uhome eq 'no_host') {
13402: srand( time() ^ ($$ + ($$ << 15)) ); # Seed rand.
1.361 raeburn 13403: my $configpass = &LONCAPA::Enrollment::create_password($dom);
1.9 raeburn 13404: $configuserok =
13405: &Apache::lonnet::modifyuser($dom,$confname,'','internal',
13406: $configpass,'','','','','',undef,$servadm);
13407: } else {
13408: $configuserok = 'ok';
13409: %currroles =
13410: &Apache::lonnet::get_my_roles($confname,$dom,'userroles');
13411: }
13412: return ($configuserok,%currroles);
13413: }
13414:
13415: sub check_authorstatus {
13416: my ($dom,$confname,%currroles) = @_;
13417: my $author_ok;
1.40 raeburn 13418: if (!$currroles{':'.$dom.':au'}) {
1.9 raeburn 13419: my $start = time;
13420: my $end = 0;
13421: $author_ok =
13422: &Apache::lonnet::assignrole($dom,$confname,'/'.$dom.'/',
1.47 raeburn 13423: 'au',$end,$start,'','','domconfig');
1.9 raeburn 13424: } else {
13425: $author_ok = 'ok';
13426: }
13427: return $author_ok;
13428: }
13429:
1.421 raeburn 13430: sub update_modify_urls {
13431: my ($r,$modified) = @_;
13432: if ((ref($modified) eq 'ARRAY') && (@{$modified})) {
13433: push(@{$modified_urls},$modified);
13434: unless ($registered_cleanup) {
13435: my $handlers = $r->get_handlers('PerlCleanupHandler');
13436: $r->set_handlers('PerlCleanupHandler' => [\¬ifysubscribed,@{$handlers}]);
13437: $registered_cleanup=1;
1.9 raeburn 13438: }
13439: }
1.155 raeburn 13440: }
13441:
13442: sub notifysubscribed {
13443: foreach my $targetsource (@{$modified_urls}){
13444: next unless (ref($targetsource) eq 'ARRAY');
13445: my ($target,$source)=@{$targetsource};
13446: if ($source ne '') {
1.316 raeburn 13447: if (open(my $logfh,">>",$source.'.log')) {
1.155 raeburn 13448: print $logfh "\nCleanup phase: Notifications\n";
13449: my @subscribed=&subscribed_hosts($target);
13450: foreach my $subhost (@subscribed) {
13451: print $logfh "\nNotifying host ".$subhost.':';
13452: my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
13453: print $logfh $reply;
13454: }
13455: my @subscribedmeta=&subscribed_hosts("$target.meta");
13456: foreach my $subhost (@subscribedmeta) {
13457: print $logfh "\nNotifying host for metadata only ".$subhost.':';
13458: my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
13459: $subhost);
13460: print $logfh $reply;
13461: }
13462: print $logfh "\n============ Done ============\n";
1.160 raeburn 13463: close($logfh);
1.155 raeburn 13464: }
13465: }
13466: }
13467: return OK;
13468: }
13469:
13470: sub subscribed_hosts {
13471: my ($target) = @_;
13472: my @subscribed;
1.316 raeburn 13473: if (open(my $fh,"<","$target.subscription")) {
1.155 raeburn 13474: while (my $subline=<$fh>) {
13475: if ($subline =~ /^($match_lonid):/) {
13476: my $host = $1;
13477: if ($host ne $Apache::lonnet::perlvar{'lonHostID'}) {
13478: unless (grep(/^\Q$host\E$/,@subscribed)) {
13479: push(@subscribed,$host);
13480: }
13481: }
13482: }
13483: }
13484: }
13485: return @subscribed;
1.9 raeburn 13486: }
13487:
13488: sub check_switchserver {
13489: my ($dom,$confname) = @_;
1.424 raeburn 13490: my ($allowed,$switchserver,$home);
13491: if ($confname eq '') {
1.9 raeburn 13492: $home = &Apache::lonnet::domain($dom,'primary');
1.424 raeburn 13493: } else {
13494: $home = &Apache::lonnet::homeserver($confname,$dom);
13495: if ($home eq 'no_host') {
13496: $home = &Apache::lonnet::domain($dom,'primary');
13497: }
1.9 raeburn 13498: }
13499: my @ids=&Apache::lonnet::current_machine_ids();
1.10 albertel 13500: foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
13501: if (!$allowed) {
1.426 raeburn 13502: $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&role='.
13503: &HTML::Entities::encode($env{'request.role'},'\'<>"&').
13504: '&destinationurl=/adm/domainprefs">'.&mt('Switch Server').'</a>';
1.9 raeburn 13505: }
13506: return $switchserver;
13507: }
13508:
1.1 raeburn 13509: sub modify_quotas {
1.216 raeburn 13510: my ($r,$dom,$action,$lastactref,%domconfig) = @_;
1.101 raeburn 13511: my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash,
1.216 raeburn 13512: %limithash,$toolregexp,%conditions,$resulttext,%changes,$confname,$configuserok,
1.235 raeburn 13513: $author_ok,$switchserver,$errors,$validationitemsref,$validationnamesref,
13514: $validationfieldsref);
1.86 raeburn 13515: if ($action eq 'quotas') {
13516: $context = 'tools';
1.163 raeburn 13517: } else {
1.86 raeburn 13518: $context = $action;
13519: }
13520: if ($context eq 'requestcourses') {
1.325 raeburn 13521: @usertools = ('official','unofficial','community','textbook','placement','lti');
1.106 raeburn 13522: @options =('norequest','approval','validate','autolimit');
1.101 raeburn 13523: %validations = &Apache::lonnet::auto_courserequest_checks($dom);
13524: %titles = &courserequest_titles();
13525: $toolregexp = join('|',@usertools);
13526: %conditions = &courserequest_conditions();
1.216 raeburn 13527: $confname = $dom.'-domainconfig';
13528: my $servadm = $r->dir_config('lonAdmEMail');
13529: ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
1.235 raeburn 13530: ($validationitemsref,$validationnamesref,$validationfieldsref) =
13531: &Apache::loncoursequeueadmin::requestcourses_validation_types();
1.163 raeburn 13532: } elsif ($context eq 'requestauthor') {
13533: @usertools = ('author');
13534: %titles = &authorrequest_titles();
1.86 raeburn 13535: } else {
1.413 raeburn 13536: @usertools = ('aboutme','blog','webdav','portfolio','timezone');
1.101 raeburn 13537: %titles = &tool_titles();
1.86 raeburn 13538: }
1.212 raeburn 13539: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
1.44 raeburn 13540: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.1 raeburn 13541: foreach my $key (keys(%env)) {
1.101 raeburn 13542: if ($context eq 'requestcourses') {
13543: if ($key =~ /^form\.crsreq_($toolregexp)_(.+)$/) {
13544: my $item = $1;
13545: my $type = $2;
13546: if ($type =~ /^limit_(.+)/) {
13547: $limithash{$item}{$1} = $env{$key};
13548: } else {
13549: $confhash{$item}{$type} = $env{$key};
13550: }
13551: }
1.163 raeburn 13552: } elsif ($context eq 'requestauthor') {
13553: if ($key =~ /^\Qform.authorreq_\E(.+)$/) {
13554: $confhash{$1} = $env{$key};
13555: }
1.101 raeburn 13556: } else {
1.86 raeburn 13557: if ($key =~ /^form\.quota_(.+)$/) {
13558: $confhash{'defaultquota'}{$1} = $env{$key};
1.197 raeburn 13559: } elsif ($key =~ /^form\.authorquota_(.+)$/) {
13560: $confhash{'authorquota'}{$1} = $env{$key};
13561: } elsif ($key =~ /^form\.\Q$context\E_(.+)$/) {
1.101 raeburn 13562: @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key);
13563: }
1.72 raeburn 13564: }
13565: }
1.163 raeburn 13566: if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
1.224 raeburn 13567: my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
1.102 raeburn 13568: @approvalnotify = sort(@approvalnotify);
13569: $confhash{'notify'}{'approval'} = join(',',@approvalnotify);
1.325 raeburn 13570: my @crstypes = ('official','unofficial','community','textbook','placement','lti');
1.218 raeburn 13571: my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
13572: foreach my $type (@hasuniquecode) {
13573: if (grep(/^\Q$type\E$/,@crstypes)) {
13574: $confhash{'uniquecode'}{$type} = 1;
13575: }
1.216 raeburn 13576: }
1.242 raeburn 13577: my (%newbook,%allpos);
1.216 raeburn 13578: if ($context eq 'requestcourses') {
1.242 raeburn 13579: foreach my $type ('textbooks','templates') {
13580: @{$allpos{$type}} = ();
13581: my $invalid;
13582: if ($type eq 'textbooks') {
13583: $invalid = &mt('Invalid LON-CAPA course for textbook');
13584: } else {
13585: $invalid = &mt('Invalid LON-CAPA course for template');
13586: }
13587: if ($env{'form.'.$type.'_addbook'}) {
13588: if (($env{'form.'.$type.'_addbook_cnum'} =~ /^$match_courseid$/) &&
13589: ($env{'form.'.$type.'_addbook_cdom'} =~ /^$match_domain$/)) {
13590: if (&Apache::lonnet::homeserver($env{'form.'.$type.'_addbook_cnum'},
13591: $env{'form.'.$type.'_addbook_cdom'}) eq 'no_host') {
13592: $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
13593: } else {
13594: $newbook{$type} = $env{'form.'.$type.'_addbook_cdom'}.'_'.$env{'form.'.$type.'_addbook_cnum'};
13595: my $position = $env{'form.'.$type.'_addbook_pos'};
13596: $position =~ s/\D+//g;
13597: if ($position ne '') {
13598: $allpos{$type}[$position] = $newbook{$type};
13599: }
1.216 raeburn 13600: }
1.242 raeburn 13601: } else {
13602: $errors .= '<li><span class="LC_error">'.$invalid.'</span></li>';
1.216 raeburn 13603: }
13604: }
1.242 raeburn 13605: }
1.216 raeburn 13606: }
1.102 raeburn 13607: if (ref($domconfig{$action}) eq 'HASH') {
13608: if (ref($domconfig{$action}{'notify'}) eq 'HASH') {
13609: if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) {
13610: $changes{'notify'}{'approval'} = 1;
13611: }
13612: } else {
1.144 raeburn 13613: if ($confhash{'notify'}{'approval'}) {
1.102 raeburn 13614: $changes{'notify'}{'approval'} = 1;
13615: }
13616: }
1.218 raeburn 13617: if (ref($domconfig{$action}{'uniquecode'}) eq 'HASH') {
13618: if (ref($confhash{'uniquecode'}) eq 'HASH') {
13619: foreach my $crstype (keys(%{$domconfig{$action}{'uniquecode'}})) {
13620: unless ($confhash{'uniquecode'}{$crstype}) {
13621: $changes{'uniquecode'} = 1;
13622: }
13623: }
13624: unless ($changes{'uniquecode'}) {
13625: foreach my $crstype (keys(%{$confhash{'uniquecode'}})) {
13626: unless ($domconfig{$action}{'uniquecode'}{$crstype}) {
13627: $changes{'uniquecode'} = 1;
13628: }
13629: }
13630: }
13631: } else {
13632: $changes{'uniquecode'} = 1;
13633: }
13634: } elsif (ref($confhash{'uniquecode'}) eq 'HASH') {
13635: $changes{'uniquecode'} = 1;
1.216 raeburn 13636: }
13637: if ($context eq 'requestcourses') {
1.242 raeburn 13638: foreach my $type ('textbooks','templates') {
13639: if (ref($domconfig{$action}{$type}) eq 'HASH') {
13640: my %deletions;
13641: my @todelete = &Apache::loncommon::get_env_multiple('form.'.$type.'_del');
13642: if (@todelete) {
13643: map { $deletions{$_} = 1; } @todelete;
13644: }
13645: my %imgdeletions;
13646: my @todeleteimages = &Apache::loncommon::get_env_multiple('form.'.$type.'_image_del');
13647: if (@todeleteimages) {
13648: map { $imgdeletions{$_} = 1; } @todeleteimages;
13649: }
13650: my $maxnum = $env{'form.'.$type.'_maxnum'};
13651: for (my $i=0; $i<=$maxnum; $i++) {
13652: my $itemid = $env{'form.'.$type.'_id_'.$i};
13653: my ($key) = ($itemid =~ /^\Q$type\E_(\w+)$/);
13654: if (ref($domconfig{$action}{$type}{$key}) eq 'HASH') {
13655: if ($deletions{$key}) {
13656: if ($domconfig{$action}{$type}{$key}{'image'}) {
13657: #FIXME need to obsolete item in RES space
13658: }
13659: next;
13660: } else {
13661: my $newpos = $env{'form.'.$itemid};
13662: $newpos =~ s/\D+//g;
1.243 raeburn 13663: foreach my $item ('subject','title','publisher','author') {
1.289 raeburn 13664: next if ((($item eq 'author') || ($item eq 'publisher')) &&
1.243 raeburn 13665: ($type eq 'templates'));
1.242 raeburn 13666: $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i};
13667: if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) {
13668: $changes{$type}{$key} = 1;
13669: }
13670: }
13671: $allpos{$type}[$newpos] = $key;
13672: }
13673: if ($imgdeletions{$key}) {
13674: $changes{$type}{$key} = 1;
1.216 raeburn 13675: #FIXME need to obsolete item in RES space
1.242 raeburn 13676: } elsif ($env{'form.'.$type.'_image_'.$i.'.filename'}) {
13677: my ($cdom,$cnum) = split(/_/,$key);
1.313 raeburn 13678: if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {
13679: $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';
13680: } else {
13681: my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,$type.'_image_'.$i,
13682: $cdom,$cnum,$type,$configuserok,
13683: $switchserver,$author_ok);
13684: if ($imgurl) {
13685: $confhash{$type}{$key}{'image'} = $imgurl;
13686: $changes{$type}{$key} = 1;
13687: }
13688: if ($error) {
13689: &Apache::lonnet::logthis($error);
13690: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
13691: }
13692: }
1.242 raeburn 13693: } elsif ($domconfig{$action}{$type}{$key}{'image'}) {
13694: $confhash{$type}{$key}{'image'} =
13695: $domconfig{$action}{$type}{$key}{'image'};
1.216 raeburn 13696: }
13697: }
13698: }
13699: }
13700: }
13701: }
1.102 raeburn 13702: } else {
1.144 raeburn 13703: if ($confhash{'notify'}{'approval'}) {
1.102 raeburn 13704: $changes{'notify'}{'approval'} = 1;
13705: }
1.218 raeburn 13706: if (ref($confhash{'uniquecode'} eq 'HASH')) {
1.216 raeburn 13707: $changes{'uniquecode'} = 1;
13708: }
13709: }
13710: if ($context eq 'requestcourses') {
1.242 raeburn 13711: foreach my $type ('textbooks','templates') {
13712: if ($newbook{$type}) {
13713: $changes{$type}{$newbook{$type}} = 1;
1.243 raeburn 13714: foreach my $item ('subject','title','publisher','author') {
13715: next if ((($item eq 'author') || ($item eq 'publisher')) &&
13716: ($type eq 'template'));
1.242 raeburn 13717: $env{'form.'.$type.'_addbook_'.$item} =~ s/(`)/'/g;
13718: if ($env{'form.'.$type.'_addbook_'.$item}) {
13719: $confhash{$type}{$newbook{$type}}{$item} = $env{'form.'.$type.'_addbook_'.$item};
13720: }
13721: }
13722: if ($type eq 'textbooks') {
13723: if ($env{'form.'.$type.'_addbook_image.filename'} ne '') {
13724: my ($cdom,$cnum) = split(/_/,$newbook{$type});
1.313 raeburn 13725: if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {
13726: $errors .= '<li><span class="LC_error">'.&mt('Image not saved: could not find textbook course').'</li>';
13727: } else {
13728: my ($imageurl,$error) =
13729: &process_textbook_image($r,$dom,$confname,$type.'_addbook_image',$cdom,$cnum,$type,
13730: $configuserok,$switchserver,$author_ok);
13731: if ($imageurl) {
13732: $confhash{$type}{$newbook{$type}}{'image'} = $imageurl;
13733: }
13734: if ($error) {
13735: &Apache::lonnet::logthis($error);
13736: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
13737: }
1.242 raeburn 13738: }
13739: }
1.216 raeburn 13740: }
13741: }
1.242 raeburn 13742: if (@{$allpos{$type}} > 0) {
13743: my $idx = 0;
13744: foreach my $item (@{$allpos{$type}}) {
13745: if ($item ne '') {
13746: $confhash{$type}{$item}{'order'} = $idx;
13747: if (ref($domconfig{$action}) eq 'HASH') {
13748: if (ref($domconfig{$action}{$type}) eq 'HASH') {
13749: if (ref($domconfig{$action}{$type}{$item}) eq 'HASH') {
13750: if ($domconfig{$action}{$type}{$item}{'order'} ne $idx) {
13751: $changes{$type}{$item} = 1;
13752: }
1.216 raeburn 13753: }
13754: }
13755: }
1.242 raeburn 13756: $idx ++;
1.216 raeburn 13757: }
13758: }
13759: }
13760: }
1.235 raeburn 13761: if (ref($validationitemsref) eq 'ARRAY') {
13762: foreach my $item (@{$validationitemsref}) {
13763: if ($item eq 'fields') {
13764: my @changed;
13765: @{$confhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.requestcourses_validation_'.$item);
13766: if (@{$confhash{'validation'}{$item}} > 0) {
13767: @{$confhash{'validation'}{$item}} = sort(@{$confhash{'validation'}{$item}});
13768: }
1.266 raeburn 13769: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
13770: if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
13771: if (ref($domconfig{'requestcourses'}{'validation'}{$item}) eq 'ARRAY') {
13772: @changed = &Apache::loncommon::compare_arrays($confhash{'validation'}{$item},
13773: $domconfig{'requestcourses'}{'validation'}{$item});
13774: } else {
13775: @changed = @{$confhash{'validation'}{$item}};
13776: }
1.235 raeburn 13777: } else {
13778: @changed = @{$confhash{'validation'}{$item}};
13779: }
13780: } else {
13781: @changed = @{$confhash{'validation'}{$item}};
13782: }
13783: if (@changed) {
13784: if ($confhash{'validation'}{$item}) {
13785: $changes{'validation'}{$item} = join(', ',@{$confhash{'validation'}{$item}});
13786: } else {
13787: $changes{'validation'}{$item} = &mt('None');
13788: }
13789: }
13790: } else {
13791: $confhash{'validation'}{$item} = $env{'form.requestcourses_validation_'.$item};
13792: if ($item eq 'markup') {
13793: if ($env{'form.requestcourses_validation_'.$item}) {
13794: $env{'form.requestcourses_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;
13795: }
13796: }
1.266 raeburn 13797: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
13798: if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
13799: if ($domconfig{'requestcourses'}{'validation'}{$item} ne $confhash{'validation'}{$item}) {
13800: $changes{'validation'}{$item} = $confhash{'validation'}{$item};
13801: }
13802: } else {
13803: if ($confhash{'validation'}{$item} ne '') {
13804: $changes{'validation'}{$item} = $confhash{'validation'}{$item};
13805: }
1.235 raeburn 13806: }
13807: } else {
13808: if ($confhash{'validation'}{$item} ne '') {
13809: $changes{'validation'}{$item} = $confhash{'validation'}{$item};
13810: }
13811: }
13812: }
13813: }
13814: }
13815: if ($env{'form.validationdc'}) {
13816: my $newval = $env{'form.validationdc'};
1.285 raeburn 13817: my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
1.235 raeburn 13818: if (exists($domcoords{$newval})) {
13819: $confhash{'validation'}{'dc'} = $newval;
13820: }
13821: }
13822: if (ref($confhash{'validation'}) eq 'HASH') {
1.266 raeburn 13823: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
13824: if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
13825: if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
13826: unless ($confhash{'validation'}{'dc'} eq $domconfig{'requestcourses'}{'validation'}{'dc'}) {
13827: if ($confhash{'validation'}{'dc'} eq '') {
13828: $changes{'validation'}{'dc'} = &mt('None');
13829: } else {
13830: $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
13831: }
1.235 raeburn 13832: }
1.266 raeburn 13833: } elsif ($confhash{'validation'}{'dc'} ne '') {
13834: $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
1.235 raeburn 13835: }
13836: } elsif ($confhash{'validation'}{'dc'} ne '') {
13837: $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
13838: }
13839: } elsif ($confhash{'validation'}{'dc'} ne '') {
13840: $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'};
1.289 raeburn 13841: }
1.266 raeburn 13842: } else {
13843: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
13844: if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
13845: if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
13846: $changes{'validation'}{'dc'} = &mt('None');
13847: }
13848: }
1.235 raeburn 13849: }
13850: }
1.102 raeburn 13851: }
13852: } else {
1.86 raeburn 13853: $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'};
1.197 raeburn 13854: $confhash{'authorquota'}{'default'} = $env{'form.authorquota'};
1.86 raeburn 13855: }
1.72 raeburn 13856: foreach my $item (@usertools) {
13857: foreach my $type (@{$types},'default','_LC_adv') {
1.104 raeburn 13858: my $unset;
1.101 raeburn 13859: if ($context eq 'requestcourses') {
1.104 raeburn 13860: $unset = '0';
13861: if ($type eq '_LC_adv') {
13862: $unset = '';
13863: }
1.101 raeburn 13864: if ($confhash{$item}{$type} eq 'autolimit') {
13865: $confhash{$item}{$type} .= '=';
13866: unless ($limithash{$item}{$type} =~ /\D/) {
13867: $confhash{$item}{$type} .= $limithash{$item}{$type};
13868: }
13869: }
1.163 raeburn 13870: } elsif ($context eq 'requestauthor') {
13871: $unset = '0';
13872: if ($type eq '_LC_adv') {
13873: $unset = '';
13874: }
1.72 raeburn 13875: } else {
1.101 raeburn 13876: if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) {
13877: $confhash{$item}{$type} = 1;
13878: } else {
13879: $confhash{$item}{$type} = 0;
13880: }
1.72 raeburn 13881: }
1.86 raeburn 13882: if (ref($domconfig{$action}) eq 'HASH') {
1.163 raeburn 13883: if ($action eq 'requestauthor') {
13884: if ($domconfig{$action}{$type} ne $confhash{$type}) {
13885: $changes{$type} = 1;
13886: }
13887: } elsif (ref($domconfig{$action}{$item}) eq 'HASH') {
1.86 raeburn 13888: if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) {
13889: $changes{$item}{$type} = 1;
13890: }
13891: } else {
13892: if ($context eq 'requestcourses') {
1.104 raeburn 13893: if ($confhash{$item}{$type} ne $unset) {
1.86 raeburn 13894: $changes{$item}{$type} = 1;
13895: }
13896: } else {
13897: if (!$confhash{$item}{$type}) {
13898: $changes{$item}{$type} = 1;
13899: }
13900: }
13901: }
13902: } else {
13903: if ($context eq 'requestcourses') {
1.104 raeburn 13904: if ($confhash{$item}{$type} ne $unset) {
1.72 raeburn 13905: $changes{$item}{$type} = 1;
13906: }
1.163 raeburn 13907: } elsif ($context eq 'requestauthor') {
13908: if ($confhash{$type} ne $unset) {
13909: $changes{$type} = 1;
13910: }
1.72 raeburn 13911: } else {
13912: if (!$confhash{$item}{$type}) {
13913: $changes{$item}{$type} = 1;
13914: }
13915: }
13916: }
1.1 raeburn 13917: }
13918: }
1.163 raeburn 13919: unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
1.86 raeburn 13920: if (ref($domconfig{'quotas'}) eq 'HASH') {
13921: if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
13922: foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) {
13923: if (exists($confhash{'defaultquota'}{$key})) {
13924: if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{'defaultquota'}{$key}) {
13925: $changes{'defaultquota'}{$key} = 1;
13926: }
13927: } else {
13928: $confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{'defaultquota'}{$key};
1.72 raeburn 13929: }
13930: }
1.86 raeburn 13931: } else {
13932: foreach my $key (keys(%{$domconfig{'quotas'}})) {
13933: if (exists($confhash{'defaultquota'}{$key})) {
13934: if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{$key}) {
13935: $changes{'defaultquota'}{$key} = 1;
13936: }
13937: } else {
13938: $confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{$key};
1.72 raeburn 13939: }
1.1 raeburn 13940: }
13941: }
1.197 raeburn 13942: if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
13943: foreach my $key (keys(%{$domconfig{'quotas'}{'authorquota'}})) {
13944: if (exists($confhash{'authorquota'}{$key})) {
13945: if ($confhash{'authorquota'}{$key} ne $domconfig{'quotas'}{'authorquota'}{$key}) {
13946: $changes{'authorquota'}{$key} = 1;
13947: }
13948: } else {
13949: $confhash{'authorquota'}{$key} = $domconfig{'quotas'}{'authorquota'}{$key};
13950: }
13951: }
13952: }
1.1 raeburn 13953: }
1.86 raeburn 13954: if (ref($confhash{'defaultquota'}) eq 'HASH') {
13955: foreach my $key (keys(%{$confhash{'defaultquota'}})) {
13956: if (ref($domconfig{'quotas'}) eq 'HASH') {
13957: if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') {
13958: if (!exists($domconfig{'quotas'}{'defaultquota'}{$key})) {
13959: $changes{'defaultquota'}{$key} = 1;
13960: }
13961: } else {
13962: if (!exists($domconfig{'quotas'}{$key})) {
13963: $changes{'defaultquota'}{$key} = 1;
13964: }
1.72 raeburn 13965: }
13966: } else {
1.86 raeburn 13967: $changes{'defaultquota'}{$key} = 1;
1.55 raeburn 13968: }
1.1 raeburn 13969: }
13970: }
1.197 raeburn 13971: if (ref($confhash{'authorquota'}) eq 'HASH') {
13972: foreach my $key (keys(%{$confhash{'authorquota'}})) {
13973: if (ref($domconfig{'quotas'}) eq 'HASH') {
13974: if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') {
13975: if (!exists($domconfig{'quotas'}{'authorquota'}{$key})) {
13976: $changes{'authorquota'}{$key} = 1;
13977: }
13978: } else {
13979: $changes{'authorquota'}{$key} = 1;
13980: }
13981: } else {
13982: $changes{'authorquota'}{$key} = 1;
13983: }
13984: }
13985: }
1.1 raeburn 13986: }
1.72 raeburn 13987:
1.163 raeburn 13988: if ($context eq 'requestauthor') {
13989: $domdefaults{'requestauthor'} = \%confhash;
13990: } else {
13991: foreach my $key (keys(%confhash)) {
1.242 raeburn 13992: unless (($context eq 'requestcourses') && (($key eq 'textbooks') || ($key eq 'templates'))) {
1.216 raeburn 13993: $domdefaults{$key} = $confhash{$key};
13994: }
1.163 raeburn 13995: }
1.72 raeburn 13996: }
1.163 raeburn 13997:
1.1 raeburn 13998: my %quotahash = (
1.86 raeburn 13999: $action => { %confhash }
1.1 raeburn 14000: );
14001: my $putresult = &Apache::lonnet::put_dom('configuration',\%quotahash,
14002: $dom);
14003: if ($putresult eq 'ok') {
14004: if (keys(%changes) > 0) {
1.72 raeburn 14005: my $cachetime = 24*60*60;
14006: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
1.212 raeburn 14007: if (ref($lastactref) eq 'HASH') {
14008: $lastactref->{'domdefaults'} = 1;
14009: }
1.1 raeburn 14010: $resulttext = &mt('Changes made:').'<ul>';
1.210 raeburn 14011: unless (($context eq 'requestcourses') ||
1.163 raeburn 14012: ($context eq 'requestauthor')) {
1.86 raeburn 14013: if (ref($changes{'defaultquota'}) eq 'HASH') {
14014: $resulttext .= '<li>'.&mt('Portfolio default quotas').'<ul>';
14015: foreach my $type (@{$types},'default') {
14016: if (defined($changes{'defaultquota'}{$type})) {
14017: my $typetitle = $usertypes->{$type};
14018: if ($type eq 'default') {
14019: $typetitle = $othertitle;
14020: }
1.213 raeburn 14021: $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'defaultquota'}{$type}).'</li>';
1.72 raeburn 14022: }
14023: }
1.86 raeburn 14024: $resulttext .= '</ul></li>';
1.72 raeburn 14025: }
1.197 raeburn 14026: if (ref($changes{'authorquota'}) eq 'HASH') {
1.223 bisitz 14027: $resulttext .= '<li>'.&mt('Authoring Space default quotas').'<ul>';
1.197 raeburn 14028: foreach my $type (@{$types},'default') {
14029: if (defined($changes{'authorquota'}{$type})) {
14030: my $typetitle = $usertypes->{$type};
14031: if ($type eq 'default') {
14032: $typetitle = $othertitle;
14033: }
1.213 raeburn 14034: $resulttext .= '<li>'.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'authorquota'}{$type}).'</li>';
1.197 raeburn 14035: }
14036: }
14037: $resulttext .= '</ul></li>';
14038: }
1.72 raeburn 14039: }
1.80 raeburn 14040: my %newenv;
1.72 raeburn 14041: foreach my $item (@usertools) {
1.163 raeburn 14042: my (%haschgs,%inconf);
14043: if ($context eq 'requestauthor') {
14044: %haschgs = %changes;
1.210 raeburn 14045: %inconf = %confhash;
1.163 raeburn 14046: } else {
14047: if (ref($changes{$item}) eq 'HASH') {
14048: %haschgs = %{$changes{$item}};
14049: }
14050: if (ref($confhash{$item}) eq 'HASH') {
14051: %inconf = %{$confhash{$item}};
14052: }
14053: }
14054: if (keys(%haschgs) > 0) {
1.80 raeburn 14055: my $newacc =
14056: &Apache::lonnet::usertools_access($env{'user.name'},
14057: $env{'user.domain'},
1.86 raeburn 14058: $item,'reload',$context);
1.210 raeburn 14059: if (($context eq 'requestcourses') ||
1.163 raeburn 14060: ($context eq 'requestauthor')) {
1.108 raeburn 14061: if ($env{'environment.canrequest.'.$item} ne $newacc) {
14062: $newenv{'environment.canrequest.'.$item} = $newacc;
1.86 raeburn 14063: }
14064: } else {
14065: if ($env{'environment.availabletools.'.$item} ne $newacc) {
14066: $newenv{'environment.availabletools.'.$item} = $newacc;
14067: }
1.80 raeburn 14068: }
1.163 raeburn 14069: unless ($context eq 'requestauthor') {
14070: $resulttext .= '<li>'.$titles{$item}.'<ul>';
14071: }
1.72 raeburn 14072: foreach my $type (@{$types},'default','_LC_adv') {
1.163 raeburn 14073: if ($haschgs{$type}) {
1.72 raeburn 14074: my $typetitle = $usertypes->{$type};
14075: if ($type eq 'default') {
14076: $typetitle = $othertitle;
14077: } elsif ($type eq '_LC_adv') {
14078: $typetitle = 'LON-CAPA Advanced Users';
14079: }
1.163 raeburn 14080: if ($inconf{$type}) {
1.101 raeburn 14081: if ($context eq 'requestcourses') {
14082: my $cond;
1.163 raeburn 14083: if ($inconf{$type} =~ /^autolimit=(\d*)$/) {
1.101 raeburn 14084: if ($1 eq '') {
14085: $cond = &mt('(Automatic processing of any request).');
14086: } else {
14087: $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1);
14088: }
14089: } else {
1.163 raeburn 14090: $cond = $conditions{$inconf{$type}};
1.101 raeburn 14091: }
14092: $resulttext .= '<li>'.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'</li>';
1.172 raeburn 14093: } elsif ($context eq 'requestauthor') {
14094: $resulttext .= '<li>'.&mt('Set to "[_1]" for "[_2]".',
14095: $titles{$inconf{$type}},$typetitle);
14096:
1.101 raeburn 14097: } else {
14098: $resulttext .= '<li>'.&mt('Set to be available to [_1]',$typetitle).'</li>';
14099: }
1.72 raeburn 14100: } else {
1.104 raeburn 14101: if ($type eq '_LC_adv') {
1.163 raeburn 14102: if ($inconf{$type} eq '0') {
1.104 raeburn 14103: $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
14104: } else {
14105: $resulttext .= '<li>'.&mt('No override set for [_1]',$typetitle).'</li>';
14106: }
14107: } else {
14108: $resulttext .= '<li>'.&mt('Set to be unavailable to [_1]',$typetitle).'</li>';
14109: }
1.72 raeburn 14110: }
14111: }
1.26 raeburn 14112: }
1.163 raeburn 14113: unless ($context eq 'requestauthor') {
14114: $resulttext .= '</ul></li>';
14115: }
1.26 raeburn 14116: }
1.1 raeburn 14117: }
1.163 raeburn 14118: if (($action eq 'requestcourses') || ($action eq 'requestauthor')) {
1.102 raeburn 14119: if (ref($changes{'notify'}) eq 'HASH') {
14120: if ($changes{'notify'}{'approval'}) {
14121: if (ref($confhash{'notify'}) eq 'HASH') {
14122: if ($confhash{'notify'}{'approval'}) {
14123: $resulttext .= '<li>'.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'</li>';
14124: } else {
1.163 raeburn 14125: $resulttext .= '<li>'.&mt('No Domain Coordinators will receive notification of requests requiring approval.').'</li>';
1.102 raeburn 14126: }
14127: }
14128: }
14129: }
14130: }
1.216 raeburn 14131: if ($action eq 'requestcourses') {
14132: my @offon = ('off','on');
14133: if ($changes{'uniquecode'}) {
1.218 raeburn 14134: if (ref($confhash{'uniquecode'}) eq 'HASH') {
14135: my $codestr = join(' ',map{ &mt($_); } sort(keys(%{$confhash{'uniquecode'}})));
14136: $resulttext .= '<li>'.
14137: &mt('Generation of six character code as course identifier for distribution to students set to on for: [_1].','<b>'.$codestr.'</b>').
14138: '</li>';
14139: } else {
14140: $resulttext .= '<li>'.&mt('Generation of six character code as course identifier for distribution to students set to off.').
14141: '</li>';
14142: }
1.216 raeburn 14143: }
1.242 raeburn 14144: foreach my $type ('textbooks','templates') {
14145: if (ref($changes{$type}) eq 'HASH') {
14146: $resulttext .= '<li>'.&mt("Available $type updated").'<ul>';
14147: foreach my $key (sort(keys(%{$changes{$type}}))) {
14148: my %coursehash = &Apache::lonnet::coursedescription($key);
14149: my $coursetitle = $coursehash{'description'};
14150: my $position = $confhash{$type}{$key}{'order'} + 1;
14151: $resulttext .= '<li>';
1.243 raeburn 14152: foreach my $item ('subject','title','publisher','author') {
14153: next if ((($item eq 'author') || ($item eq 'publisher')) &&
14154: ($type eq 'templates'));
1.242 raeburn 14155: my $name = $item.':';
14156: $name =~ s/^(\w)/\U$1/;
14157: $resulttext .= &mt($name).' '.$confhash{$type}{$key}{$item}.'<br />';
14158: }
14159: $resulttext .= ' '.&mt('Order: [_1]',$position).'<br />';
14160: if ($type eq 'textbooks') {
14161: if ($confhash{$type}{$key}{'image'}) {
14162: $resulttext .= ' '.&mt('Image: [_1]',
14163: '<img src="'.$confhash{$type}{$key}{'image'}.'"'.
14164: ' alt="Textbook cover" />').'<br />';
14165: }
14166: }
14167: $resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'</li>';
1.216 raeburn 14168: }
1.242 raeburn 14169: $resulttext .= '</ul></li>';
1.216 raeburn 14170: }
14171: }
1.235 raeburn 14172: if (ref($changes{'validation'}) eq 'HASH') {
14173: if ((ref($validationitemsref) eq 'ARRAY') && (ref($validationnamesref) eq 'HASH')) {
14174: $resulttext .= '<li>'.&mt('Validation of courses/communities updated').'<ul>';
14175: foreach my $item (@{$validationitemsref}) {
14176: if (exists($changes{'validation'}{$item})) {
14177: if ($item eq 'markup') {
14178: $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},
14179: '<br /><pre>'.$changes{'validation'}{$item}.'</pre>').'</li>';
14180: } else {
14181: $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$validationnamesref->{$item},
14182: '<b>'.$changes{'validation'}{$item}.'</b>').'</li>';
14183: }
14184: }
14185: }
14186: if (exists($changes{'validation'}{'dc'})) {
14187: $resulttext .= '<li>'.&mt('Validated course requests identified as processed by: [_1]',
14188: '<b>'.$changes{'validation'}{'dc'}.'</b>').'</li>';
14189: }
14190: }
14191: }
1.216 raeburn 14192: }
1.1 raeburn 14193: $resulttext .= '</ul>';
1.80 raeburn 14194: if (keys(%newenv)) {
14195: &Apache::lonnet::appenv(\%newenv);
14196: }
1.1 raeburn 14197: } else {
1.86 raeburn 14198: if ($context eq 'requestcourses') {
14199: $resulttext = &mt('No changes made to rights to request creation of courses.');
1.163 raeburn 14200: } elsif ($context eq 'requestauthor') {
14201: $resulttext = &mt('No changes made to rights to request author space.');
1.86 raeburn 14202: } else {
1.90 weissno 14203: $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas');
1.86 raeburn 14204: }
1.1 raeburn 14205: }
14206: } else {
1.11 albertel 14207: $resulttext = '<span class="LC_error">'.
14208: &mt('An error occurred: [_1]',$putresult).'</span>';
1.1 raeburn 14209: }
1.216 raeburn 14210: if ($errors) {
14211: $resulttext .= '<p>'.&mt('The following errors occurred when modifying Textbook settings.').
14212: '<ul>'.$errors.'</ul></p>';
14213: }
1.3 raeburn 14214: return $resulttext;
1.1 raeburn 14215: }
14216:
1.216 raeburn 14217: sub process_textbook_image {
1.242 raeburn 14218: my ($r,$dom,$confname,$caller,$cdom,$cnum,$type,$configuserok,$switchserver,$author_ok) = @_;
1.216 raeburn 14219: my $filename = $env{'form.'.$caller.'.filename'};
14220: my ($error,$url);
14221: my ($width,$height) = (50,50);
14222: if ($configuserok eq 'ok') {
14223: if ($switchserver) {
14224: $error = &mt('Upload of textbook image is not permitted to this server: [_1]',
14225: $switchserver);
14226: } elsif ($author_ok eq 'ok') {
1.421 raeburn 14227: my $modified = [];
1.216 raeburn 14228: my ($result,$imageurl) =
1.421 raeburn 14229: &Apache::lonconfigsettings::publishlogo($r,'upload',$caller,$dom,$confname,
14230: "$type/$cdom/$cnum/cover",$width,$height,
14231: '',$modified);
1.216 raeburn 14232: if ($result eq 'ok') {
14233: $url = $imageurl;
1.421 raeburn 14234: &update_modify_urls($r,$modified);
1.216 raeburn 14235: } else {
14236: $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
14237: }
14238: } else {
14239: $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$author_ok);
14240: }
14241: } else {
14242: $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$configuserok);
14243: }
14244: return ($url,$error);
14245: }
14246:
1.267 raeburn 14247: sub modify_ltitools {
14248: my ($r,$dom,$action,$lastactref,%domconfig) = @_;
1.421 raeburn 14249: my (%currtoolsec,%secchanges,%newtoolsec,%newkeyset);
14250: &fetch_secrets($dom,'toolsec',\%domconfig,\%currtoolsec,\%secchanges,\%newtoolsec,\%newkeyset);
14251:
1.267 raeburn 14252: my $confname = $dom.'-domainconfig';
14253: my $servadm = $r->dir_config('lonAdmEMail');
14254: my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
1.421 raeburn 14255:
14256: my ($resulttext,$ltitoolsoutput,$is_home,$errors,%ltitoolschg,%newtoolsenc,%newltitools);
14257: my $toolserror =
14258: &Apache::courseprefs::process_ltitools($r,$dom,$confname,$domconfig{'ltitools'},\%ltitoolschg,'domain',
14259: $lastactref,$configuserok,$switchserver,$author_ok);
14260:
14261: my $home = &Apache::lonnet::domain($dom,'primary');
14262: unless (($home eq 'no_host') || ($home eq '')) {
14263: my @ids=&Apache::lonnet::current_machine_ids();
14264: foreach my $id (@ids) { if ($id eq $home) { $is_home=1; last; } }
14265: }
14266:
14267: if (keys(%ltitoolschg)) {
14268: foreach my $id (keys(%ltitoolschg)) {
14269: if (ref($ltitoolschg{$id}) eq 'HASH') {
14270: foreach my $inner (keys(%{$ltitoolschg{$id}})) {
14271: if (($inner eq 'secret') || ($inner eq 'key')) {
14272: if ($is_home) {
14273: $newtoolsenc{$id}{$inner} = $ltitoolschg{$id}{$inner};
14274: }
14275: }
14276: }
1.267 raeburn 14277: }
1.421 raeburn 14278: }
14279: $ltitoolsoutput = &Apache::courseprefs::store_ltitools($dom,'','domain',\%ltitoolschg,$domconfig{'ltitools'});
14280: if (keys(%ltitoolschg)) {
14281: %newltitools = %ltitoolschg;
14282: }
14283: }
14284: if (ref($domconfig{'ltitools'}) eq 'HASH') {
14285: foreach my $id (%{$domconfig{'ltitools'}}) {
14286: next if ($id !~ /^\d+$/);
14287: unless (exists($ltitoolschg{$id})) {
14288: if (ref($domconfig{'ltitools'}{$id}) eq 'HASH') {
14289: foreach my $inner (keys(%{$domconfig{'ltitools'}{$id}})) {
14290: if (($inner eq 'secret') || ($inner eq 'key')) {
14291: if ($is_home) {
14292: $newtoolsenc{$id}{$inner} = $domconfig{'ltitools'}{$id}{$inner};
14293: }
14294: } else {
14295: $newltitools{$id}{$inner} = $domconfig{'ltitools'}{$id}{$inner};
14296: }
14297: }
14298: } else {
14299: $newltitools{$id} = $domconfig{'ltitools'}{$id};
1.322 raeburn 14300: }
1.421 raeburn 14301: }
14302: }
14303: }
14304: if ($toolserror) {
14305: $errors = '<li>'.$toolserror.'</li>';
14306: }
14307: if ((keys(%ltitoolschg) == 0) && (keys(%secchanges) == 0)) {
14308: $resulttext = &mt('No changes made.');
14309: if ($errors) {
14310: $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
14311: $errors.'</ul>';
14312: }
14313: return $resulttext;
14314: }
14315: my %ltitoolshash = (
14316: $action => { %newltitools }
14317: );
14318: if (keys(%secchanges)) {
14319: $ltitoolshash{'toolsec'} = \%newtoolsec;
14320: }
14321: my $putresult = &Apache::lonnet::put_dom('configuration',\%ltitoolshash,$dom);
14322: if ($putresult eq 'ok') {
14323: my %keystore;
14324: if ($is_home) {
14325: my %toolsenchash = (
14326: $action => { %newtoolsenc }
14327: );
14328: &Apache::lonnet::put_dom('encconfig',\%toolsenchash,$dom,undef,1);
1.423 raeburn 14329: my $cachetime = 24*60*60;
14330: &Apache::lonnet::do_cache_new('ltitoolsenc',$dom,\%newtoolsenc,$cachetime);
1.421 raeburn 14331: &store_security($dom,'ltitools',\%secchanges,\%newkeyset,\%keystore,$lastactref);
14332: }
14333: $resulttext = &mt('Changes made:').'<ul>';
14334: if (keys(%secchanges) > 0) {
1.423 raeburn 14335: $resulttext .= <i_security_results($dom,'ltitools',\%secchanges,\%newtoolsec,\%newkeyset,\%keystore);
1.421 raeburn 14336: }
14337: if (keys(%ltitoolschg) > 0) {
14338: $resulttext .= $ltitoolsoutput;
14339: }
1.423 raeburn 14340: my $cachetime = 24*60*60;
14341: &Apache::lonnet::do_cache_new('ltitools',$dom,\%newltitools,$cachetime);
14342: if (ref($lastactref) eq 'HASH') {
14343: $lastactref->{'ltitools'} = 1;
14344: }
1.421 raeburn 14345: } else {
14346: $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';
14347: }
14348: if ($errors) {
14349: $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.
14350: $errors.'</ul></p>';
14351: }
14352: return $resulttext;
14353: }
14354:
14355: sub fetch_secrets {
14356: my ($dom,$context,$domconfig,$currsec,$secchanges,$newsec,$newkeyset) = @_;
14357: my %keyset;
14358: %{$currsec} = ();
14359: $newsec->{'private'}{'keys'} = [];
14360: $newsec->{'encrypt'} = {};
14361: $newsec->{'rules'} = {};
14362: if ($context eq 'ltisec') {
14363: $newsec->{'linkprot'} = {};
14364: }
14365: if (ref($domconfig->{$context}) eq 'HASH') {
14366: %{$currsec} = %{$domconfig->{$context}};
14367: if ($context eq 'ltisec') {
14368: if (ref($currsec->{'linkprot'}) eq 'HASH') {
14369: foreach my $id (keys(%{$currsec->{'linkprot'}})) {
14370: unless ($id =~ /^\d+$/) {
14371: delete($currsec->{'linkprot'}{$id});
1.297 raeburn 14372: }
1.267 raeburn 14373: }
14374: }
1.421 raeburn 14375: }
14376: if (ref($currsec->{'private'}) eq 'HASH') {
14377: if (ref($currsec->{'private'}{'keys'}) eq 'ARRAY') {
14378: $newsec->{'private'}{'keys'} = $currsec->{'private'}{'keys'};
14379: map { $keyset{$_} = 1; } @{$currsec->{'private'}{'keys'}};
1.267 raeburn 14380: }
1.421 raeburn 14381: }
14382: }
14383: my @items= ('crs','dom');
14384: if ($context eq 'ltisec') {
14385: push(@items,'consumers');
14386: }
14387: foreach my $item (@items) {
14388: my $formelement;
14389: if (($context eq 'toolsec') || ($item eq 'consumers')) {
14390: $formelement = 'form.'.$context.'_'.$item;
14391: } else {
14392: $formelement = 'form.'.$context.'_'.$item.'linkprot';
14393: }
14394: if ($env{$formelement}) {
14395: $newsec->{'encrypt'}{$item} = 1;
14396: if (ref($currsec->{'encrypt'}) eq 'HASH') {
14397: unless ($currsec->{'encrypt'}{$item}) {
14398: $secchanges->{'encrypt'} = 1;
14399: }
14400: } else {
14401: $secchanges->{'encrypt'} = 1;
1.267 raeburn 14402: }
1.421 raeburn 14403: } elsif (ref($currsec->{'encrypt'}) eq 'HASH') {
14404: if ($currsec->{'encrypt'}{$item}) {
14405: $secchanges->{'encrypt'} = 1;
1.323 raeburn 14406: }
1.421 raeburn 14407: }
14408: }
14409: my $secrets;
14410: if ($context eq 'ltisec') {
14411: $secrets = 'ltisecrets';
14412: } else {
14413: $secrets = 'toolsecrets';
14414: }
14415: unless (exists($currsec->{'rules'})) {
14416: $currsec->{'rules'} = {};
14417: }
14418: &password_rule_changes($secrets,$newsec->{'rules'},$currsec->{'rules'},$secchanges);
14419:
14420: my @ids=&Apache::lonnet::current_machine_ids();
14421: my %servers = &Apache::lonnet::get_servers($dom,'library');
14422:
14423: foreach my $hostid (keys(%servers)) {
14424: if (($hostid ne '') && (grep(/^\Q$hostid\E$/,@ids))) {
14425: my $keyitem = 'form.'.$context.'_privkey_'.$hostid;
14426: if (exists($env{$keyitem})) {
14427: $env{$keyitem} =~ s/(`)/'/g;
14428: if ($keyset{$hostid}) {
14429: if ($env{'form.'.$context.'_changeprivkey_'.$hostid}) {
14430: if ($env{$keyitem} ne '') {
14431: $secchanges->{'private'} = 1;
14432: $newkeyset->{$hostid} = $env{$keyitem};
14433: }
1.296 raeburn 14434: }
1.421 raeburn 14435: } elsif ($env{$keyitem} ne '') {
14436: unless (grep(/^\Q$hostid\E$/,@{$newsec->{'private'}{'keys'}})) {
14437: push(@{$newsec->{'private'}{'keys'}},$hostid);
1.296 raeburn 14438: }
1.421 raeburn 14439: $secchanges->{'private'} = 1;
14440: $newkeyset->{$hostid} = $env{$keyitem};
1.267 raeburn 14441: }
14442: }
1.421 raeburn 14443: }
14444: }
14445: }
14446:
14447: sub store_security {
1.424 raeburn 14448: my ($dom,$context,$secchanges,$newkeyset,$keystore) = @_;
1.421 raeburn 14449: return unless ((ref($secchanges) eq 'HASH') && (ref($newkeyset) eq 'HASH') &&
14450: (ref($keystore) eq 'HASH'));
14451: if (keys(%{$secchanges})) {
14452: if ($secchanges->{'private'}) {
14453: my $who = &escape($env{'user.name'}.':'.$env{'user.domain'});
14454: foreach my $hostid (keys(%{$newkeyset})) {
14455: my $storehash = {
14456: key => $newkeyset->{$hostid},
14457: who => $env{'user.name'}.':'.$env{'user.domain'},
14458: };
14459: $keystore->{$hostid} = &Apache::lonnet::store_dom($storehash,$context,'private',
14460: $dom,$hostid);
14461: }
14462: }
14463: }
14464: }
14465:
14466: sub lti_security_results {
1.423 raeburn 14467: my ($dom,$context,$secchanges,$newsec,$newkeyset,$keystore) = @_;
1.421 raeburn 14468: my $output;
1.423 raeburn 14469: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
14470: my $needs_update;
1.421 raeburn 14471: foreach my $item (keys(%{$secchanges})) {
14472: if ($item eq 'encrypt') {
1.423 raeburn 14473: $needs_update = 1;
1.421 raeburn 14474: my %encrypted;
14475: if ($context eq 'lti') {
14476: %encrypted = (
14477: crs => {
14478: on => &mt('Encryption of stored link protection secrets defined in courses enabled'),
14479: off => &mt('Encryption of stored link protection secrets defined in courses disabled'),
14480: },
14481: dom => {
14482: on => &mt('Encryption of stored link protection secrets defined in domain enabled'),
14483: off => &mt('Encryption of stored link protection secrets defined in domain disabled'),
14484: },
14485: consumers => {
14486: on => &mt('Encryption of stored consumer secrets defined in domain enabled'),
14487: off => &mt('Encryption of stored consumer secrets defined in domain disabled'),
14488: },
14489: );
1.267 raeburn 14490: } else {
1.421 raeburn 14491: %encrypted = (
14492: crs => {
14493: on => &mt('Encryption of stored external tool secrets defined in courses enabled'),
14494: off => &mt('Encryption of stored external tool secrets defined in courses disabled'),
14495: },
14496: dom => {
14497: on => &mt('Encryption of stored external tool secrets defined in domain enabled'),
14498: off => &mt('Encryption of stored external tool secrets defined in domain disabled'),
14499: },
14500: );
14501:
14502: }
14503: my @types= ('crs','dom');
14504: if ($context eq 'lti') {
1.423 raeburn 14505: foreach my $type (@types) {
14506: undef($domdefaults{'linkprotenc_'.$type});
14507: }
1.421 raeburn 14508: push(@types,'consumers');
1.423 raeburn 14509: undef($domdefaults{'ltienc_consumers'});
14510: } elsif ($context eq 'ltitools') {
14511: foreach my $type (@types) {
14512: undef($domdefaults{'toolenc_'.$type});
14513: }
1.267 raeburn 14514: }
1.421 raeburn 14515: foreach my $type (@types) {
14516: my $shown = $encrypted{$type}{'off'};
14517: if (ref($newsec->{$item}) eq 'HASH') {
14518: if ($newsec->{$item}{$type}) {
1.423 raeburn 14519: if ($context eq 'lti') {
14520: if ($type eq 'consumers') {
14521: $domdefaults{'ltienc_consumers'} = 1;
14522: } else {
14523: $domdefaults{'linkprotenc_'.$type} = 1;
14524: }
14525: } elsif ($context eq 'ltitools') {
14526: $domdefaults{'toolenc_'.$type} = 1;
14527: }
1.421 raeburn 14528: $shown = $encrypted{$type}{'on'};
1.319 raeburn 14529: }
1.267 raeburn 14530: }
1.421 raeburn 14531: $output .= '<li>'.$shown.'</li>';
1.267 raeburn 14532: }
1.421 raeburn 14533: } elsif ($item eq 'rules') {
14534: my %titles = &Apache::lonlocal::texthash(
14535: min => 'Minimum password length',
14536: max => 'Maximum password length',
14537: chars => 'Required characters',
14538: );
14539: foreach my $rule ('min','max') {
14540: if ($newsec->{rules}{$rule} eq '') {
14541: if ($rule eq 'min') {
14542: $output .= '<li>'.&mt('[_1] not set.',$titles{$rule});
14543: ' '.&mt('Default of [_1] will be used',
14544: $Apache::lonnet::passwdmin).'</li>';
14545: } else {
14546: $output .= '<li>'.&mt('[_1] set to none',$titles{$rule}).'</li>';
14547: }
14548: } else {
14549: $output .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$newsec->{rules}{$rule}).'</li>';
14550: }
14551: }
14552: if (ref($newsec->{'rules'}{'chars'}) eq 'ARRAY') {
14553: if (@{$newsec->{'rules'}{'chars'}} > 0) {
14554: my %rulenames = &Apache::lonlocal::texthash(
14555: uc => 'At least one upper case letter',
14556: lc => 'At least one lower case letter',
14557: num => 'At least one number',
14558: spec => 'At least one non-alphanumeric',
14559: );
14560: my $needed = '<ul><li>'.
14561: join('</li><li>',map {$rulenames{$_} } @{$newsec->{'rules'}{'chars'}}).
14562: '</li></ul>';
14563: $output .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';
14564: } else {
14565: $output .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';
1.267 raeburn 14566: }
1.421 raeburn 14567: } else {
14568: $output .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';
1.267 raeburn 14569: }
1.421 raeburn 14570: } elsif ($item eq 'private') {
1.423 raeburn 14571: $needs_update = 1;
14572: if ($context eq 'lti') {
14573: undef($domdefaults{'ltiprivhosts'});
14574: } elsif ($context eq 'ltitools') {
14575: undef($domdefaults{'toolprivhosts'});
14576: }
1.421 raeburn 14577: if (keys(%{$newkeyset})) {
1.423 raeburn 14578: my @privhosts;
1.421 raeburn 14579: foreach my $hostid (sort(keys(%{$newkeyset}))) {
14580: if ($keystore->{$hostid} eq 'ok') {
14581: $output .= '<li>'.&mt('Encryption key for storage of shared secrets saved for [_1]',$hostid).'</li>';
1.423 raeburn 14582: unless (grep(/^\Q$hostid\E$/,@privhosts)) {
14583: push(@privhosts,$hostid);
14584: }
14585: }
14586: }
14587: if (@privhosts) {
14588: if ($context eq 'lti') {
14589: $domdefaults{'ltiprivhosts'} = \@privhosts;
14590: } elsif ($context eq 'ltitools') {
14591: $domdefaults{'toolprivhosts'} = \@privhosts;
1.267 raeburn 14592: }
14593: }
14594: }
1.421 raeburn 14595: } elsif ($item eq 'linkprot') {
14596: next;
1.267 raeburn 14597: }
14598: }
1.423 raeburn 14599: if ($needs_update) {
14600: my $cachetime = 24*60*60;
14601: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
14602: }
1.421 raeburn 14603: return $output;
14604: }
14605:
14606: sub modify_proctoring {
14607: my ($r,$dom,$action,$lastactref,%domconfig) = @_;
14608: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
14609: my (@allpos,%changes,%confhash,%encconfhash,$errors,$resulttext,%imgdeletions);
14610: my $confname = $dom.'-domainconfig';
14611: my $servadm = $r->dir_config('lonAdmEMail');
1.372 raeburn 14612: my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
14613: my %providernames = &proctoring_providernames();
14614: my $maxnum = scalar(keys(%providernames));
14615:
14616: my (%requserfields,%optuserfields,%defaults,%extended,%crsconf,@courseroles,@ltiroles);
14617: my ($requref,$opturef,$defref,$extref,$crsref,$rolesref,$ltiref) = &proctoring_data();
14618: if (ref($requref) eq 'HASH') {
14619: %requserfields = %{$requref};
14620: }
14621: if (ref($opturef) eq 'HASH') {
14622: %optuserfields = %{$opturef};
14623: }
14624: if (ref($defref) eq 'HASH') {
14625: %defaults = %{$defref};
14626: }
14627: if (ref($extref) eq 'HASH') {
14628: %extended = %{$extref};
14629: }
14630: if (ref($crsref) eq 'HASH') {
14631: %crsconf = %{$crsref};
14632: }
14633: if (ref($rolesref) eq 'ARRAY') {
14634: @courseroles = @{$rolesref};
14635: }
14636: if (ref($ltiref) eq 'ARRAY') {
14637: @ltiroles = @{$ltiref};
14638: }
14639:
14640: if (ref($domconfig{$action}) eq 'HASH') {
14641: my @todeleteimages = &Apache::loncommon::get_env_multiple('form.proctoring_image_del');
14642: if (@todeleteimages) {
14643: map { $imgdeletions{$_} = 1; } @todeleteimages;
14644: }
14645: }
14646: my %customadds;
14647: my @newcustom = &Apache::loncommon::get_env_multiple('form.proctoring_customadd');
14648: if (@newcustom) {
14649: map { $customadds{$_} = 1; } @newcustom;
14650: }
14651: foreach my $provider (sort(keys(%providernames))) {
14652: $confhash{$provider} = {};
14653: my $pos = $env{'form.proctoring_pos_'.$provider};
14654: $pos =~ s/\D+//g;
14655: $allpos[$pos] = $provider;
14656: my (%current,%currentenc);
14657: my $showroles = 0;
14658: if (ref($domconfig{$action}) eq 'HASH') {
14659: if (ref($domconfig{$action}{$provider}) eq 'HASH') {
14660: %current = %{$domconfig{$action}{$provider}};
14661: foreach my $item ('key','secret') {
14662: $currentenc{$item} = $current{$item};
14663: delete($current{$item});
14664: }
14665: }
14666: }
14667: if ($env{'form.proctoring_available_'.$provider}) {
14668: $confhash{$provider}{'available'} = 1;
14669: unless ($current{'available'}) {
14670: $changes{$provider} = 1;
14671: }
14672: } else {
14673: %{$confhash{$provider}} = %current;
14674: %{$encconfhash{$provider}} = %currentenc;
14675: $confhash{$provider}{'available'} = 0;
14676: if ($current{'available'}) {
14677: $changes{$provider} = 1;
14678: }
14679: }
14680: if ($confhash{$provider}{'available'}) {
14681: foreach my $field ('lifetime','version','sigmethod','url','key','secret') {
14682: my $possval = $env{'form.proctoring_'.$provider.'_'.$field};
14683: if ($field eq 'lifetime') {
14684: if ($possval =~ /^\d+$/) {
14685: $confhash{$provider}{$field} = $possval;
14686: }
14687: } elsif ($field eq 'version') {
14688: if ($possval =~ /^\d+\.\d+$/) {
14689: $confhash{$provider}{$field} = $possval;
14690: }
14691: } elsif ($field eq 'sigmethod') {
14692: if ($possval =~ /^\QHMAC-SHA\E(1|256)$/) {
14693: $confhash{$provider}{$field} = $possval;
14694: }
14695: } elsif ($field eq 'url') {
14696: $confhash{$provider}{$field} = $possval;
14697: } elsif (($field eq 'key') || ($field eq 'secret')) {
14698: $encconfhash{$provider}{$field} = $possval;
14699: unless ($currentenc{$field} eq $possval) {
14700: $changes{$provider} = 1;
14701: }
14702: }
14703: unless (($field eq 'key') || ($field eq 'secret')) {
14704: unless ($current{$field} eq $confhash{$provider}{$field}) {
14705: $changes{$provider} = 1;
14706: }
14707: }
14708: }
14709: if ($imgdeletions{$provider}) {
14710: $changes{$provider} = 1;
14711: } elsif ($env{'form.proctoring_image_'.$provider.'.filename'} ne '') {
14712: my ($imageurl,$error) =
14713: &process_proctoring_image($r,$dom,$confname,'proctoring_image_'.$provider,$provider,
14714: $configuserok,$switchserver,$author_ok);
14715: if ($imageurl) {
14716: $confhash{$provider}{'image'} = $imageurl;
14717: $changes{$provider} = 1;
14718: }
14719: if ($error) {
14720: &Apache::lonnet::logthis($error);
14721: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
14722: }
14723: } elsif (exists($current{'image'})) {
14724: $confhash{$provider}{'image'} = $current{'image'};
14725: }
14726: if (ref($requserfields{$provider}) eq 'ARRAY') {
14727: if (@{$requserfields{$provider}} > 0) {
14728: if (grep(/^user$/,@{$requserfields{$provider}})) {
14729: if ($env{'form.proctoring_userincdom_'.$provider}) {
14730: $confhash{$provider}{'incdom'} = 1;
14731: }
14732: unless ($current{'incdom'} eq $confhash{$provider}{'incdom'}) {
14733: $changes{$provider} = 1;
14734: }
14735: }
14736: if (grep(/^roles$/,@{$requserfields{$provider}})) {
14737: $showroles = 1;
14738: }
14739: }
14740: }
14741: $confhash{$provider}{'fields'} = [];
14742: if (ref($optuserfields{$provider}) eq 'ARRAY') {
14743: if (@{$optuserfields{$provider}} > 0) {
14744: my @optfields = &Apache::loncommon::get_env_multiple('form.proctoring_optional_'.$provider);
14745: foreach my $field (@{$optuserfields{$provider}}) {
14746: if (grep(/^\Q$field\E$/,@optfields)) {
14747: push(@{$confhash{$provider}{'fields'}},$field);
14748: }
14749: }
14750: }
14751: if (ref($current{'fields'}) eq 'ARRAY') {
14752: unless ($changes{$provider}) {
14753: my @new = sort(@{$confhash{$provider}{'fields'}});
14754: my @old = sort(@{$current{'fields'}});
14755: my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
14756: if (@diffs) {
14757: $changes{$provider} = 1;
14758: }
14759: }
14760: } elsif (@{$confhash{$provider}{'fields'}}) {
14761: $changes{$provider} = 1;
14762: }
14763: }
14764: if (ref($defaults{$provider}) eq 'ARRAY') {
14765: if (@{$defaults{$provider}} > 0) {
14766: my %options;
14767: if (ref($extended{$provider}) eq 'HASH') {
14768: %options = %{$extended{$provider}};
14769: }
14770: my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_defaults_'.$provider);
14771: foreach my $field (@{$defaults{$provider}}) {
14772: if ((exists($options{$field})) && (ref($options{$field}) eq 'ARRAY')) {
14773: my $poss = $env{'form.proctoring_defaults_'.$field.'_'.$provider};
14774: if (grep(/^\Q$poss\E$/,@{$options{$field}})) {
14775: push(@{$confhash{$provider}{'defaults'}},$poss);
14776: }
14777: } elsif ((exists($options{$field})) && (ref($options{$field}) eq 'HASH')) {
14778: foreach my $inner (keys(%{$options{$field}})) {
14779: if (ref($options{$field}{$inner}) eq 'ARRAY') {
14780: my $poss = $env{'form.proctoring_'.$inner.'_'.$provider};
14781: if (grep(/^\Q$poss\E$/,@{$options{$field}{$inner}})) {
14782: $confhash{$provider}{'defaults'}{$inner} = $poss;
14783: }
14784: } else {
14785: $confhash{$provider}{'defaults'}{$inner} = $env{'form.proctoring_'.$inner.'_'.$provider};
14786: }
14787: }
14788: } else {
14789: if (grep(/^\Q$field\E$/,@checked)) {
14790: push(@{$confhash{$provider}{'defaults'}},$field);
14791: }
14792: }
14793: }
14794: if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') {
14795: if (ref($current{'defaults'}) eq 'ARRAY') {
14796: unless ($changes{$provider}) {
14797: my @new = sort(@{$confhash{$provider}{'defaults'}});
14798: my @old = sort(@{$current{'defaults'}});
14799: my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
14800: if (@diffs) {
14801: $changes{$provider} = 1;
14802: }
14803: }
14804: } elsif (ref($current{'defaults'}) eq 'ARRAY') {
14805: if (@{$current{'defaults'}}) {
14806: $changes{$provider} = 1;
14807: }
14808: }
14809: } elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') {
14810: if (ref($current{'defaults'}) eq 'HASH') {
14811: unless ($changes{$provider}) {
14812: foreach my $key (keys(%{$confhash{$provider}{'defaults'}})) {
14813: unless ($confhash{$provider}{'defaults'}{$key} eq $current{'defaults'}{$key}) {
14814: $changes{$provider} = 1;
14815: last;
14816: }
14817: }
14818: }
14819: unless ($changes{$provider}) {
14820: foreach my $key (keys(%{$current{'defaults'}})) {
14821: unless ($current{'defaults'}{$key} eq $confhash{$provider}{'defaults'}{$key}) {
14822: $changes{$provider} = 1;
14823: last;
14824: }
14825: }
14826: }
14827: } elsif (keys(%{$confhash{$provider}{'defaults'}})) {
14828: $changes{$provider} = 1;
14829: }
14830: }
14831: }
14832: }
14833: if (ref($crsconf{$provider}) eq 'ARRAY') {
14834: if (@{$crsconf{$provider}} > 0) {
14835: $confhash{$provider}{'crsconf'} = [];
14836: my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_crsconf_'.$provider);
14837: foreach my $crsfield (@{$crsconf{$provider}}) {
14838: if (grep(/^\Q$crsfield\E$/,@checked)) {
14839: push(@{$confhash{$provider}{'crsconf'}},$crsfield);
14840: }
14841: }
14842: if (ref($current{'crsconf'}) eq 'ARRAY') {
14843: unless ($changes{$provider}) {
14844: my @new = sort(@{$confhash{$provider}{'crsconf'}});
14845: my @old = sort(@{$current{'crsconf'}});
14846: my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
14847: if (@diffs) {
14848: $changes{$provider} = 1;
14849: }
14850: }
14851: } elsif (@{$confhash{$provider}{'crsconf'}}) {
14852: $changes{$provider} = 1;
14853: }
14854: }
14855: }
14856: if ($showroles) {
14857: $confhash{$provider}{'roles'} = {};
14858: foreach my $role (@courseroles) {
14859: my $poss = $env{'form.proctoring_roles_'.$role.'_'.$provider};
14860: if (grep(/^\Q$poss\E$/,@ltiroles)) {
14861: $confhash{$provider}{'roles'}{$role} = $poss;
14862: }
14863: }
14864: unless ($changes{$provider}) {
14865: if (ref($current{'roles'}) eq 'HASH') {
14866: foreach my $role (keys(%{$current{'roles'}})) {
14867: unless ($current{'roles'}{$role} eq $confhash{$provider}{'roles'}{$role}) {
14868: $changes{$provider} = 1;
14869: last
14870: }
14871: }
14872: unless ($changes{$provider}) {
14873: foreach my $role (keys(%{$confhash{$provider}{'roles'}})) {
14874: unless ($confhash{$provider}{'roles'}{$role} eq $current{'roles'}{$role}) {
14875: $changes{$provider} = 1;
14876: last;
14877: }
14878: }
14879: }
14880: } elsif (keys(%{$confhash{$provider}{'roles'}})) {
14881: $changes{$provider} = 1;
14882: }
14883: }
14884: }
14885: if (ref($current{'custom'}) eq 'HASH') {
14886: my @customdels = &Apache::loncommon::get_env_multiple('form.proctoring_customdel_'.$provider);
14887: foreach my $key (keys(%{$current{'custom'}})) {
14888: if (grep(/^\Q$key\E$/,@customdels)) {
14889: $changes{$provider} = 1;
14890: } else {
14891: $confhash{$provider}{'custom'}{$key} = $env{'form.proctoring_customval_'.$key.'_'.$provider};
14892: if ($confhash{$provider}{'custom'}{$key} ne $current{'custom'}{$key}) {
14893: $changes{$provider} = 1;
14894: }
14895: }
14896: }
14897: }
14898: if ($customadds{$provider}) {
14899: my $name = $env{'form.proctoring_custom_name_'.$provider};
14900: $name =~ s/(`)/'/g;
14901: $name =~ s/^\s+//;
14902: $name =~ s/\s+$//;
14903: my $value = $env{'form.proctoring_custom_value_'.$provider};
14904: $value =~ s/(`)/'/g;
14905: $value =~ s/^\s+//;
14906: $value =~ s/\s+$//;
14907: if ($name ne '') {
14908: $confhash{$provider}{'custom'}{$name} = $value;
14909: $changes{$provider} = 1;
14910: }
14911: }
14912: }
14913: }
14914: if (@allpos > 0) {
14915: my $idx = 0;
14916: foreach my $provider (@allpos) {
14917: if ($provider ne '') {
14918: $confhash{$provider}{'order'} = $idx;
14919: unless ($changes{$provider}) {
14920: if (ref($domconfig{$action}) eq 'HASH') {
14921: if (ref($domconfig{$action}{$provider}) eq 'HASH') {
14922: if ($domconfig{$action}{$provider}{'order'} ne $idx) {
14923: $changes{$provider} = 1;
14924: }
14925: }
14926: }
14927: }
14928: $idx ++;
14929: }
14930: }
14931: }
14932: my %proc_hash = (
14933: $action => { %confhash }
14934: );
14935: my $putresult = &Apache::lonnet::put_dom('configuration',\%proc_hash,
14936: $dom);
14937: if ($putresult eq 'ok') {
14938: my %proc_enchash = (
14939: $action => { %encconfhash }
14940: );
1.384 raeburn 14941: &Apache::lonnet::put_dom('encconfig',\%proc_enchash,$dom,undef,1);
1.372 raeburn 14942: if (keys(%changes) > 0) {
14943: my $cachetime = 24*60*60;
14944: my %procall = %confhash;
14945: foreach my $provider (keys(%procall)) {
14946: if (ref($encconfhash{$provider}) eq 'HASH') {
14947: foreach my $key ('key','secret') {
14948: $procall{$provider}{$key} = $encconfhash{$provider}{$key};
14949: }
14950: }
14951: }
14952: &Apache::lonnet::do_cache_new('proctoring',$dom,\%procall,$cachetime);
14953: if (ref($lastactref) eq 'HASH') {
14954: $lastactref->{'proctoring'} = 1;
14955: }
14956: $resulttext = &mt('Configuration for Provider(s) with changes:').'<ul>';
14957: my %bynum;
14958: foreach my $provider (sort(keys(%changes))) {
14959: my $position = $confhash{$provider}{'order'};
14960: $bynum{$position} = $provider;
14961: }
14962: foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
14963: my $provider = $bynum{$pos};
14964: my %lt = &proctoring_titles($provider);
14965: my %fieldtitles = &proctoring_fieldtitles($provider);
14966: if (!$confhash{$provider}{'available'}) {
14967: $resulttext .= '<li>'.&mt('Proctoring integration unavailable for: [_1]','<b>'.$providernames{$provider}.'</b>').'</li>';
14968: } else {
14969: $resulttext .= '<li>'.&mt('Proctoring integration available for: [_1]','<b>'.$providernames{$provider}.'</b>');
14970: if ($confhash{$provider}{'image'}) {
14971: $resulttext .= ' '.
14972: '<img src="'.$confhash{$provider}{'image'}.'"'.
14973: ' alt="'.&mt('Proctoring icon').'" />';
14974: }
14975: $resulttext .= '<ul>';
14976: my $position = $pos + 1;
14977: $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
14978: foreach my $key ('version','sigmethod','url','lifetime') {
14979: if ($confhash{$provider}{$key} ne '') {
14980: $resulttext .= '<li>'.$lt{$key}.': '.$confhash{$provider}{$key}.'</li>';
14981: }
14982: }
14983: if ($encconfhash{$provider}{'key'} ne '') {
14984: $resulttext .= '<li>'.$lt{'key'}.': '.$encconfhash{$provider}{'key'}.'</li>';
14985: }
14986: if ($encconfhash{$provider}{'secret'} ne '') {
14987: $resulttext .= '<li>'.$lt{'secret'}.': ';
14988: my $num = length($encconfhash{$provider}{'secret'});
14989: $resulttext .= ('*'x$num).'</li>';
14990: }
14991: my (@fields,$showroles);
14992: if (ref($requserfields{$provider}) eq 'ARRAY') {
14993: push(@fields,@{$requserfields{$provider}});
14994: }
14995: if (ref($confhash{$provider}{'fields'}) eq 'ARRAY') {
14996: push(@fields,@{$confhash{$provider}{'fields'}});
14997: } elsif (ref($confhash{$provider}{'fields'}) eq 'HASH') {
14998: push(@fields,(keys(%{$confhash{$provider}{'fields'}})));
14999: }
15000: if (@fields) {
15001: if (grep(/^roles$/,@fields)) {
15002: $showroles = 1;
15003: }
15004: $resulttext .= '<li>'.$lt{'udsl'}.': "'.
15005: join('", "', map { $lt{$_}; } @fields).'"</li>';
15006: }
15007: if (ref($requserfields{$provider}) eq 'ARRAY') {
15008: if (grep(/^user$/,@{$requserfields{$provider}})) {
15009: if ($confhash{$provider}{'incdom'}) {
15010: $resulttext .= '<li>'.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'uname:dom'}).'</li>';
15011: } else {
15012: $resulttext .= '<li>'.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'username'}).'</li>';
15013: }
15014: }
15015: }
15016: if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') {
15017: if (@{$confhash{$provider}{'defaults'}} > 0) {
15018: $resulttext .= '<li>'.$lt{'defa'};
15019: foreach my $field (@{$confhash{$provider}{'defaults'}}) {
15020: $resulttext .= ' "'.$fieldtitles{$field}.'",';
15021: }
15022: $resulttext =~ s/,$//;
15023: $resulttext .= '</li>';
15024: }
15025: } elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') {
15026: if (keys(%{$confhash{$provider}{'defaults'}})) {
15027: $resulttext .= '<li>'.$lt{'defa'}.': <ul>';
15028: foreach my $key (sort(keys(%{$confhash{$provider}{'defaults'}}))) {
15029: if ($confhash{$provider}{'defaults'}{$key} ne '') {
15030: $resulttext .= '<li>'.$fieldtitles{$key}.' = '.$confhash{$provider}{'defaults'}{$key}.'</li>';
15031: }
15032: }
15033: $resulttext .= '</ul></li>';
15034: }
15035: }
15036: if (ref($crsconf{$provider}) eq 'ARRAY') {
15037: if (@{$crsconf{$provider}} > 0) {
15038: $resulttext .= '<li>'.&mt('Configurable in course:');
15039: my $numconfig = 0;
15040: if (ref($confhash{$provider}{'crsconf'}) eq 'ARRAY') {
15041: if (@{$confhash{$provider}{'crsconf'}} > 0) {
15042: foreach my $field (@{$confhash{$provider}{'crsconf'}}) {
15043: $numconfig ++;
15044: if ($provider eq 'examity') {
15045: $resulttext .= ' "'.$lt{'crs'.$field}.'",';
15046: } else {
15047: $resulttext .= ' "'.$fieldtitles{$field}.'",';
15048: }
15049: }
15050: $resulttext =~ s/,$//;
15051: }
15052: }
15053: if (!$numconfig) {
15054: $resulttext .= ' '.&mt('None');
15055: }
15056: $resulttext .= '</li>';
15057: }
15058: }
15059: if ($showroles) {
15060: if (ref($confhash{$provider}{'roles'}) eq 'HASH') {
15061: my $rolemaps;
15062: foreach my $role (@courseroles) {
15063: if ($confhash{$provider}{'roles'}{$role}) {
15064: $rolemaps .= (' 'x2).&Apache::lonnet::plaintext($role,'Course').'='.
15065: $confhash{$provider}{'roles'}{$role}.',';
15066: }
15067: }
15068: if ($rolemaps) {
15069: $rolemaps =~ s/,$//;
15070: $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
15071: }
15072: }
15073: }
15074: if (ref($confhash{$provider}{'custom'}) eq 'HASH') {
15075: my $customlist;
15076: if (keys(%{$confhash{$provider}{'custom'}})) {
15077: foreach my $key (sort(keys(%{$confhash{$provider}{'custom'}}))) {
15078: $customlist .= $key.'='.$confhash{$provider}{'custom'}{$key}.', ';
15079: }
15080: $customlist =~ s/,$//;
15081: }
15082: if ($customlist) {
15083: $resulttext .= '<li>'.&mt('Custom items').': '.$customlist.'</li>';
15084: }
15085: }
15086: $resulttext .= '</ul></li>';
15087: }
15088: }
15089: $resulttext .= '</ul>';
15090: } else {
15091: $resulttext = &mt('No changes made.');
15092: }
15093: } else {
15094: $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';
15095: }
15096: if ($errors) {
15097: $resulttext .= &mt('The following errors occurred: ').'<ul>'.
15098: $errors.'</ul>';
15099: }
15100: return $resulttext;
15101: }
15102:
15103: sub process_proctoring_image {
15104: my ($r,$dom,$confname,$caller,$provider,$configuserok,$switchserver,$author_ok) = @_;
15105: my $filename = $env{'form.'.$caller.'.filename'};
15106: my ($error,$url);
15107: my ($width,$height) = (21,21);
15108: if ($configuserok eq 'ok') {
15109: if ($switchserver) {
15110: $error = &mt('Upload of Remote Proctoring Provider icon is not permitted to this server: [_1]',
15111: $switchserver);
15112: } elsif ($author_ok eq 'ok') {
1.421 raeburn 15113: my $modified = [];
1.372 raeburn 15114: my ($result,$imageurl,$madethumb) =
1.421 raeburn 15115: &Apache::lonconfigsettings::publishlogo($r,'upload',$caller,$dom,$confname,
15116: "proctoring/$provider/icon",$width,$height,
15117: '',$modified);
1.372 raeburn 15118: if ($result eq 'ok') {
15119: if ($madethumb) {
15120: my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
15121: my $imagethumb = "$path/tn-".$imagefile;
15122: $url = $imagethumb;
15123: } else {
15124: $url = $imageurl;
15125: }
1.421 raeburn 15126: &update_modify_urls($r,$modified);
1.372 raeburn 15127: } else {
15128: $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
15129: }
15130: } else {
15131: $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$author_ok);
15132: }
15133: } else {
15134: $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$configuserok);
15135: }
15136: return ($url,$error);
15137: }
15138:
1.320 raeburn 15139: sub modify_lti {
15140: my ($r,$dom,$action,$lastactref,%domconfig) = @_;
15141: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
1.424 raeburn 15142: my ($newid,@allpos,%changes,%confhash,%ltienc,$errors,$resulttext);
1.320 raeburn 15143: my (%posslti,%posslticrs,%posscrstype);
15144: my @courseroles = ('cc','in','ta','ep','st');
15145: my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
15146: my @lticourseroles = qw(Instructor TeachingAssistant Mentor Learner);
1.392 raeburn 15147: my @coursetypes = ('official','unofficial','community','textbook','placement','lti');
1.320 raeburn 15148: my %coursetypetitles = &Apache::lonlocal::texthash (
15149: official => 'Official',
15150: unofficial => 'Unofficial',
15151: community => 'Community',
15152: textbook => 'Textbook',
15153: placement => 'Placement Test',
1.392 raeburn 15154: lti => 'LTI Provider',
1.320 raeburn 15155: );
1.325 raeburn 15156: my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
1.320 raeburn 15157: my %lt = <i_names();
15158: map { $posslti{$_} = 1; } @ltiroles;
15159: map { $posslticrs{$_} = 1; } @lticourseroles;
15160: map { $posscrstype{$_} = 1; } @coursetypes;
1.325 raeburn 15161:
1.326 raeburn 15162: my %menutitles = <imenu_titles();
1.421 raeburn 15163: my (%currltisec,%secchanges,%newltisec,%newltienc,%newkeyset);
1.326 raeburn 15164:
1.421 raeburn 15165: &fetch_secrets($dom,'ltisec',\%domconfig,\%currltisec,\%secchanges,\%newltisec,\%newkeyset);
1.405 raeburn 15166:
1.406 raeburn 15167: my (%linkprotchg,$linkprotoutput,$is_home);
15168: my $proterror = &Apache::courseprefs::process_linkprot($dom,'',$currltisec{'linkprot'},
15169: \%linkprotchg,'domain');
15170: my $home = &Apache::lonnet::domain($dom,'primary');
15171: unless (($home eq 'no_host') || ($home eq '')) {
15172: my @ids=&Apache::lonnet::current_machine_ids();
15173: foreach my $id (@ids) { if ($id eq $home) { $is_home=1; } }
15174: }
15175:
15176: if (keys(%linkprotchg)) {
15177: $secchanges{'linkprot'} = 1;
15178: my %oldlinkprot;
15179: if (ref($currltisec{'linkprot'}) eq 'HASH') {
15180: %oldlinkprot = %{$currltisec{'linkprot'}};
15181: }
15182: foreach my $id (keys(%linkprotchg)) {
15183: if (ref($linkprotchg{$id}) eq 'HASH') {
15184: foreach my $inner (keys(%{$linkprotchg{$id}})) {
15185: if (($inner eq 'secret') || ($inner eq 'key')) {
15186: if ($is_home) {
15187: $newltienc{$id}{$inner} = $linkprotchg{$id}{$inner};
15188: }
15189: }
15190: }
15191: } else {
15192: $newltisec{'linkprot'}{$id} = $linkprotchg{$id};
15193: }
15194: }
15195: $linkprotoutput = &Apache::courseprefs::store_linkprot($dom,'','domain',\%linkprotchg,\%oldlinkprot);
15196: if (keys(%linkprotchg)) {
15197: %{$newltisec{'linkprot'}} = %linkprotchg;
15198: }
15199: }
15200: if (ref($currltisec{'linkprot'}) eq 'HASH') {
15201: foreach my $id (%{$currltisec{'linkprot'}}) {
15202: next if ($id !~ /^\d+$/);
15203: unless (exists($linkprotchg{$id})) {
15204: if (ref($currltisec{'linkprot'}{$id}) eq 'HASH') {
15205: foreach my $inner (keys(%{$currltisec{'linkprot'}{$id}})) {
15206: if (($inner eq 'secret') || ($inner eq 'key')) {
15207: if ($is_home) {
15208: $newltienc{$id}{$inner} = $currltisec{'linkprot'}{$id}{$inner};
15209: }
15210: } else {
15211: $newltisec{'linkprot'}{$id}{$inner} = $currltisec{'linkprot'}{$id}{$inner};
15212: }
15213: }
15214: } else {
15215: $newltisec{'linkprot'}{$id} = $currltisec{'linkprot'}{$id};
15216: }
15217: }
15218: }
15219: }
15220: if ($proterror) {
15221: $errors .= '<li>'.$proterror.'</li>';
15222: }
1.320 raeburn 15223: my (@items,%deletions,%itemids);
15224: if ($env{'form.lti_add'}) {
15225: my $consumer = $env{'form.lti_consumer_add'};
15226: $consumer =~ s/(`)/'/g;
15227: ($newid,my $error) = &get_lti_id($dom,$consumer);
15228: if ($newid) {
15229: $itemids{'add'} = $newid;
15230: push(@items,'add');
15231: $changes{$newid} = 1;
15232: } else {
15233: my $error = &mt('Failed to acquire unique ID for new LTI configuration');
15234: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
15235: }
15236: }
15237: if (ref($domconfig{$action}) eq 'HASH') {
15238: my @todelete = &Apache::loncommon::get_env_multiple('form.lti_del');
15239: if (@todelete) {
15240: map { $deletions{$_} = 1; } @todelete;
15241: }
15242: my $maxnum = $env{'form.lti_maxnum'};
1.390 raeburn 15243: for (my $i=0; $i<$maxnum; $i++) {
1.320 raeburn 15244: my $itemid = $env{'form.lti_id_'.$i};
15245: $itemid =~ s/\D+//g;
15246: if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
15247: if ($deletions{$itemid}) {
15248: $changes{$itemid} = $domconfig{$action}{$itemid}{'consumer'};
15249: } else {
1.390 raeburn 15250: push(@items,$i);
15251: $itemids{$i} = $itemid;
1.320 raeburn 15252: }
15253: }
15254: }
15255: }
1.424 raeburn 15256: my (%keystore,$secstored);
15257: if ($is_home) {
15258: &store_security($dom,'lti',\%secchanges,\%newkeyset,\%keystore);
15259: }
15260:
15261: my ($cipher,$privnum);
15262: if ((@items > 0) && ($is_home)) {
15263: ($cipher,$privnum) = &get_priv_creds($dom,$home,$secchanges{'encrypt'},
15264: $newltisec{'encrypt'},$keystore{$home});
15265: }
1.320 raeburn 15266: foreach my $idx (@items) {
15267: my $itemid = $itemids{$idx};
15268: next unless ($itemid);
1.424 raeburn 15269: my %currlti;
15270: unless ($idx eq 'add') {
15271: if (ref($domconfig{$action}) eq 'HASH') {
15272: if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
15273: %currlti = %{$domconfig{$action}{$itemid}};
15274: }
15275: }
15276: }
1.390 raeburn 15277: my $position = $env{'form.lti_pos_'.$itemid};
1.320 raeburn 15278: $position =~ s/\D+//g;
15279: if ($position ne '') {
15280: $allpos[$position] = $itemid;
15281: }
1.424 raeburn 15282: foreach my $item ('consumer','lifetime','requser','crsinc') {
1.320 raeburn 15283: my $formitem = 'form.lti_'.$item.'_'.$idx;
15284: $env{$formitem} =~ s/(`)/'/g;
15285: if ($item eq 'lifetime') {
15286: $env{$formitem} =~ s/[^\d.]//g;
15287: }
15288: if ($env{$formitem} ne '') {
1.424 raeburn 15289: $confhash{$itemid}{$item} = $env{$formitem};
15290: unless (($idx eq 'add') || ($changes{$itemid})) {
15291: if ($currlti{$item} ne $confhash{$itemid}{$item}) {
15292: $changes{$itemid} = 1;
1.320 raeburn 15293: }
15294: }
15295: }
15296: }
15297: if ($env{'form.lti_version_'.$idx} eq 'LTI-1p0') {
15298: $confhash{$itemid}{'version'} = $env{'form.lti_version_'.$idx};
15299: }
1.345 raeburn 15300: if ($confhash{$itemid}{'requser'}) {
15301: if ($env{'form.lti_mapuser_'.$idx} eq 'sourcedid') {
1.405 raeburn 15302: $confhash{$itemid}{'mapuser'} = 'lis_person_sourcedid';
1.345 raeburn 15303: } elsif ($env{'form.lti_mapuser_'.$idx} eq 'email') {
15304: $confhash{$itemid}{'mapuser'} = 'lis_person_contact_email_primary';
15305: } elsif ($env{'form.lti_mapuser_'.$idx} eq 'other') {
15306: my $mapuser = $env{'form.lti_customuser_'.$idx};
15307: $mapuser =~ s/(`)/'/g;
1.405 raeburn 15308: $mapuser =~ s/^\s+|\s+$//g;
15309: $confhash{$itemid}{'mapuser'} = $mapuser;
1.345 raeburn 15310: }
15311: my @possmakeuser = &Apache::loncommon::get_env_multiple('form.lti_makeuser_'.$idx);
15312: my @makeuser;
15313: foreach my $ltirole (sort(@possmakeuser)) {
15314: if ($posslti{$ltirole}) {
15315: push(@makeuser,$ltirole);
15316: }
15317: }
15318: $confhash{$itemid}{'makeuser'} = \@makeuser;
15319: if (@makeuser) {
15320: my $lcauth = $env{'form.lti_lcauth_'.$idx};
15321: if ($lcauth =~ /^(internal|krb4|krb5|localauth)$/) {
15322: $confhash{$itemid}{'lcauth'} = $lcauth;
15323: if ($lcauth ne 'internal') {
15324: my $lcauthparm = $env{'form.lti_lcauthparm_'.$idx};
15325: $lcauthparm =~ s/^(\s+|\s+)$//g;
15326: $lcauthparm =~ s/`//g;
15327: if ($lcauthparm ne '') {
15328: $confhash{$itemid}{'lcauthparm'} = $lcauthparm;
15329: }
15330: }
15331: } else {
15332: $confhash{$itemid}{'lcauth'} = 'lti';
15333: }
1.320 raeburn 15334: }
1.345 raeburn 15335: my @possinstdata = &Apache::loncommon::get_env_multiple('form.lti_instdata_'.$idx);
15336: if (@possinstdata) {
15337: foreach my $field (@possinstdata) {
15338: if (exists($fieldtitles{$field})) {
15339: push(@{$confhash{$itemid}{'instdata'}});
1.325 raeburn 15340: }
15341: }
15342: }
1.363 raeburn 15343: if ($env{'form.lti_callback_'.$idx}) {
15344: if ($env{'form.lti_callbackparam_'.$idx}) {
15345: my $callback = $env{'form.lti_callbackparam_'.$idx};
15346: $callback =~ s/^\s+|\s+$//g;
15347: $confhash{$itemid}{'callback'} = $callback;
15348: }
15349: }
1.391 raeburn 15350: foreach my $field ('topmenu','inlinemenu') {
1.345 raeburn 15351: if ($env{'form.lti_'.$field.'_'.$idx}) {
15352: $confhash{$itemid}{$field} = 1;
15353: }
1.320 raeburn 15354: }
1.345 raeburn 15355: if ($env{'form.lti_topmenu_'.$idx} || $env{'form.lti_inlinemenu_'.$idx}) {
15356: $confhash{$itemid}{lcmenu} = [];
15357: my @possmenu = &Apache::loncommon::get_env_multiple('form.lti_menuitem_'.$idx);
15358: foreach my $field (@possmenu) {
15359: if (exists($menutitles{$field})) {
15360: if ($field eq 'grades') {
15361: next unless ($env{'form.lti_inlinemenu_'.$idx});
15362: }
15363: push(@{$confhash{$itemid}{lcmenu}},$field);
1.326 raeburn 15364: }
15365: }
15366: }
1.391 raeburn 15367: if ($confhash{$itemid}{'crsinc'}) {
15368: if (($env{'form.lti_mapcrs_'.$idx} eq 'course_offering_sourcedid') ||
15369: ($env{'form.lti_mapcrs_'.$idx} eq 'context_id')) {
15370: $confhash{$itemid}{'mapcrs'} = $env{'form.lti_mapcrs_'.$idx};
15371: } elsif ($env{'form.lti_mapcrs_'.$idx} eq 'other') {
15372: my $mapcrs = $env{'form.lti_mapcrsfield_'.$idx};
15373: $mapcrs =~ s/(`)/'/g;
15374: $mapcrs =~ s/^\s+|\s+$//g;
15375: $confhash{$itemid}{'mapcrs'} = $mapcrs;
15376: }
15377: my @posstypes = &Apache::loncommon::get_env_multiple('form.lti_mapcrstype_'.$idx);
15378: my @crstypes;
15379: foreach my $type (sort(@posstypes)) {
15380: if ($posscrstype{$type}) {
15381: push(@crstypes,$type);
15382: }
15383: }
15384: $confhash{$itemid}{'mapcrstype'} = \@crstypes;
1.392 raeburn 15385: if ($env{'form.lti_storecrs_'.$idx}) {
15386: $confhash{$itemid}{'storecrs'} = 1;
15387: }
1.391 raeburn 15388: if ($env{'form.lti_makecrs_'.$idx}) {
15389: $confhash{$itemid}{'makecrs'} = 1;
15390: }
15391: foreach my $ltirole (@lticourseroles) {
15392: my $possrole = $env{'form.lti_maprole_'.$ltirole.'_'.$idx};
15393: if (grep(/^\Q$possrole\E$/,@courseroles)) {
15394: $confhash{$itemid}{'maproles'}{$ltirole} = $possrole;
15395: }
15396: }
15397: my @possenroll = &Apache::loncommon::get_env_multiple('form.lti_selfenroll_'.$idx);
15398: my @selfenroll;
15399: foreach my $type (sort(@possenroll)) {
15400: if ($posslticrs{$type}) {
15401: push(@selfenroll,$type);
15402: }
15403: }
15404: $confhash{$itemid}{'selfenroll'} = \@selfenroll;
15405: if ($env{'form.lti_crssec_'.$idx}) {
15406: if ($env{'form.lti_crssecsrc_'.$idx} eq 'course_section_sourcedid') {
15407: $confhash{$itemid}{'section'} = $env{'form.lti_crssecsrc_'.$idx};
15408: } elsif ($env{'form.lti_crssecsrc_'.$idx} eq 'other') {
15409: my $section = $env{'form.lti_customsection_'.$idx};
15410: $section =~ s/(`)/'/g;
15411: $section =~ s/^\s+|\s+$//g;
15412: if ($section ne '') {
15413: $confhash{$itemid}{'section'} = $section;
15414: }
15415: }
15416: }
15417: foreach my $field ('passback','roster') {
15418: if ($env{'form.lti_'.$field.'_'.$idx}) {
15419: $confhash{$itemid}{$field} = 1;
15420: }
15421: }
15422: if ($env{'form.lti_passback_'.$idx}) {
15423: if ($env{'form.lti_passbackformat_'.$idx} eq '1.0') {
15424: $confhash{$itemid}{'passbackformat'} = '1.0';
15425: } else {
15426: $confhash{$itemid}{'passbackformat'} = '1.1';
1.337 raeburn 15427: }
15428: }
1.391 raeburn 15429: }
15430: unless (($idx eq 'add') || ($changes{$itemid})) {
15431: if ($confhash{$itemid}{'crsinc'}) {
1.392 raeburn 15432: foreach my $field ('mapcrs','storecrs','makecrs','section','passback','roster') {
1.424 raeburn 15433: if ($currlti{$field} ne $confhash{$itemid}{$field}) {
1.320 raeburn 15434: $changes{$itemid} = 1;
15435: }
1.345 raeburn 15436: }
15437: unless ($changes{$itemid}) {
1.424 raeburn 15438: if ($currlti{'passback'} eq $confhash{$itemid}{'passback'}) {
15439: if ($currlti{'passbackformat'} ne $confhash{$itemid}{'passbackformat'}) {
1.320 raeburn 15440: $changes{$itemid} = 1;
15441: }
15442: }
1.345 raeburn 15443: }
1.391 raeburn 15444: foreach my $field ('mapcrstype','selfenroll') {
15445: unless ($changes{$itemid}) {
1.424 raeburn 15446: if (ref($currlti{$field}) eq 'ARRAY') {
1.391 raeburn 15447: if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
1.424 raeburn 15448: my @diffs = &Apache::loncommon::compare_arrays($currlti{$field},
1.391 raeburn 15449: $confhash{$itemid}{$field});
15450: if (@diffs) {
15451: $changes{$itemid} = 1;
15452: }
1.424 raeburn 15453: } elsif (@{$currlti{$field}} > 0) {
1.391 raeburn 15454: $changes{$itemid} = 1;
15455: }
15456: } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
15457: if (@{$confhash{$itemid}{$field}} > 0) {
1.320 raeburn 15458: $changes{$itemid} = 1;
15459: }
15460: }
1.391 raeburn 15461: }
15462: }
15463: unless ($changes{$itemid}) {
1.424 raeburn 15464: if (ref($currlti{'maproles'}) eq 'HASH') {
1.391 raeburn 15465: if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
1.424 raeburn 15466: foreach my $ltirole (keys(%{$currlti{'maproles'}})) {
15467: if ($currlti{'maproles'}{$ltirole} ne
1.391 raeburn 15468: $confhash{$itemid}{'maproles'}{$ltirole}) {
1.345 raeburn 15469: $changes{$itemid} = 1;
15470: last;
15471: }
15472: }
1.391 raeburn 15473: unless ($changes{$itemid}) {
15474: foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
15475: if ($confhash{$itemid}{'maproles'}{$ltirole} ne
1.424 raeburn 15476: $currlti{'maproles'}{$ltirole}) {
1.391 raeburn 15477: $changes{$itemid} = 1;
15478: last;
15479: }
15480: }
15481: }
1.424 raeburn 15482: } elsif (keys(%{$currlti{'maproles'}}) > 0) {
1.391 raeburn 15483: $changes{$itemid} = 1;
1.345 raeburn 15484: }
1.391 raeburn 15485: } elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
15486: unless ($changes{$itemid}) {
15487: if (keys(%{$confhash{$itemid}{'maproles'}}) > 0) {
15488: $changes{$itemid} = 1;
15489: }
15490: }
15491: }
15492: }
15493: }
15494: unless ($changes{$itemid}) {
15495: foreach my $field ('mapuser','lcauth','lcauthparm','topmenu','inlinemenu','callback') {
1.424 raeburn 15496: if ($currlti{$field} ne $confhash{$itemid}{$field}) {
1.345 raeburn 15497: $changes{$itemid} = 1;
1.320 raeburn 15498: }
1.391 raeburn 15499: }
15500: unless ($changes{$itemid}) {
15501: foreach my $field ('makeuser','lcmenu') {
1.424 raeburn 15502: if (ref($currlti{$field}) eq 'ARRAY') {
1.391 raeburn 15503: if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
1.424 raeburn 15504: my @diffs = &Apache::loncommon::compare_arrays($currlti{$field},
1.391 raeburn 15505: $confhash{$itemid}{$field});
15506: if (@diffs) {
15507: $changes{$itemid} = 1;
15508: }
1.424 raeburn 15509: } elsif (@{$currlti{$field}} > 0) {
1.391 raeburn 15510: $changes{$itemid} = 1;
15511: }
15512: } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
15513: if (@{$confhash{$itemid}{$field}} > 0) {
15514: $changes{$itemid} = 1;
15515: }
1.345 raeburn 15516: }
1.320 raeburn 15517: }
15518: }
15519: }
15520: }
15521: }
1.424 raeburn 15522: if ($is_home) {
15523: my $keyitem = 'form.lti_key_'.$idx;
15524: $env{$keyitem} =~ s/(`)/'/g;
15525: if ($env{$keyitem} ne '') {
15526: $ltienc{$itemid}{'key'} = $env{$keyitem};
15527: unless ($changes{$itemid}) {
15528: if ($currlti{'key'} ne $env{$keyitem}) {
15529: $changes{$itemid} = 1;
15530: }
15531: }
15532: }
15533: my $secretitem = 'form.lti_secret_'.$idx;
15534: $env{$secretitem} =~ s/(`)/'/g;
15535: if ($currlti{'usable'}) {
15536: if ($env{'form.lti_changesecret_'.$idx}) {
15537: if ($env{$secretitem} ne '') {
15538: if ($privnum && $cipher) {
15539: $ltienc{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
15540: $confhash{$itemid}{'cipher'} = $privnum;
15541: } else {
15542: $ltienc{$itemid}{'secret'} = $env{$secretitem};
15543: }
15544: $changes{$itemid} = 1;
15545: }
15546: } else {
15547: $ltienc{$itemid}{'secret'} = $currlti{'secret'};
15548: $confhash{$itemid}{'cipher'} = $currlti{'cipher'};
15549: }
15550: if (ref($ltienc{$itemid}) eq 'HASH') {
15551: if (($ltienc{$itemid}{'key'} ne '') && ($ltienc{$itemid}{'secret'} ne '')) {
15552: $confhash{$itemid}{'usable'} = 1;
15553: }
15554: }
15555: } elsif ($env{$secretitem} ne '') {
15556: if ($privnum && $cipher) {
15557: $ltienc{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
15558: $confhash{$itemid}{'cipher'} = $privnum;
15559: } else {
15560: $ltienc{$itemid}{'secret'} = $env{$secretitem};
15561: }
15562: if (ref($ltienc{$itemid}) eq 'HASH') {
15563: if (($ltienc{$itemid}{'key'} ne '') && ($ltienc{$itemid}{'key'} ne '')) {
15564: $confhash{$itemid}{'usable'} = 1;
15565: }
15566: }
15567: $changes{$itemid} = 1;
15568: }
15569: }
15570: unless ($changes{$itemid}) {
15571: foreach my $key (keys(%currlti)) {
15572: if (ref($currlti{$key}) eq 'HASH') {
15573: if (ref($confhash{$itemid}{$key}) eq 'HASH') {
15574: foreach my $innerkey (keys(%{$currlti{$key}})) {
15575: unless (exists($confhash{$itemid}{$key}{$innerkey})) {
15576: $changes{$itemid} = 1;
15577: last;
15578: }
15579: }
15580: } elsif (keys(%{$currlti{$key}}) > 0) {
15581: $changes{$itemid} = 1;
15582: }
15583: }
15584: last if ($changes{$itemid});
15585: }
15586: }
1.320 raeburn 15587: }
15588: if (@allpos > 0) {
15589: my $idx = 0;
15590: foreach my $itemid (@allpos) {
15591: if ($itemid ne '') {
15592: $confhash{$itemid}{'order'} = $idx;
15593: if (ref($domconfig{$action}) eq 'HASH') {
15594: if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
15595: if ($domconfig{$action}{$itemid}{'order'} ne $idx) {
15596: $changes{$itemid} = 1;
15597: }
15598: }
15599: }
15600: $idx ++;
15601: }
15602: }
15603: }
1.424 raeburn 15604:
15605: if ((keys(%changes) == 0) && (keys(%secchanges) == 0)) {
15606: return &mt('No changes made.');
15607: }
15608:
1.320 raeburn 15609: my %ltihash = (
1.405 raeburn 15610: $action => { %confhash }
15611: );
1.424 raeburn 15612: my %ltienchash;
15613:
15614: if ($is_home) {
15615: %ltienchash = (
15616: $action => { %ltienc }
15617: );
15618: }
1.405 raeburn 15619: if (keys(%secchanges)) {
15620: $ltihash{'ltisec'} = \%newltisec;
1.406 raeburn 15621: if ($secchanges{'linkprot'}) {
15622: if ($is_home) {
15623: $ltienchash{'linkprot'} = \%newltienc;
15624: }
15625: }
1.405 raeburn 15626: }
15627: my $putresult = &Apache::lonnet::put_dom('configuration',\%ltihash,$dom);
1.320 raeburn 15628: if ($putresult eq 'ok') {
1.424 raeburn 15629: if (keys(%ltienchash)) {
15630: &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom,undef,1);
1.405 raeburn 15631: }
15632: $resulttext = &mt('Changes made:').'<ul>';
15633: if (keys(%secchanges) > 0) {
1.423 raeburn 15634: $resulttext .= <i_security_results($dom,'lti',\%secchanges,\%newltisec,\%newkeyset,\%keystore);
1.421 raeburn 15635: if (exists($secchanges{'linkprot'})) {
15636: $resulttext .= $linkprotoutput;
1.405 raeburn 15637: }
15638: }
1.320 raeburn 15639: if (keys(%changes) > 0) {
15640: my $cachetime = 24*60*60;
1.424 raeburn 15641: &Apache::lonnet::do_cache_new('lti',$dom,\%confhash,$cachetime);
1.320 raeburn 15642: if (ref($lastactref) eq 'HASH') {
15643: $lastactref->{'lti'} = 1;
15644: }
15645: my %bynum;
15646: foreach my $itemid (sort(keys(%changes))) {
1.424 raeburn 15647: if (ref($confhash{$itemid}) eq 'HASH') {
15648: my $position = $confhash{$itemid}{'order'};
15649: $bynum{$position} = $itemid;
15650: }
1.320 raeburn 15651: }
15652: foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
15653: my $itemid = $bynum{$pos};
1.424 raeburn 15654: if (ref($confhash{$itemid}) eq 'HASH') {
1.390 raeburn 15655: $resulttext .= '<li><b>'.$confhash{$itemid}{'consumer'}.'</b><ul>';
1.320 raeburn 15656: my $position = $pos + 1;
15657: $resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>';
15658: foreach my $item ('version','lifetime') {
15659: if ($confhash{$itemid}{$item} ne '') {
15660: $resulttext .= '<li>'.$lt{$item}.': '.$confhash{$itemid}{$item}.'</li>';
15661: }
15662: }
1.424 raeburn 15663: if ($ltienc{$itemid}{'key'} ne '') {
15664: $resulttext .= '<li>'.$lt{'key'}.': '.$ltienc{$itemid}{'key'}.'</li>';
1.320 raeburn 15665: }
1.424 raeburn 15666: if ($ltienc{$itemid}{'secret'} ne '') {
15667: $resulttext .= '<li>'.$lt{'secret'}.': ['.&mt('not shown').']</li>';
1.320 raeburn 15668: }
1.345 raeburn 15669: if ($confhash{$itemid}{'requser'}) {
1.391 raeburn 15670: if ($confhash{$itemid}{'callback'}) {
15671: $resulttext .= '<li>'.&mt('Callback setting').': '.$confhash{$itemid}{'callback'}.'</li>';
15672: } else {
1.392 raeburn 15673: $resulttext .= '<li>'.&mt('Callback to logout LON-CAPA on log out from Consumer').'</li>';
1.391 raeburn 15674: }
1.345 raeburn 15675: if ($confhash{$itemid}{'mapuser'}) {
15676: my $shownmapuser;
15677: if ($confhash{$itemid}{'mapuser'} eq 'lis_person_sourcedid') {
15678: $shownmapuser = $lt{'sourcedid'}.' (lis_person_sourcedid)';
15679: } elsif ($confhash{$itemid}{'mapuser'} eq 'lis_person_contact_email_primary') {
15680: $shownmapuser = $lt{'email'}.' (lis_person_contact_email_primary)';
15681: } else {
15682: $shownmapuser = &mt('Other').' ('.$confhash{$itemid}{'mapuser'}.')';
1.320 raeburn 15683: }
1.345 raeburn 15684: $resulttext .= '<li>'.&mt('LON-CAPA username').': '.$shownmapuser.'</li>';
1.320 raeburn 15685: }
1.345 raeburn 15686: if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
15687: if (@{$confhash{$itemid}{'makeuser'}} > 0) {
15688: $resulttext .= '<li>'.&mt('Following roles may create user accounts: [_1]',
15689: join(', ',@{$confhash{$itemid}{'makeuser'}})).'<br />';
15690: if ($confhash{$itemid}{'lcauth'} eq 'lti') {
15691: $resulttext .= &mt('New users will only be able to authenticate via LTI').'</li>';
15692: } else {
15693: $resulttext .= &mt('New users will be assigned LON-CAPA authentication: [_1]',
15694: $confhash{$itemid}{'lcauth'});
15695: if ($confhash{$itemid}{'lcauth'} eq 'internal') {
15696: $resulttext .= '; '.&mt('a randomly generated password will be created');
15697: } elsif ($confhash{$itemid}{'lcauth'} eq 'localauth') {
15698: if ($confhash{$itemid}{'lcauthparm'} ne '') {
15699: $resulttext .= ' '.&mt('with argument: [_1]',$confhash{$itemid}{'lcauthparm'});
15700: }
15701: } else {
15702: $resulttext .= '; '.&mt('Kerberos domain: [_1]',$confhash{$itemid}{'lcauthparm'});
15703: }
15704: }
15705: $resulttext .= '</li>';
15706: } else {
15707: $resulttext .= '<li>'.&mt('User account creation not permitted.').'</li>';
15708: }
1.320 raeburn 15709: }
1.345 raeburn 15710: if (ref($confhash{$itemid}{'instdata'}) eq 'ARRAY') {
15711: if (@{$confhash{$itemid}{'instdata'}} > 0) {
15712: $resulttext .= '<li>'.&mt('Institutional data will be used when creating a new user for: [_1]',
15713: join(', ',map { $fieldtitles{$_}; } @{$confhash{$itemid}{'instdata'}})).'</li>';
1.325 raeburn 15714: } else {
1.345 raeburn 15715: $resulttext .= '<li>'.&mt('No institutional data used when creating a new user.').'</li>';
1.325 raeburn 15716: }
1.320 raeburn 15717: }
1.391 raeburn 15718: foreach my $item ('topmenu','inlinemenu') {
1.345 raeburn 15719: $resulttext .= '<li>'.$lt{$item}.': ';
15720: if ($confhash{$itemid}{$item}) {
15721: $resulttext .= &mt('Yes');
15722: } else {
15723: $resulttext .= &mt('No');
1.337 raeburn 15724: }
1.345 raeburn 15725: $resulttext .= '</li>';
1.320 raeburn 15726: }
1.345 raeburn 15727: if (ref($confhash{$itemid}{'lcmenu'}) eq 'ARRAY') {
15728: if (@{$confhash{$itemid}{'lcmenu'}} > 0) {
15729: $resulttext .= '<li>'.&mt('Menu items:').' '.
1.391 raeburn 15730: join(', ', map { $menutitles{$_}; } (@{$confhash{$itemid}{'lcmenu'}})).'</li>';
15731: } else {
15732: $resulttext .= '<li>'.&mt('No menu items displayed in header or online menu').'</li>';
15733: }
15734: }
15735: if ($confhash{$itemid}{'crsinc'}) {
15736: if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
15737: my $rolemaps;
15738: foreach my $role (@ltiroles) {
15739: if ($confhash{$itemid}{'maproles'}{$role}) {
15740: $rolemaps .= (' 'x2).$role.'='.
15741: &Apache::lonnet::plaintext($confhash{$itemid}{'maproles'}{$role},
15742: 'Course').',';
15743: }
15744: }
15745: if ($rolemaps) {
15746: $rolemaps =~ s/,$//;
15747: $resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>';
15748: }
15749: }
15750: if ($confhash{$itemid}{'mapcrs'}) {
15751: $resulttext .= '<li>'.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.'</li>';
15752: }
15753: if (ref($confhash{$itemid}{'mapcrstype'}) eq 'ARRAY') {
15754: if (@{$confhash{$itemid}{'mapcrstype'}} > 0) {
15755: $resulttext .= '<li>'.&mt('Mapping for the following LON-CAPA course types: [_1]',
15756: join(', ',map { $coursetypetitles{$_}; } @coursetypes)).
15757: '</li>';
15758: } else {
15759: $resulttext .= '<li>'.&mt('No mapping to LON-CAPA courses').'</li>';
15760: }
15761: }
1.392 raeburn 15762: if ($confhash{$itemid}{'storecrs'}) {
15763: $resulttext .= '<li>'.&mt('Store mapping of course identifier to LON-CAPA CourseID').': '.$confhash{$itemid}{'storecrs'}.'</li>';
15764: }
1.391 raeburn 15765: if ($confhash{$itemid}{'makecrs'}) {
15766: $resulttext .= '<li>'.&mt('Instructor may create course (if absent).').'</li>';
15767: } else {
15768: $resulttext .= '<li>'.&mt('Instructor may not create course (if absent).').'</li>';
15769: }
15770: if (ref($confhash{$itemid}{'selfenroll'}) eq 'ARRAY') {
15771: if (@{$confhash{$itemid}{'selfenroll'}} > 0) {
15772: $resulttext .= '<li>'.&mt('Self-enrollment for following roles: [_1]',
15773: join(', ',@{$confhash{$itemid}{'selfenroll'}})).
15774: '</li>';
15775: } else {
15776: $resulttext .= '<li>'.&mt('Self-enrollment not permitted').'</li>';
15777: }
15778: }
15779: if ($confhash{$itemid}{'section'}) {
15780: if ($confhash{$itemid}{'section'} eq 'course_section_sourcedid') {
15781: $resulttext .= '<li>'.&mt('User section from standard field:').
15782: ' (course_section_sourcedid)'.'</li>';
15783: } else {
15784: $resulttext .= '<li>'.&mt('User section from:').' '.
15785: $confhash{$itemid}{'section'}.'</li>';
15786: }
1.345 raeburn 15787: } else {
1.391 raeburn 15788: $resulttext .= '<li>'.&mt('No section assignment').'</li>';
15789: }
15790: foreach my $item ('passback','roster','topmenu','inlinemenu') {
15791: $resulttext .= '<li>'.$lt{$item}.': ';
15792: if ($confhash{$itemid}{$item}) {
15793: $resulttext .= &mt('Yes');
15794: if ($item eq 'passback') {
15795: if ($confhash{$itemid}{'passbackformat'} eq '1.0') {
15796: $resulttext .= ' ('.&mt('Outcomes Extension (1.0)').')';
15797: } elsif ($confhash{$itemid}{'passbackformat'} eq '1.1') {
15798: $resulttext .= ' ('.&mt('Outcomes Service (1.1)').')';
15799: }
15800: }
15801: } else {
15802: $resulttext .= &mt('No');
15803: }
15804: $resulttext .= '</li>';
15805: }
15806: if (ref($confhash{$itemid}{'lcmenu'}) eq 'ARRAY') {
15807: if (@{$confhash{$itemid}{'lcmenu'}} > 0) {
15808: $resulttext .= '<li>'.&mt('Menu items:').' '.
15809: join(', ', map { $menutitles{$_}; } (@{$confhash{$itemid}{'lcmenu'}})).'</li>';
15810: } else {
15811: $resulttext .= '<li>'.&mt('No menu items displayed in header or online menu').'</li>';
15812: }
1.345 raeburn 15813: }
1.326 raeburn 15814: }
15815: }
1.320 raeburn 15816: $resulttext .= '</ul></li>';
15817: }
15818: }
1.424 raeburn 15819: if (keys(%deletions)) {
15820: foreach my $itemid (sort { $a <=> $b } keys(%deletions)) {
15821: $resulttext .= '<li>'.&mt('Deleted: [_1]',$changes{$itemid}).'</li>';
15822: }
15823: }
1.320 raeburn 15824: }
1.405 raeburn 15825: $resulttext .= '</ul>';
1.424 raeburn 15826: if (ref($lastactref) eq 'HASH') {
15827: if (($secchanges{'encrypt'}) || ($secchanges{'private'})) {
15828: $lastactref->{'domdefaults'} = 1;
15829: }
15830: }
1.320 raeburn 15831: } else {
15832: $errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>';
15833: }
15834: if ($errors) {
15835: $resulttext .= &mt('The following errors occurred: ').'<ul>'.
15836: $errors.'</ul>';
15837: }
15838: return $resulttext;
15839: }
15840:
1.424 raeburn 15841: sub get_priv_creds {
15842: my ($dom,$home,$encchg,$encrypt,$storedsec) = @_;
15843: my ($needenc,$cipher,$privnum);
15844: my %domdefs = &Apache::lonnet::get_domain_defaults($dom);
15845: if (($encchg) && (ref($encrypt) eq 'HASH')) {
15846: $needenc = $encrypt->{'consumers'}
15847: } else {
15848: $needenc = $domdefs{'ltienc_consumers'};
15849: }
15850: if ($needenc) {
15851: if (($storedsec eq 'ok') || ((ref($domdefs{'ltiprivhosts'}) eq 'ARRAY') &&
15852: (grep(/^\Q$home\E$/,@{$domdefs{'ltiprivhosts'}})))) {
15853: my %privhash = &Apache::lonnet::restore_dom('lti','private',$dom,$home,1);
15854: my $privkey = $privhash{'key'};
15855: $privnum = $privhash{'version'};
15856: if (($privnum) && ($privkey ne '')) {
15857: $cipher = Crypt::CBC->new({'key' => $privkey,
15858: 'cipher' => 'DES'});
15859: }
15860: }
15861: }
15862: return ($cipher,$privnum);
15863: }
15864:
1.320 raeburn 15865: sub get_lti_id {
15866: my ($domain,$consumer) = @_;
15867: # get lock on lti db
15868: my $lockhash = {
15869: lock => $env{'user.name'}.
15870: ':'.$env{'user.domain'},
15871: };
15872: my $tries = 0;
15873: my $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
15874: my ($id,$error);
15875:
15876: while (($gotlock ne 'ok') && ($tries<10)) {
15877: $tries ++;
15878: sleep (0.1);
15879: $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
15880: }
15881: if ($gotlock eq 'ok') {
15882: my %currids = &Apache::lonnet::dump_dom('lti',$domain);
15883: if ($currids{'lock'}) {
15884: delete($currids{'lock'});
15885: if (keys(%currids)) {
15886: my @curr = sort { $a <=> $b } keys(%currids);
15887: if ($curr[-1] =~ /^\d+$/) {
15888: $id = 1 + $curr[-1];
15889: }
15890: } else {
15891: $id = 1;
15892: }
15893: if ($id) {
15894: unless (&Apache::lonnet::newput_dom('lti',{ $id => $consumer },$domain) eq 'ok') {
15895: $error = 'nostore';
15896: }
15897: } else {
15898: $error = 'nonumber';
15899: }
15900: }
15901: my $dellockoutcome = &Apache::lonnet::del_dom('lti',['lock'],$domain);
15902: } else {
15903: $error = 'nolock';
15904: }
15905: return ($id,$error);
15906: }
15907:
1.3 raeburn 15908: sub modify_autoenroll {
1.205 raeburn 15909: my ($dom,$lastactref,%domconfig) = @_;
1.1 raeburn 15910: my ($resulttext,%changes);
15911: my %currautoenroll;
15912: if (ref($domconfig{'autoenroll'}) eq 'HASH') {
15913: foreach my $key (keys(%{$domconfig{'autoenroll'}})) {
15914: $currautoenroll{$key} = $domconfig{'autoenroll'}{$key};
15915: }
15916: }
15917: my $autorun = &Apache::lonnet::auto_run(undef,$dom),
15918: my %title = ( run => 'Auto-enrollment active',
1.129 raeburn 15919: sender => 'Sender for notification messages',
1.274 raeburn 15920: coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',
1.399 raeburn 15921: autofailsafe => 'Failsafe for no drops if institutional data missing for a section');
1.1 raeburn 15922: my @offon = ('off','on');
1.17 raeburn 15923: my $sender_uname = $env{'form.sender_uname'};
15924: my $sender_domain = $env{'form.sender_domain'};
15925: if ($sender_domain eq '') {
15926: $sender_uname = '';
15927: } elsif ($sender_uname eq '') {
15928: $sender_domain = '';
15929: }
1.129 raeburn 15930: my $coowners = $env{'form.autoassign_coowners'};
1.399 raeburn 15931: my $autofailsafe = $env{'form.autoenroll_autofailsafe'};
15932: $autofailsafe =~ s{^\s+|\s+$}{}g;
15933: if ($autofailsafe =~ /\D/) {
15934: undef($autofailsafe);
15935: }
1.274 raeburn 15936: my $failsafe = $env{'form.autoenroll_failsafe'};
1.399 raeburn 15937: unless (($failsafe eq 'zero') || ($failsafe eq 'any')) {
15938: $failsafe = 'off';
1.400 raeburn 15939: undef($autofailsafe);
1.274 raeburn 15940: }
1.1 raeburn 15941: my %autoenrollhash = (
1.129 raeburn 15942: autoenroll => { 'run' => $env{'form.autoenroll_run'},
15943: 'sender_uname' => $sender_uname,
15944: 'sender_domain' => $sender_domain,
15945: 'co-owners' => $coowners,
1.399 raeburn 15946: 'autofailsafe' => $autofailsafe,
1.400 raeburn 15947: 'failsafe' => $failsafe,
1.1 raeburn 15948: }
15949: );
1.4 raeburn 15950: my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
15951: $dom);
1.1 raeburn 15952: if ($putresult eq 'ok') {
15953: if (exists($currautoenroll{'run'})) {
15954: if ($currautoenroll{'run'} ne $env{'form.autoenroll_run'}) {
15955: $changes{'run'} = 1;
15956: }
15957: } elsif ($autorun) {
15958: if ($env{'form.autoenroll_run'} ne '1') {
1.23 raeburn 15959: $changes{'run'} = 1;
1.1 raeburn 15960: }
15961: }
1.17 raeburn 15962: if ($currautoenroll{'sender_uname'} ne $sender_uname) {
1.1 raeburn 15963: $changes{'sender'} = 1;
15964: }
1.17 raeburn 15965: if ($currautoenroll{'sender_domain'} ne $sender_domain) {
1.1 raeburn 15966: $changes{'sender'} = 1;
15967: }
1.129 raeburn 15968: if ($currautoenroll{'co-owners'} ne '') {
15969: if ($currautoenroll{'co-owners'} ne $coowners) {
15970: $changes{'coowners'} = 1;
15971: }
15972: } elsif ($coowners) {
15973: $changes{'coowners'} = 1;
1.274 raeburn 15974: }
1.399 raeburn 15975: if ($currautoenroll{'autofailsafe'} ne $autofailsafe) {
1.274 raeburn 15976: $changes{'autofailsafe'} = 1;
15977: }
1.399 raeburn 15978: if ($currautoenroll{'failsafe'} ne $failsafe) {
15979: $changes{'failsafe'} = 1;
15980: }
1.1 raeburn 15981: if (keys(%changes) > 0) {
15982: $resulttext = &mt('Changes made:').'<ul>';
1.3 raeburn 15983: if ($changes{'run'}) {
1.1 raeburn 15984: $resulttext .= '<li>'.&mt("$title{'run'} set to $offon[$env{'form.autoenroll_run'}]").'</li>';
15985: }
15986: if ($changes{'sender'}) {
1.17 raeburn 15987: if ($sender_uname eq '' || $sender_domain eq '') {
15988: $resulttext .= '<li>'.&mt("$title{'sender'} set to default (course owner).").'</li>';
15989: } else {
15990: $resulttext .= '<li>'.&mt("$title{'sender'} set to [_1]",$sender_uname.':'.$sender_domain).'</li>';
15991: }
1.1 raeburn 15992: }
1.129 raeburn 15993: if ($changes{'coowners'}) {
15994: $resulttext .= '<li>'.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'</li>';
15995: &Apache::loncommon::devalidate_domconfig_cache($dom);
1.212 raeburn 15996: if (ref($lastactref) eq 'HASH') {
15997: $lastactref->{'domainconfig'} = 1;
15998: }
1.129 raeburn 15999: }
1.274 raeburn 16000: if ($changes{'autofailsafe'}) {
1.399 raeburn 16001: if ($autofailsafe ne '') {
16002: $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section set to: [_1]',$autofailsafe).'</li>';
1.274 raeburn 16003: } else {
1.399 raeburn 16004: $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section not in use').'</li>';
1.274 raeburn 16005: }
1.399 raeburn 16006: }
16007: if ($changes{'failsafe'}) {
16008: if ($failsafe eq 'off') {
16009: unless ($changes{'autofailsafe'}) {
16010: $resulttext .= '<li>'.&mt('Failsafe for no drops if institutional data missing for a section not in use').'</li>';
16011: }
16012: } elsif ($failsafe eq 'zero') {
16013: $resulttext .= '<li>'.&mt('Failsafe applies if retrieved section enrollment is zero').'</li>';
16014: } else {
16015: $resulttext .= '<li>'.&mt('Failsafe applies if retrieved section enrollment is zero or greater').'</li>';
16016: }
16017: }
16018: if (($changes{'autofailsafe'}) || ($changes{'failsafe'})) {
1.274 raeburn 16019: &Apache::lonnet::get_domain_defaults($dom,1);
16020: if (ref($lastactref) eq 'HASH') {
16021: $lastactref->{'domdefaults'} = 1;
16022: }
16023: }
1.1 raeburn 16024: $resulttext .= '</ul>';
16025: } else {
16026: $resulttext = &mt('No changes made to auto-enrollment settings');
16027: }
16028: } else {
1.11 albertel 16029: $resulttext = '<span class="LC_error">'.
16030: &mt('An error occurred: [_1]',$putresult).'</span>';
1.1 raeburn 16031: }
1.3 raeburn 16032: return $resulttext;
1.1 raeburn 16033: }
16034:
16035: sub modify_autoupdate {
1.3 raeburn 16036: my ($dom,%domconfig) = @_;
1.1 raeburn 16037: my ($resulttext,%currautoupdate,%fields,%changes);
16038: if (ref($domconfig{'autoupdate'}) eq 'HASH') {
16039: foreach my $key (keys(%{$domconfig{'autoupdate'}})) {
16040: $currautoupdate{$key} = $domconfig{'autoupdate'}{$key};
16041: }
16042: }
16043: my @offon = ('off','on');
16044: my %title = &Apache::lonlocal::texthash (
1.385 raeburn 16045: run => 'Auto-update:',
16046: classlists => 'Updates to user information in classlists?',
16047: unexpired => 'Skip updates for users without active or future roles?',
16048: lastactive => 'Skip updates for inactive users?',
1.1 raeburn 16049: );
1.44 raeburn 16050: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.1 raeburn 16051: my %fieldtitles = &Apache::lonlocal::texthash (
16052: id => 'Student/Employee ID',
1.20 raeburn 16053: permanentemail => 'E-mail address',
1.1 raeburn 16054: lastname => 'Last Name',
16055: firstname => 'First Name',
16056: middlename => 'Middle Name',
1.132 raeburn 16057: generation => 'Generation',
1.1 raeburn 16058: );
1.142 raeburn 16059: $othertitle = &mt('All users');
1.1 raeburn 16060: if (keys(%{$usertypes}) > 0) {
1.26 raeburn 16061: $othertitle = &mt('Other users');
1.1 raeburn 16062: }
16063: foreach my $key (keys(%env)) {
16064: if ($key =~ /^form\.updateable_(.+)_([^_]+)$/) {
1.132 raeburn 16065: my ($usertype,$item) = ($1,$2);
16066: if (grep(/^\Q$item\E$/,keys(%fieldtitles))) {
16067: if ($usertype eq 'default') {
16068: push(@{$fields{$1}},$2);
16069: } elsif (ref($types) eq 'ARRAY') {
16070: if (grep(/^\Q$usertype\E$/,@{$types})) {
16071: push(@{$fields{$1}},$2);
16072: }
16073: }
16074: }
1.1 raeburn 16075: }
16076: }
1.131 raeburn 16077: my @lockablenames = &Apache::loncommon::get_env_multiple('form.lockablenames');
16078: @lockablenames = sort(@lockablenames);
16079: if (ref($currautoupdate{'lockablenames'}) eq 'ARRAY') {
16080: my @changed = &Apache::loncommon::compare_arrays($currautoupdate{'lockablenames'},\@lockablenames);
16081: if (@changed) {
16082: $changes{'lockablenames'} = 1;
16083: }
16084: } else {
16085: if (@lockablenames) {
16086: $changes{'lockablenames'} = 1;
16087: }
16088: }
1.1 raeburn 16089: my %updatehash = (
16090: autoupdate => { run => $env{'form.autoupdate_run'},
16091: classlists => $env{'form.classlists'},
1.385 raeburn 16092: unexpired => $env{'form.unexpired'},
1.1 raeburn 16093: fields => {%fields},
1.131 raeburn 16094: lockablenames => \@lockablenames,
1.1 raeburn 16095: }
16096: );
1.385 raeburn 16097: my $lastactivedays;
16098: if ($env{'form.lastactive'}) {
16099: $lastactivedays = $env{'form.lastactivedays'};
16100: $lastactivedays =~ s/^\s+|\s+$//g;
16101: unless ($lastactivedays =~ /^\d+$/) {
16102: undef($lastactivedays);
16103: $env{'form.lastactive'} = 0;
16104: }
16105: }
16106: $updatehash{'autoupdate'}{'lastactive'} = $lastactivedays;
1.1 raeburn 16107: foreach my $key (keys(%currautoupdate)) {
1.385 raeburn 16108: if (($key eq 'run') || ($key eq 'classlists') || ($key eq 'unexpired') || ($key eq 'lastactive')) {
1.1 raeburn 16109: if (exists($updatehash{autoupdate}{$key})) {
16110: if ($currautoupdate{$key} ne $updatehash{autoupdate}{$key}) {
16111: $changes{$key} = 1;
16112: }
16113: }
16114: } elsif ($key eq 'fields') {
16115: if (ref($currautoupdate{$key}) eq 'HASH') {
1.26 raeburn 16116: foreach my $item (@{$types},'default') {
1.1 raeburn 16117: if (ref($currautoupdate{$key}{$item}) eq 'ARRAY') {
16118: my $change = 0;
16119: foreach my $type (@{$currautoupdate{$key}{$item}}) {
16120: if (!exists($fields{$item})) {
16121: $change = 1;
1.132 raeburn 16122: last;
1.1 raeburn 16123: } elsif (ref($fields{$item}) eq 'ARRAY') {
1.26 raeburn 16124: if (!grep(/^\Q$type\E$/,@{$fields{$item}})) {
1.1 raeburn 16125: $change = 1;
1.132 raeburn 16126: last;
1.1 raeburn 16127: }
16128: }
16129: }
16130: if ($change) {
16131: push(@{$changes{$key}},$item);
16132: }
1.26 raeburn 16133: }
1.1 raeburn 16134: }
16135: }
1.131 raeburn 16136: } elsif ($key eq 'lockablenames') {
16137: if (ref($currautoupdate{$key}) eq 'ARRAY') {
16138: my @changed = &Apache::loncommon::compare_arrays($currautoupdate{'lockablenames'},\@lockablenames);
16139: if (@changed) {
16140: $changes{'lockablenames'} = 1;
16141: }
16142: } else {
16143: if (@lockablenames) {
16144: $changes{'lockablenames'} = 1;
16145: }
16146: }
16147: }
16148: }
16149: unless (grep(/^\Qlockablenames\E$/,keys(%currautoupdate))) {
16150: if (@lockablenames) {
16151: $changes{'lockablenames'} = 1;
1.1 raeburn 16152: }
16153: }
1.385 raeburn 16154: unless (grep(/^unexpired$/,keys(%currautoupdate))) {
16155: if ($updatehash{'autoupdate'}{'unexpired'}) {
16156: $changes{'unexpired'} = 1;
16157: }
16158: }
16159: unless (grep(/^lastactive$/,keys(%currautoupdate))) {
16160: if ($updatehash{'autoupdate'}{'lastactive'} ne '') {
16161: $changes{'lastactive'} = 1;
16162: }
16163: }
1.26 raeburn 16164: foreach my $item (@{$types},'default') {
16165: if (defined($fields{$item})) {
16166: if (ref($currautoupdate{'fields'}) eq 'HASH') {
1.132 raeburn 16167: if (ref($currautoupdate{'fields'}{$item}) eq 'ARRAY') {
16168: my $change = 0;
16169: if (ref($fields{$item}) eq 'ARRAY') {
16170: foreach my $type (@{$fields{$item}}) {
16171: if (!grep(/^\Q$type\E$/,@{$currautoupdate{'fields'}{$item}})) {
16172: $change = 1;
16173: last;
16174: }
16175: }
16176: }
16177: if ($change) {
16178: push(@{$changes{'fields'}},$item);
16179: }
16180: } else {
1.26 raeburn 16181: push(@{$changes{'fields'}},$item);
16182: }
16183: } else {
16184: push(@{$changes{'fields'}},$item);
1.1 raeburn 16185: }
16186: }
16187: }
16188: my $putresult = &Apache::lonnet::put_dom('configuration',\%updatehash,
16189: $dom);
16190: if ($putresult eq 'ok') {
16191: if (keys(%changes) > 0) {
16192: $resulttext = &mt('Changes made:').'<ul>';
16193: foreach my $key (sort(keys(%changes))) {
1.131 raeburn 16194: if ($key eq 'lockablenames') {
16195: $resulttext .= '<li>';
16196: if (@lockablenames) {
16197: $usertypes->{'default'} = $othertitle;
16198: $resulttext .= &mt("User preference to disable replacement of user's name with institutional data (by auto-update), available for the following affiliations:").' '.
16199: join(', ', map { $usertypes->{$_}; } @lockablenames).'</li>';
16200: } else {
16201: $resulttext .= &mt("User preference to disable replacement of user's name with institutional data (by auto-update) is unavailable.");
16202: }
16203: $resulttext .= '</li>';
16204: } elsif (ref($changes{$key}) eq 'ARRAY') {
1.1 raeburn 16205: foreach my $item (@{$changes{$key}}) {
16206: my @newvalues;
16207: foreach my $type (@{$fields{$item}}) {
16208: push(@newvalues,$fieldtitles{$type});
16209: }
1.3 raeburn 16210: my $newvaluestr;
16211: if (@newvalues > 0) {
16212: $newvaluestr = join(', ',@newvalues);
16213: } else {
16214: $newvaluestr = &mt('none');
1.6 raeburn 16215: }
1.1 raeburn 16216: if ($item eq 'default') {
1.26 raeburn 16217: $resulttext .= '<li>'.&mt("Updates for '[_1]' set to: '[_2]'",$othertitle,$newvaluestr).'</li>';
1.1 raeburn 16218: } else {
1.26 raeburn 16219: $resulttext .= '<li>'.&mt("Updates for '[_1]' set to: '[_2]'",$usertypes->{$item},$newvaluestr).'</li>';
1.1 raeburn 16220: }
16221: }
16222: } else {
16223: my $newvalue;
16224: if ($key eq 'run') {
16225: $newvalue = $offon[$env{'form.autoupdate_run'}];
1.385 raeburn 16226: } elsif ($key eq 'lastactive') {
16227: $newvalue = $offon[$env{'form.lastactive'}];
16228: unless ($lastactivedays eq '') {
16229: $newvalue .= '; '.&mt('inactive = no activity in last [quant,_1,day]',$lastactivedays);
16230: }
1.1 raeburn 16231: } else {
16232: $newvalue = $offon[$env{'form.'.$key}];
1.3 raeburn 16233: }
1.1 raeburn 16234: $resulttext .= '<li>'.&mt("[_1] set to $newvalue",$title{$key}).'</li>';
16235: }
16236: }
16237: $resulttext .= '</ul>';
16238: } else {
1.3 raeburn 16239: $resulttext = &mt('No changes made to autoupdates');
1.1 raeburn 16240: }
16241: } else {
1.11 albertel 16242: $resulttext = '<span class="LC_error">'.
16243: &mt('An error occurred: [_1]',$putresult).'</span>';
1.1 raeburn 16244: }
1.3 raeburn 16245: return $resulttext;
1.1 raeburn 16246: }
16247:
1.125 raeburn 16248: sub modify_autocreate {
16249: my ($dom,%domconfig) = @_;
16250: my ($resulttext,%changes,%currautocreate,%newvals,%autocreatehash);
16251: if (ref($domconfig{'autocreate'}) eq 'HASH') {
16252: foreach my $key (keys(%{$domconfig{'autocreate'}})) {
16253: $currautocreate{$key} = $domconfig{'autocreate'}{$key};
16254: }
16255: }
16256: my %title= ( xml => 'Auto-creation of courses in XML course description files',
16257: req => 'Auto-creation of validated requests for official courses',
16258: xmldc => 'Identity of course creator of courses from XML files',
16259: );
16260: my @types = ('xml','req');
16261: foreach my $item (@types) {
16262: $newvals{$item} = $env{'form.autocreate_'.$item};
16263: $newvals{$item} =~ s/\D//g;
16264: $newvals{$item} = 0 if ($newvals{$item} eq '');
16265: }
16266: $newvals{'xmldc'} = $env{'form.autocreate_xmldc'};
1.285 raeburn 16267: my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
1.125 raeburn 16268: unless (exists($domcoords{$newvals{'xmldc'}})) {
16269: $newvals{'xmldc'} = '';
16270: }
16271: %autocreatehash = (
16272: autocreate => { xml => $newvals{'xml'},
16273: req => $newvals{'req'},
16274: }
16275: );
16276: if ($newvals{'xmldc'} ne '') {
16277: $autocreatehash{'autocreate'}{'xmldc'} = $newvals{'xmldc'};
16278: }
16279: my $putresult = &Apache::lonnet::put_dom('configuration',\%autocreatehash,
16280: $dom);
16281: if ($putresult eq 'ok') {
16282: my @items = @types;
16283: if ($newvals{'xml'}) {
16284: push(@items,'xmldc');
16285: }
16286: foreach my $item (@items) {
16287: if (exists($currautocreate{$item})) {
16288: if ($currautocreate{$item} ne $newvals{$item}) {
16289: $changes{$item} = 1;
16290: }
16291: } elsif ($newvals{$item}) {
16292: $changes{$item} = 1;
16293: }
16294: }
16295: if (keys(%changes) > 0) {
16296: my @offon = ('off','on');
16297: $resulttext = &mt('Changes made:').'<ul>';
16298: foreach my $item (@types) {
16299: if ($changes{$item}) {
16300: my $newtxt = $offon[$newvals{$item}];
1.178 raeburn 16301: $resulttext .= '<li>'.
16302: &mt("$title{$item} set to [_1]$newtxt [_2]",
16303: '<b>','</b>').
16304: '</li>';
1.125 raeburn 16305: }
16306: }
16307: if ($changes{'xmldc'}) {
16308: my ($dcname,$dcdom) = split(':',$newvals{'xmldc'});
16309: my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom);
1.178 raeburn 16310: $resulttext .= '<li>'.&mt("$title{'xmldc'} set to [_1]",'<b>'.$newtxt.'</b>').'</li>';
1.125 raeburn 16311: }
16312: $resulttext .= '</ul>';
16313: } else {
16314: $resulttext = &mt('No changes made to auto-creation settings');
16315: }
16316: } else {
16317: $resulttext = '<span class="LC_error">'.
16318: &mt('An error occurred: [_1]',$putresult).'</span>';
16319: }
16320: return $resulttext;
16321: }
16322:
1.23 raeburn 16323: sub modify_directorysrch {
1.295 raeburn 16324: my ($dom,$lastactref,%domconfig) = @_;
1.23 raeburn 16325: my ($resulttext,%changes);
16326: my %currdirsrch;
16327: if (ref($domconfig{'directorysrch'}) eq 'HASH') {
16328: foreach my $key (keys(%{$domconfig{'directorysrch'}})) {
16329: $currdirsrch{$key} = $domconfig{'directorysrch'}{$key};
16330: }
16331: }
1.277 raeburn 16332: my %title = ( available => 'Institutional directory search available',
16333: localonly => 'Other domains can search institution',
16334: lcavailable => 'LON-CAPA directory search available',
1.289 raeburn 16335: lclocalonly => 'Other domains can search LON-CAPA domain',
1.23 raeburn 16336: searchby => 'Search types',
16337: searchtypes => 'Search latitude');
16338: my @offon = ('off','on');
1.24 raeburn 16339: my @otherdoms = ('Yes','No');
1.23 raeburn 16340:
1.25 raeburn 16341: my @searchtypes = &Apache::loncommon::get_env_multiple('form.searchtypes');
1.23 raeburn 16342: my @cansearch = &Apache::loncommon::get_env_multiple('form.cansearch');
16343: my @searchby = &Apache::loncommon::get_env_multiple('form.searchby');
16344:
1.44 raeburn 16345: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.26 raeburn 16346: if (keys(%{$usertypes}) == 0) {
16347: @cansearch = ('default');
16348: } else {
16349: if (ref($currdirsrch{'cansearch'}) eq 'ARRAY') {
16350: foreach my $type (@{$currdirsrch{'cansearch'}}) {
16351: if (!grep(/^\Q$type\E$/,@cansearch)) {
16352: push(@{$changes{'cansearch'}},$type);
16353: }
1.23 raeburn 16354: }
1.26 raeburn 16355: foreach my $type (@cansearch) {
16356: if (!grep(/^\Q$type\E$/,@{$currdirsrch{'cansearch'}})) {
16357: push(@{$changes{'cansearch'}},$type);
16358: }
1.23 raeburn 16359: }
1.26 raeburn 16360: } else {
16361: push(@{$changes{'cansearch'}},@cansearch);
1.23 raeburn 16362: }
16363: }
16364:
16365: if (ref($currdirsrch{'searchby'}) eq 'ARRAY') {
16366: foreach my $by (@{$currdirsrch{'searchby'}}) {
16367: if (!grep(/^\Q$by\E$/,@searchby)) {
16368: push(@{$changes{'searchby'}},$by);
16369: }
16370: }
16371: foreach my $by (@searchby) {
16372: if (!grep(/^\Q$by\E$/,@{$currdirsrch{'searchby'}})) {
16373: push(@{$changes{'searchby'}},$by);
16374: }
16375: }
16376: } else {
16377: push(@{$changes{'searchby'}},@searchby);
16378: }
1.25 raeburn 16379:
16380: if (ref($currdirsrch{'searchtypes'}) eq 'ARRAY') {
16381: foreach my $type (@{$currdirsrch{'searchtypes'}}) {
16382: if (!grep(/^\Q$type\E$/,@searchtypes)) {
16383: push(@{$changes{'searchtypes'}},$type);
16384: }
16385: }
16386: foreach my $type (@searchtypes) {
16387: if (!grep(/^\Q$type\E$/,@{$currdirsrch{'searchtypes'}})) {
16388: push(@{$changes{'searchtypes'}},$type);
16389: }
16390: }
16391: } else {
16392: if (exists($currdirsrch{'searchtypes'})) {
16393: foreach my $type (@searchtypes) {
16394: if ($type ne $currdirsrch{'searchtypes'}) {
16395: push(@{$changes{'searchtypes'}},$type);
16396: }
16397: }
16398: if (!grep(/^\Q$currdirsrch{'searchtypes'}\E/,@searchtypes)) {
16399: push(@{$changes{'searchtypes'}},$currdirsrch{'searchtypes'});
16400: }
16401: } else {
16402: push(@{$changes{'searchtypes'}},@searchtypes);
16403: }
16404: }
16405:
1.23 raeburn 16406: my %dirsrch_hash = (
16407: directorysrch => { available => $env{'form.dirsrch_available'},
16408: cansearch => \@cansearch,
1.277 raeburn 16409: localonly => $env{'form.dirsrch_instlocalonly'},
16410: lclocalonly => $env{'form.dirsrch_domlocalonly'},
16411: lcavailable => $env{'form.dirsrch_domavailable'},
1.23 raeburn 16412: searchby => \@searchby,
1.25 raeburn 16413: searchtypes => \@searchtypes,
1.23 raeburn 16414: }
16415: );
16416: my $putresult = &Apache::lonnet::put_dom('configuration',\%dirsrch_hash,
16417: $dom);
16418: if ($putresult eq 'ok') {
16419: if (exists($currdirsrch{'available'})) {
16420: if ($currdirsrch{'available'} ne $env{'form.dirsrch_available'}) {
16421: $changes{'available'} = 1;
16422: }
16423: } else {
16424: if ($env{'form.dirsrch_available'} eq '1') {
16425: $changes{'available'} = 1;
16426: }
16427: }
1.277 raeburn 16428: if (exists($currdirsrch{'lcavailable'})) {
1.289 raeburn 16429: if ($currdirsrch{'lcavailable'} ne $env{'form.dirsrch_domavailable'}) {
16430: $changes{'lcavailable'} = 1;
16431: }
1.277 raeburn 16432: } else {
16433: if ($env{'form.dirsrch_lcavailable'} eq '1') {
16434: $changes{'lcavailable'} = 1;
16435: }
16436: }
1.24 raeburn 16437: if (exists($currdirsrch{'localonly'})) {
1.289 raeburn 16438: if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_instlocalonly'}) {
16439: $changes{'localonly'} = 1;
16440: }
1.24 raeburn 16441: } else {
1.277 raeburn 16442: if ($env{'form.dirsrch_instlocalonly'} eq '1') {
1.24 raeburn 16443: $changes{'localonly'} = 1;
16444: }
16445: }
1.277 raeburn 16446: if (exists($currdirsrch{'lclocalonly'})) {
1.289 raeburn 16447: if ($currdirsrch{'lclocalonly'} ne $env{'form.dirsrch_domlocalonly'}) {
16448: $changes{'lclocalonly'} = 1;
16449: }
1.277 raeburn 16450: } else {
16451: if ($env{'form.dirsrch_domlocalonly'} eq '1') {
16452: $changes{'lclocalonly'} = 1;
16453: }
16454: }
1.23 raeburn 16455: if (keys(%changes) > 0) {
16456: $resulttext = &mt('Changes made:').'<ul>';
16457: if ($changes{'available'}) {
16458: $resulttext .= '<li>'.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'</li>';
16459: }
1.277 raeburn 16460: if ($changes{'lcavailable'}) {
16461: $resulttext .= '<li>'.&mt("$title{'lcavailable'} set to: $offon[$env{'form.dirsrch_domavailable'}]").'</li>';
16462: }
1.24 raeburn 16463: if ($changes{'localonly'}) {
1.277 raeburn 16464: $resulttext .= '<li>'.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_instlocalonly'}]").'</li>';
1.24 raeburn 16465: }
1.277 raeburn 16466: if ($changes{'lclocalonly'}) {
16467: $resulttext .= '<li>'.&mt("$title{'lclocalonly'} set to: $otherdoms[$env{'form.dirsrch_domlocalonly'}]").'</li>';
1.289 raeburn 16468: }
1.23 raeburn 16469: if (ref($changes{'cansearch'}) eq 'ARRAY') {
16470: my $chgtext;
1.26 raeburn 16471: if (ref($usertypes) eq 'HASH') {
16472: if (keys(%{$usertypes}) > 0) {
16473: foreach my $type (@{$types}) {
16474: if (grep(/^\Q$type\E$/,@cansearch)) {
16475: $chgtext .= $usertypes->{$type}.'; ';
16476: }
16477: }
16478: if (grep(/^default$/,@cansearch)) {
16479: $chgtext .= $othertitle;
16480: } else {
16481: $chgtext =~ s/\; $//;
16482: }
1.210 raeburn 16483: $resulttext .=
1.178 raeburn 16484: '<li>'.
16485: &mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]",
16486: '<span class="LC_cusr_emph">'.$dom.'</span>',$chgtext).
16487: '</li>';
1.23 raeburn 16488: }
16489: }
16490: }
16491: if (ref($changes{'searchby'}) eq 'ARRAY') {
16492: my ($searchtitles,$titleorder) = &sorted_searchtitles();
16493: my $chgtext;
16494: foreach my $type (@{$titleorder}) {
16495: if (grep(/^\Q$type\E$/,@searchby)) {
16496: if (defined($searchtitles->{$type})) {
16497: $chgtext .= $searchtitles->{$type}.'; ';
16498: }
16499: }
16500: }
16501: $chgtext =~ s/\; $//;
16502: $resulttext .= '<li>'.&mt("$title{'searchby'} set to: [_1]",$chgtext).'</li>';
16503: }
1.25 raeburn 16504: if (ref($changes{'searchtypes'}) eq 'ARRAY') {
16505: my ($srchtypes_desc,$srchtypeorder) = &sorted_searchtypes();
16506: my $chgtext;
16507: foreach my $type (@{$srchtypeorder}) {
16508: if (grep(/^\Q$type\E$/,@searchtypes)) {
16509: if (defined($srchtypes_desc->{$type})) {
16510: $chgtext .= $srchtypes_desc->{$type}.'; ';
16511: }
16512: }
16513: }
16514: $chgtext =~ s/\; $//;
1.178 raeburn 16515: $resulttext .= '<li>'.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'</li>';
1.23 raeburn 16516: }
16517: $resulttext .= '</ul>';
1.295 raeburn 16518: &Apache::lonnet::do_cache_new('directorysrch',$dom,$dirsrch_hash{'directorysrch'},3600);
16519: if (ref($lastactref) eq 'HASH') {
16520: $lastactref->{'directorysrch'} = 1;
16521: }
1.23 raeburn 16522: } else {
1.277 raeburn 16523: $resulttext = &mt('No changes made to directory search settings');
1.23 raeburn 16524: }
16525: } else {
16526: $resulttext = '<span class="LC_error">'.
1.27 raeburn 16527: &mt('An error occurred: [_1]',$putresult).'</span>';
16528: }
16529: return $resulttext;
16530: }
16531:
1.28 raeburn 16532: sub modify_contacts {
1.205 raeburn 16533: my ($dom,$lastactref,%domconfig) = @_;
1.28 raeburn 16534: my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash);
16535: if (ref($domconfig{'contacts'}) eq 'HASH') {
16536: foreach my $key (keys(%{$domconfig{'contacts'}})) {
16537: $currsetting{$key} = $domconfig{'contacts'}{$key};
16538: }
16539: }
1.286 raeburn 16540: my (%others,%to,%bcc,%includestr,%includeloc);
1.28 raeburn 16541: my @contacts = ('supportemail','adminemail');
1.286 raeburn 16542: my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',
1.350 raeburn 16543: 'lonstatusmail','requestsmail','updatesmail','idconflictsmail','hostipmail');
1.340 raeburn 16544: my @toggles = ('reporterrors','reportupdates','reportstatus');
16545: my @lonstatus = ('threshold','sysmail','weights','excluded');
1.286 raeburn 16546: my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
1.28 raeburn 16547: foreach my $type (@mailings) {
16548: @{$newsetting{$type}} =
16549: &Apache::loncommon::get_env_multiple('form.'.$type);
16550: foreach my $item (@contacts) {
16551: if (grep(/^\Q$item\E$/,@{$newsetting{$type}})) {
16552: $contacts_hash{contacts}{$type}{$item} = 1;
16553: } else {
16554: $contacts_hash{contacts}{$type}{$item} = 0;
16555: }
1.289 raeburn 16556: }
1.28 raeburn 16557: $others{$type} = $env{'form.'.$type.'_others'};
16558: $contacts_hash{contacts}{$type}{'others'} = $others{$type};
1.286 raeburn 16559: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
1.134 raeburn 16560: $bcc{$type} = $env{'form.'.$type.'_bcc'};
16561: $contacts_hash{contacts}{$type}{'bcc'} = $bcc{$type};
1.286 raeburn 16562: if (($env{'form.'.$type.'_includestr'} ne '') && ($env{'form.'.$type.'_includeloc'} =~ /^s|b$/)) {
16563: $includestr{$type} = $env{'form.'.$type.'_includestr'};
16564: $includeloc{$type} = $env{'form.'.$type.'_includeloc'};
16565: $contacts_hash{contacts}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});
16566: }
1.134 raeburn 16567: }
1.28 raeburn 16568: }
16569: foreach my $item (@contacts) {
16570: $to{$item} = $env{'form.'.$item};
16571: $contacts_hash{'contacts'}{$item} = $to{$item};
16572: }
1.203 raeburn 16573: foreach my $item (@toggles) {
16574: if ($env{'form.'.$item} =~ /^(0|1)$/) {
16575: $contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
16576: }
16577: }
1.340 raeburn 16578: my ($lonstatus_defs,$lonstatus_names) = &Apache::loncommon::lon_status_items();
16579: foreach my $item (@lonstatus) {
16580: if ($item eq 'excluded') {
16581: my (%serverhomes,@excluded);
16582: map { $serverhomes{$_} = 1; } values(%Apache::lonnet::serverhomeIDs);
16583: my @possexcluded = &Apache::loncommon::get_env_multiple('form.errorexcluded');
16584: if (@possexcluded) {
16585: foreach my $id (sort(@possexcluded)) {
16586: if ($serverhomes{$id}) {
16587: push(@excluded,$id);
16588: }
16589: }
16590: }
16591: if (@excluded) {
16592: $contacts_hash{'contacts'}{'lonstatus'}{$item} = \@excluded;
16593: }
16594: } elsif ($item eq 'weights') {
1.377 raeburn 16595: foreach my $type ('E','W','N','U') {
1.340 raeburn 16596: $env{'form.error'.$item.'_'.$type} =~ s/^\s+|\s+$//g;
16597: if ($env{'form.error'.$item.'_'.$type} =~ /^\d+$/) {
16598: unless ($env{'form.error'.$item.'_'.$type} == $lonstatus_defs->{$type}) {
16599: $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type} =
16600: $env{'form.error'.$item.'_'.$type};
16601: }
16602: }
16603: }
16604: } elsif (($item eq 'threshold') || ($item eq 'sysmail')) {
16605: $env{'form.error'.$item} =~ s/^\s+|\s+$//g;
16606: if ($env{'form.error'.$item} =~ /^\d+$/) {
16607: unless ($env{'form.error'.$item} == $lonstatus_defs->{$item}) {
16608: $contacts_hash{'contacts'}{'lonstatus'}{$item} = $env{'form.error'.$item};
16609: }
16610: }
16611: }
16612: }
1.286 raeburn 16613: if ((ref($fields) eq 'ARRAY') && (ref($possoptions) eq 'HASH')) {
16614: foreach my $field (@{$fields}) {
16615: if (ref($possoptions->{$field}) eq 'ARRAY') {
16616: my $value = $env{'form.helpform_'.$field};
16617: $value =~ s/^\s+|\s+$//g;
16618: if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {
1.315 raeburn 16619: $contacts_hash{'contacts'}{'helpform'}{$field} = $value;
1.286 raeburn 16620: if ($field eq 'screenshot') {
16621: $env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;
16622: if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {
1.315 raeburn 16623: $contacts_hash{'contacts'}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};
1.286 raeburn 16624: }
16625: }
16626: }
16627: }
16628: }
16629: }
1.315 raeburn 16630: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
16631: my (@statuses,%usertypeshash,@overrides);
16632: if ((ref($types) eq 'ARRAY') && (@{$types} > 0)) {
16633: @statuses = @{$types};
16634: if (ref($usertypes) eq 'HASH') {
16635: %usertypeshash = %{$usertypes};
16636: }
16637: }
16638: if (@statuses) {
16639: my @possoverrides = &Apache::loncommon::get_env_multiple('form.overrides');
16640: foreach my $type (@possoverrides) {
16641: if (($type ne '') && (grep(/^\Q$type\E$/,@statuses))) {
16642: push(@overrides,$type);
16643: }
16644: }
16645: if (@overrides) {
16646: foreach my $type (@overrides) {
16647: my @standard = &Apache::loncommon::get_env_multiple('form.override_'.$type);
16648: foreach my $item (@contacts) {
16649: if (grep(/^\Q$item\E$/,@standard)) {
16650: $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 1;
16651: $newsetting{'override_'.$type}{$item} = 1;
16652: } else {
16653: $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 0;
16654: $newsetting{'override_'.$type}{$item} = 0;
16655: }
16656: }
16657: $contacts_hash{'contacts'}{'overrides'}{$type}{'others'} = $env{'form.override_'.$type.'_others'};
16658: $contacts_hash{'contacts'}{'overrides'}{$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};
16659: $newsetting{'override_'.$type}{'others'} = $env{'form.override_'.$type.'_others'};
16660: $newsetting{'override_'.$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};
16661: if (($env{'form.override_'.$type.'_includestr'} ne '') && ($env{'form.override_'.$type.'_includeloc'} =~ /^s|b$/)) {
16662: $includestr{$type} = $env{'form.override_'.$type.'_includestr'};
16663: $includeloc{$type} = $env{'form.override_'.$type.'_includeloc'};
16664: $contacts_hash{'contacts'}{'overrides'}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});
16665: $newsetting{'override_'.$type}{'include'} = $contacts_hash{'contacts'}{'overrides'}{$type}{'include'};
16666: }
1.425 raeburn 16667: }
1.315 raeburn 16668: }
16669: }
1.28 raeburn 16670: if (keys(%currsetting) > 0) {
16671: foreach my $item (@contacts) {
16672: if ($to{$item} ne $currsetting{$item}) {
16673: $changes{$item} = 1;
16674: }
16675: }
16676: foreach my $type (@mailings) {
16677: foreach my $item (@contacts) {
16678: if (ref($currsetting{$type}) eq 'HASH') {
16679: if ($currsetting{$type}{$item} ne $contacts_hash{contacts}{$type}{$item}) {
16680: push(@{$changes{$type}},$item);
16681: }
16682: } else {
16683: push(@{$changes{$type}},@{$newsetting{$type}});
16684: }
16685: }
16686: if ($others{$type} ne $currsetting{$type}{'others'}) {
16687: push(@{$changes{$type}},'others');
16688: }
1.289 raeburn 16689: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
1.134 raeburn 16690: if ($bcc{$type} ne $currsetting{$type}{'bcc'}) {
16691: push(@{$changes{$type}},'bcc');
16692: }
1.286 raeburn 16693: my ($currloc,$currstr) = split(/:/,$currsetting{$type}{'include'},2);
16694: if (($includeloc{$type} ne $currloc) || (&escape($includestr{$type}) ne $currstr)) {
16695: push(@{$changes{$type}},'include');
16696: }
16697: }
16698: }
16699: if (ref($fields) eq 'ARRAY') {
16700: if (ref($currsetting{'helpform'}) eq 'HASH') {
16701: foreach my $field (@{$fields}) {
16702: if ($currsetting{'helpform'}{$field} ne $contacts_hash{'contacts'}{'helpform'}{$field}) {
16703: push(@{$changes{'helpform'}},$field);
16704: }
16705: if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
16706: if ($currsetting{'helpform'}{'maxsize'} ne $contacts_hash{'contacts'}{'helpform'}{'maxsize'}) {
16707: push(@{$changes{'helpform'}},'maxsize');
16708: }
16709: }
16710: }
16711: } else {
16712: foreach my $field (@{$fields}) {
16713: if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {
16714: push(@{$changes{'helpform'}},$field);
16715: }
16716: if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
16717: if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {
16718: push(@{$changes{'helpform'}},'maxsize');
16719: }
16720: }
16721: }
1.134 raeburn 16722: }
1.28 raeburn 16723: }
1.315 raeburn 16724: if (@statuses) {
1.425 raeburn 16725: if (ref($currsetting{'overrides'}) eq 'HASH') {
1.315 raeburn 16726: foreach my $key (keys(%{$currsetting{'overrides'}})) {
16727: if (ref($currsetting{'overrides'}{$key}) eq 'HASH') {
16728: if (ref($newsetting{'override_'.$key}) eq 'HASH') {
16729: foreach my $item (@contacts,'bcc','others','include') {
1.425 raeburn 16730: if ($currsetting{'overrides'}{$key}{$item} ne $newsetting{'override_'.$key}{$item}) {
1.315 raeburn 16731: push(@{$changes{'overrides'}},$key);
16732: last;
16733: }
16734: }
16735: } else {
16736: push(@{$changes{'overrides'}},$key);
16737: }
16738: }
16739: }
16740: foreach my $key (@overrides) {
16741: unless (exists($currsetting{'overrides'}{$key})) {
16742: push(@{$changes{'overrides'}},$key);
16743: }
16744: }
16745: } else {
16746: foreach my $key (@overrides) {
1.425 raeburn 16747: push(@{$changes{'overrides'}},$key);
1.315 raeburn 16748: }
16749: }
16750: }
1.340 raeburn 16751: if (ref($currsetting{'lonstatus'}) eq 'HASH') {
16752: foreach my $key ('excluded','weights','threshold','sysmail') {
16753: if ($key eq 'excluded') {
16754: if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&
16755: (ref($contacts_hash{contacts}{lonstatus}{excluded}) eq 'ARRAY')) {
16756: if ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&
16757: (@{$currsetting{'lonstatus'}{$key}})) {
16758: my @diffs =
16759: &Apache::loncommon::compare_arrays($contacts_hash{contacts}{lonstatus}{excluded},
16760: $currsetting{'lonstatus'}{$key});
16761: if (@diffs) {
16762: push(@{$changes{'lonstatus'}},$key);
16763: }
16764: } elsif (@{$contacts_hash{contacts}{lonstatus}{excluded}}) {
16765: push(@{$changes{'lonstatus'}},$key);
16766: }
16767: } elsif ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&
16768: (@{$currsetting{'lonstatus'}{$key}})) {
16769: push(@{$changes{'lonstatus'}},$key);
16770: }
16771: } elsif ($key eq 'weights') {
16772: if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&
16773: (ref($contacts_hash{contacts}{lonstatus}{$key}) eq 'HASH')) {
16774: if (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {
1.341 raeburn 16775: foreach my $type ('E','W','N','U') {
1.340 raeburn 16776: unless ($contacts_hash{contacts}{lonstatus}{$key}{$type} eq
16777: $currsetting{'lonstatus'}{$key}{$type}) {
16778: push(@{$changes{'lonstatus'}},$key);
16779: last;
16780: }
16781: }
16782: } else {
1.341 raeburn 16783: foreach my $type ('E','W','N','U') {
1.340 raeburn 16784: if ($contacts_hash{contacts}{lonstatus}{$key}{$type} ne '') {
16785: push(@{$changes{'lonstatus'}},$key);
16786: last;
16787: }
16788: }
16789: }
16790: } elsif (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {
1.341 raeburn 16791: foreach my $type ('E','W','N','U') {
1.340 raeburn 16792: if ($currsetting{'lonstatus'}{$key}{$type} ne '') {
16793: push(@{$changes{'lonstatus'}},$key);
16794: last;
16795: }
16796: }
16797: }
16798: } elsif (($key eq 'threshold') || ($key eq 'sysmail')) {
16799: if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
16800: if ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {
16801: if ($currsetting{'lonstatus'}{$key} != $contacts_hash{contacts}{lonstatus}{$key}) {
16802: push(@{$changes{'lonstatus'}},$key);
16803: }
16804: } elsif ($contacts_hash{contacts}{lonstatus}{$key} =~ /^\d+$/) {
16805: push(@{$changes{'lonstatus'}},$key);
16806: }
16807: } elsif ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {
16808: push(@{$changes{'lonstatus'}},$key);
16809: }
16810: }
16811: }
16812: } else {
16813: if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
16814: foreach my $key ('excluded','weights','threshold','sysmail') {
16815: if (exists($contacts_hash{contacts}{lonstatus}{$key})) {
16816: push(@{$changes{'lonstatus'}},$key);
16817: }
16818: }
16819: }
16820: }
1.28 raeburn 16821: } else {
16822: my %default;
16823: $default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
16824: $default{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'};
16825: $default{'errormail'} = 'adminemail';
16826: $default{'packagesmail'} = 'adminemail';
16827: $default{'helpdeskmail'} = 'supportemail';
1.286 raeburn 16828: $default{'otherdomsmail'} = 'supportemail';
1.89 raeburn 16829: $default{'lonstatusmail'} = 'adminemail';
1.102 raeburn 16830: $default{'requestsmail'} = 'adminemail';
1.190 raeburn 16831: $default{'updatesmail'} = 'adminemail';
1.350 raeburn 16832: $default{'hostipmail'} = 'adminemail';
1.28 raeburn 16833: foreach my $item (@contacts) {
16834: if ($to{$item} ne $default{$item}) {
1.286 raeburn 16835: $changes{$item} = 1;
1.203 raeburn 16836: }
1.28 raeburn 16837: }
16838: foreach my $type (@mailings) {
16839: if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) {
16840: push(@{$changes{$type}},@{$newsetting{$type}});
16841: }
16842: if ($others{$type} ne '') {
16843: push(@{$changes{$type}},'others');
1.134 raeburn 16844: }
1.286 raeburn 16845: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
1.134 raeburn 16846: if ($bcc{$type} ne '') {
16847: push(@{$changes{$type}},'bcc');
16848: }
1.286 raeburn 16849: if (($includeloc{$type} =~ /^b|s$/) && ($includestr{$type} ne '')) {
16850: push(@{$changes{$type}},'include');
16851: }
1.134 raeburn 16852: }
1.28 raeburn 16853: }
1.286 raeburn 16854: if (ref($fields) eq 'ARRAY') {
16855: foreach my $field (@{$fields}) {
16856: if ($contacts_hash{'contacts'}{'helpform'}{$field} ne 'yes') {
16857: push(@{$changes{'helpform'}},$field);
16858: }
16859: if (($field eq 'screenshot') && ($contacts_hash{'contacts'}{'helpform'}{'screenshot'} ne 'no')) {
16860: if ($contacts_hash{'contacts'}{'helpform'}{'maxsize'} != 1) {
16861: push(@{$changes{'helpform'}},'maxsize');
16862: }
16863: }
16864: }
1.289 raeburn 16865: }
1.340 raeburn 16866: if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
16867: foreach my $key ('excluded','weights','threshold','sysmail') {
16868: if (exists($contacts_hash{contacts}{lonstatus}{$key})) {
16869: push(@{$changes{'lonstatus'}},$key);
16870: }
16871: }
16872: }
1.28 raeburn 16873: }
1.203 raeburn 16874: foreach my $item (@toggles) {
16875: if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) {
16876: $changes{$item} = 1;
16877: } elsif ((!$env{'form.'.$item}) &&
16878: (($currsetting{$item} eq '') || ($currsetting{$item} == 1))) {
16879: $changes{$item} = 1;
16880: }
16881: }
1.28 raeburn 16882: my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash,
16883: $dom);
16884: if ($putresult eq 'ok') {
16885: if (keys(%changes) > 0) {
1.205 raeburn 16886: &Apache::loncommon::devalidate_domconfig_cache($dom);
1.212 raeburn 16887: if (ref($lastactref) eq 'HASH') {
16888: $lastactref->{'domainconfig'} = 1;
16889: }
1.28 raeburn 16890: my ($titles,$short_titles) = &contact_titles();
16891: $resulttext = &mt('Changes made:').'<ul>';
16892: foreach my $item (@contacts) {
16893: if ($changes{$item}) {
16894: $resulttext .= '<li>'.$titles->{$item}.
16895: &mt(' set to: ').
16896: '<span class="LC_cusr_emph">'.
16897: $to{$item}.'</span></li>';
16898: }
16899: }
16900: foreach my $type (@mailings) {
16901: if (ref($changes{$type}) eq 'ARRAY') {
1.286 raeburn 16902: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
1.289 raeburn 16903: $resulttext .= '<li>'.$titles->{$type}.' -- '.&mt('sent to').': ';
1.286 raeburn 16904: } else {
16905: $resulttext .= '<li>'.$titles->{$type}.': ';
16906: }
1.28 raeburn 16907: my @text;
16908: foreach my $item (@{$newsetting{$type}}) {
16909: push(@text,$short_titles->{$item});
16910: }
16911: if ($others{$type} ne '') {
16912: push(@text,$others{$type});
16913: }
1.286 raeburn 16914: if (@text) {
16915: $resulttext .= '<span class="LC_cusr_emph">'.
16916: join(', ',@text).'</span>';
16917: }
16918: if (($type eq 'helpdeskmail') || ($type eq 'otherdomsmail')) {
1.134 raeburn 16919: if ($bcc{$type} ne '') {
1.286 raeburn 16920: my $bcctext;
16921: if (@text) {
1.289 raeburn 16922: $bcctext = ' '.&mt('with Bcc to');
1.286 raeburn 16923: } else {
16924: $bcctext = '(Bcc)';
16925: }
16926: $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$bcc{$type}.'</span>';
16927: } elsif (!@text) {
16928: $resulttext .= &mt('No one');
1.425 raeburn 16929: }
1.289 raeburn 16930: if ($includestr{$type} ne '') {
1.286 raeburn 16931: if ($includeloc{$type} eq 'b') {
16932: $resulttext .= '<br />'.&mt('Text automatically added to e-mail body:').' '.$includestr{$type};
16933: } elsif ($includeloc{$type} eq 's') {
16934: $resulttext .= '<br />'.&mt('Text automatically added to e-mail subject:').' '.$includestr{$type};
16935: }
1.134 raeburn 16936: }
1.286 raeburn 16937: } elsif (!@text) {
16938: $resulttext .= &mt('No recipients');
1.134 raeburn 16939: }
16940: $resulttext .= '</li>';
1.28 raeburn 16941: }
16942: }
1.315 raeburn 16943: if (ref($changes{'overrides'}) eq 'ARRAY') {
16944: my @deletions;
16945: foreach my $type (@{$changes{'overrides'}}) {
16946: if ($usertypeshash{$type}) {
16947: if (grep(/^\Q$type\E/,@overrides)) {
16948: $resulttext .= '<li>'.&mt("Overrides based on requester's affiliation set for [_1]",
16949: $usertypeshash{$type}).'<ul><li>';
16950: if (ref($newsetting{'override_'.$type}) eq 'HASH') {
16951: my @text;
16952: foreach my $item (@contacts) {
1.425 raeburn 16953: if ($newsetting{'override_'.$type}{$item}) {
1.315 raeburn 16954: push(@text,$short_titles->{$item});
16955: }
16956: }
16957: if ($newsetting{'override_'.$type}{'others'} ne '') {
16958: push(@text,$newsetting{'override_'.$type}{'others'});
16959: }
1.425 raeburn 16960:
1.315 raeburn 16961: if (@text) {
16962: $resulttext .= &mt('Helpdesk e-mail sent to: [_1]',
16963: '<span class="LC_cusr_emph">'.join(', ',@text).'</span>');
16964: }
16965: if ($newsetting{'override_'.$type}{'bcc'} ne '') {
16966: my $bcctext;
16967: if (@text) {
16968: $bcctext = ' '.&mt('with Bcc to');
16969: } else {
16970: $bcctext = '(Bcc)';
16971: }
16972: $resulttext .= $bcctext.': <span class="LC_cusr_emph">'.$newsetting{'override_'.$type}{'bcc'}.'</span>';
16973: } elsif (!@text) {
16974: $resulttext .= &mt('Helpdesk e-mail sent to no one');
16975: }
16976: $resulttext .= '</li>';
16977: if ($newsetting{'override_'.$type}{'include'} ne '') {
16978: my ($loc,$str) = split(/:/,$newsetting{'override_'.$type}{'include'});
16979: if ($loc eq 'b') {
16980: $resulttext .= '<li>'.&mt('Text automatically added to e-mail body:').' '.&unescape($str).'</li>';
16981: } elsif ($loc eq 's') {
16982: $resulttext .= '<li>'.&mt('Text automatically added to e-mail subject:').' '.&unescape($str).'</li>';
16983: }
16984: }
16985: }
16986: $resulttext .= '</li></ul></li>';
16987: } else {
16988: push(@deletions,$usertypeshash{$type});
16989: }
16990: }
16991: }
16992: if (@deletions) {
16993: $resulttext .= '<li>'.&mt("Overrides based on requester's affiliation discontinued for: [_1]",
16994: join(', ',@deletions)).'</li>';
16995: }
16996: }
1.203 raeburn 16997: my @offon = ('off','on');
1.340 raeburn 16998: my $corelink = &core_link_msu();
1.203 raeburn 16999: if ($changes{'reporterrors'}) {
17000: $resulttext .= '<li>'.
17001: &mt('E-mail error reports to [_1] set to "'.
17002: $offon[$env{'form.reporterrors'}].'".',
1.340 raeburn 17003: $corelink).
1.203 raeburn 17004: '</li>';
17005: }
17006: if ($changes{'reportupdates'}) {
17007: $resulttext .= '<li>'.
17008: &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.
17009: $offon[$env{'form.reportupdates'}].'".',
1.340 raeburn 17010: $corelink).
1.203 raeburn 17011: '</li>';
17012: }
1.340 raeburn 17013: if ($changes{'reportstatus'}) {
17014: $resulttext .= '<li>'.
17015: &mt('E-mail status if errors above threshold to [_1] set to "'.
17016: $offon[$env{'form.reportstatus'}].'".',
17017: $corelink).
17018: '</li>';
17019: }
17020: if (ref($changes{'lonstatus'}) eq 'ARRAY') {
17021: $resulttext .= '<li>'.
17022: &mt('Nightly status check e-mail settings').':<ul>';
17023: my (%defval,%use_def,%shown);
17024: $defval{'threshold'} = $lonstatus_defs->{'threshold'};
17025: $defval{'sysmail'} = $lonstatus_defs->{'sysmail'};
17026: $defval{'weights'} =
1.341 raeburn 17027: join(', ',map { $lonstatus_names->{$_}.'='.$lonstatus_defs->{$_}; } ('E','W','N','U'));
1.340 raeburn 17028: $defval{'excluded'} = &mt('None');
17029: if (ref($contacts_hash{'contacts'}{'lonstatus'}) eq 'HASH') {
17030: foreach my $item ('threshold','sysmail','weights','excluded') {
17031: if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item})) {
17032: if (($item eq 'threshold') || ($item eq 'sysmail')) {
17033: $shown{$item} = $contacts_hash{'contacts'}{'lonstatus'}{$item};
17034: } elsif ($item eq 'weights') {
17035: if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'HASH') {
1.341 raeburn 17036: foreach my $type ('E','W','N','U') {
1.340 raeburn 17037: $shown{$item} .= $lonstatus_names->{$type}.'=';
17038: if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item}{$type})) {
17039: $shown{$item} .= $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type};
17040: } else {
17041: $shown{$item} .= $lonstatus_defs->{$type};
17042: }
17043: $shown{$item} .= ', ';
17044: }
17045: $shown{$item} =~ s/, $//;
17046: } else {
17047: $shown{$item} = $defval{$item};
17048: }
17049: } elsif ($item eq 'excluded') {
17050: if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'ARRAY') {
17051: $shown{$item} = join(', ',@{$contacts_hash{'contacts'}{'lonstatus'}{$item}});
17052: } else {
17053: $shown{$item} = $defval{$item};
17054: }
17055: }
17056: } else {
17057: $shown{$item} = $defval{$item};
17058: }
17059: }
17060: } else {
17061: foreach my $item ('threshold','weights','excluded','sysmail') {
17062: $shown{$item} = $defval{$item};
17063: }
17064: }
17065: foreach my $item ('threshold','weights','excluded','sysmail') {
17066: $resulttext .= '<li>'.&mt($titles->{'error'.$item}.' -- [_1]',
17067: $shown{$item}).'</li>';
17068: }
17069: $resulttext .= '</ul></li>';
17070: }
1.286 raeburn 17071: if ((ref($changes{'helpform'}) eq 'ARRAY') && (ref($fields) eq 'ARRAY')) {
17072: my (@optional,@required,@unused,$maxsizechg);
17073: foreach my $field (@{$changes{'helpform'}}) {
17074: if ($field eq 'maxsize') {
17075: $maxsizechg = 1;
17076: next;
17077: }
17078: if ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'yes') {
1.289 raeburn 17079: push(@optional,$field);
1.286 raeburn 17080: } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'no') {
17081: push(@unused,$field);
17082: } elsif ($contacts_hash{'contacts'}{'helpform'}{$field} eq 'req') {
1.289 raeburn 17083: push(@required,$field);
1.286 raeburn 17084: }
17085: }
17086: if (@optional) {
17087: $resulttext .= '<li>'.
17088: &mt('Help form fields changed to "Optional": [_1].',
17089: '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @optional)).'</span>'.
17090: '</li>';
17091: }
17092: if (@required) {
17093: $resulttext .= '<li>'.
17094: &mt('Help form fields changed to "Required": [_1].',
17095: '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @required)).'</span>'.
17096: '</li>';
17097: }
17098: if (@unused) {
17099: $resulttext .= '<li>'.
17100: &mt('Help form fields changed to "Not shown": [_1].',
17101: '<span class="LC_cusr_emph">'.join(', ',map { $fieldtitles->{$_}; } @unused)).'</span>'.
17102: '</li>';
17103: }
17104: if ($maxsizechg) {
17105: $resulttext .= '<li>'.
17106: &mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',
17107: $contacts_hash{'contacts'}{'helpform'}{'maxsize'}).
17108: '</li>';
17109: }
17110: }
1.28 raeburn 17111: $resulttext .= '</ul>';
17112: } else {
1.288 raeburn 17113: $resulttext = &mt('No changes made to contacts and form settings');
1.28 raeburn 17114: }
17115: } else {
17116: $resulttext = '<span class="LC_error">'.
17117: &mt('An error occurred: [_1].',$putresult).'</span>';
17118: }
17119: return $resulttext;
17120: }
17121:
1.357 raeburn 17122: sub modify_privacy {
1.427 raeburn 17123: my ($dom,$lastactref,%domconfig) = @_;
1.357 raeburn 17124: my ($resulttext,%current,%changes);
17125: if (ref($domconfig{'privacy'}) eq 'HASH') {
17126: %current = %{$domconfig{'privacy'}};
17127: }
17128: my @fields = ('lastname','firstname','middlename','generation','permanentemail','id');
17129: my @items = ('domain','author','course','community');
17130: my %names = &Apache::lonlocal::texthash (
17131: domain => 'Assigned domain role(s)',
17132: author => 'Assigned co-author role(s)',
17133: course => 'Assigned course role(s)',
1.416 raeburn 17134: community => 'Assigned community role(s)',
1.357 raeburn 17135: );
17136: my %roles = &Apache::lonlocal::texthash (
17137: domain => 'Domain role',
17138: author => 'Co-author role',
17139: course => 'Course role',
17140: community => 'Community role',
17141: );
17142: my %titles = &Apache::lonlocal::texthash (
17143: approval => 'Approval for role in different domain',
17144: othdom => 'User information available in other domain',
17145: priv => 'Information viewable by privileged user in same domain',
17146: unpriv => 'Information viewable by unprivileged user in same domain',
17147: instdom => 'Other domain shares institution/provider',
17148: extdom => 'Other domain has different institution/provider',
17149: none => 'Not allowed',
17150: user => 'User authorizes',
17151: domain => 'Domain Coordinator authorizes',
17152: auto => 'Unrestricted',
1.418 raeburn 17153: notify => 'Notify when role needs authorization',
1.357 raeburn 17154: );
17155: my %fieldnames = &Apache::lonlocal::texthash (
17156: id => 'Student/Employee ID',
17157: permanentemail => 'E-mail address',
17158: lastname => 'Last Name',
17159: firstname => 'First Name',
17160: middlename => 'Middle Name',
17161: generation => 'Generation',
17162: );
17163: my ($othertitle,$usertypes,$types) =
17164: &Apache::loncommon::sorted_inst_types($dom);
17165: my (%by_ip,%by_location,@intdoms,@instdoms);
17166: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
17167:
17168: my %privacyhash = (
17169: 'approval' => {
17170: instdom => {},
17171: extdom => {},
17172: },
17173: 'othdom' => {},
17174: 'priv' => {},
17175: 'unpriv' => {},
17176: );
17177: foreach my $item (@items) {
17178: if (@instdoms > 1) {
1.416 raeburn 17179: if ($env{'form.privacy_approval_instdom_'.$item} =~ /^(none|user|domain|auto)$/) {
1.357 raeburn 17180: $privacyhash{'approval'}{'instdom'}{$item} = $env{'form.privacy_approval_instdom_'.$item};
17181: }
17182: if (ref($current{'approval'}) eq 'HASH') {
17183: if (ref($current{'approval'}{'instdom'}) eq 'HASH') {
17184: unless ($privacyhash{'approval'}{'instdom'}{$item} eq $current{'approval'}{'instdom'}{$item}) {
17185: $changes{'approval'} = 1;
17186: }
17187: }
17188: } elsif ($privacyhash{'approval'}{'instdom'}{$item} ne 'auto') {
17189: $changes{'approval'} = 1;
17190: }
17191: }
17192: if (keys(%by_location) > 0) {
17193: if ($env{'form.privacy_approval_extdom_'.$item} =~ /^(none|user|domain|auto)$/) {
17194: $privacyhash{'approval'}{'extdom'}{$item} = $env{'form.privacy_approval_extdom_'.$item};
17195: }
17196: if (ref($current{'approval'}) eq 'HASH') {
17197: if (ref($current{'approval'}{'extdom'}) eq 'HASH') {
17198: unless ($privacyhash{'approval'}{'extdom'}{$item} eq $current{'approval'}{'extdom'}{$item}) {
17199: $changes{'approval'} = 1;
17200: }
17201: }
17202: } elsif ($privacyhash{'approval'}{'extdom'}{$item} ne 'auto') {
17203: $changes{'approval'} = 1;
17204: }
17205: }
17206: foreach my $status ('priv','unpriv') {
17207: my @possibles = sort(&Apache::loncommon::get_env_multiple('form.privacy_'.$status.'_'.$item));
17208: my @newvalues;
17209: foreach my $field (@possibles) {
17210: if (grep(/^\Q$field\E$/,@fields)) {
17211: $privacyhash{$status}{$item}{$field} = 1;
17212: push(@newvalues,$field);
17213: }
17214: }
17215: @newvalues = sort(@newvalues);
17216: if (ref($current{$status}) eq 'HASH') {
17217: if (ref($current{$status}{$item}) eq 'HASH') {
17218: my @currvalues = sort(keys(%{$current{$status}{$item}}));
17219: my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
17220: if (@diffs > 0) {
17221: $changes{$status} = 1;
17222: }
17223: }
17224: } else {
17225: my @stdfields;
17226: foreach my $field (@fields) {
17227: if ($field eq 'id') {
17228: next if ($status eq 'unpriv');
17229: next if (($status eq 'priv') && ($item eq 'community'));
17230: }
17231: push(@stdfields,$field);
17232: }
17233: my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
17234: if (@diffs > 0) {
17235: $changes{$status} = 1;
17236: }
17237: }
17238: }
17239: }
17240: if ((@instdoms > 1) || (keys(%by_location) > 0)) {
17241: my @statuses;
17242: if (ref($types) eq 'ARRAY') {
17243: @statuses = @{$types};
17244: }
17245: foreach my $type (@statuses,'default') {
17246: my @possfields = &Apache::loncommon::get_env_multiple('form.privacy_othdom_'.$type);
17247: my @newvalues;
17248: foreach my $field (sort(@possfields)) {
17249: if (grep(/^\Q$field\E$/,@fields)) {
17250: $privacyhash{'othdom'}{$type}{$field} = 1;
17251: push(@newvalues,$field);
17252: }
17253: }
17254: @newvalues = sort(@newvalues);
17255: if (ref($current{'othdom'}) eq 'HASH') {
17256: if (ref($current{'othdom'}{$type}) eq 'HASH') {
17257: my @currvalues = sort(keys(%{$current{'othdom'}{$type}}));
17258: my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
17259: if (@diffs > 0) {
17260: $changes{'othdom'} = 1;
17261: }
17262: }
17263: } else {
17264: my @stdfields = ('lastname','firstname','middlename','generation','permanentemail');
17265: my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
17266: if (@diffs > 0) {
17267: $changes{'othdom'} = 1;
17268: }
17269: }
17270: }
1.417 raeburn 17271: my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
17272: my %notify;
17273: foreach my $possdc (&Apache::loncommon::get_env_multiple('form.privacy_notify')) {
17274: if (exists($domcoords{$possdc})) {
17275: $notify{$possdc} = 1;
17276: }
17277: }
17278: my $notify = join(',',sort(keys(%notify)));
17279: if ($current{'notify'} ne $notify) {
17280: $changes{'notify'} = 1;
17281: }
17282: $privacyhash{'notify'} = $notify;
1.357 raeburn 17283: }
17284: my %confighash = (
17285: privacy => \%privacyhash,
17286: );
17287: my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);
17288: if ($putresult eq 'ok') {
17289: if (keys(%changes) > 0) {
17290: $resulttext = &mt('Changes made: ').'<ul>';
1.417 raeburn 17291: foreach my $key ('approval','notify','othdom','priv','unpriv') {
1.357 raeburn 17292: if ($changes{$key}) {
17293: $resulttext .= '<li>'.$titles{$key}.':<ul>';
17294: if ($key eq 'approval') {
17295: if (keys(%{$privacyhash{$key}{instdom}})) {
17296: $resulttext .= '<li>'.$titles{'instdom'}.'<ul>';
17297: foreach my $item (@items) {
17298: $resulttext .= '<li>'.$roles{$item}.': '.$titles{$privacyhash{$key}{instdom}{$item}}.'</li>';
17299: }
17300: $resulttext .= '</ul></li>';
17301: }
17302: if (keys(%{$privacyhash{$key}{extdom}})) {
17303: $resulttext .= '<li>'.$titles{'extdom'}.'<ul>';
17304: foreach my $item (@items) {
17305: $resulttext .= '<li>'.$roles{$item}.': '.$titles{$privacyhash{$key}{extdom}{$item}}.'</li>';
17306: }
17307: $resulttext .= '</ul></li>';
17308: }
1.417 raeburn 17309: } elsif ($key eq 'notify') {
17310: if ($privacyhash{$key}) {
17311: foreach my $dc (split(/,/,$privacyhash{$key})) {
17312: my ($dcname,$dcdom) = split(/:/,$dc);
17313: $resulttext .= '<li>'.&Apache::loncommon::plainname($dcname,$dcdom).'</li>';
17314: }
17315: } else {
17316: $resulttext .= '<li>'.&mt('No DCs to notify').'</li>';
17317: }
1.357 raeburn 17318: } elsif ($key eq 'othdom') {
17319: my @statuses;
17320: if (ref($types) eq 'ARRAY') {
17321: @statuses = @{$types};
17322: }
17323: if (ref($privacyhash{$key}) eq 'HASH') {
17324: foreach my $status (@statuses,'default') {
17325: if ($status eq 'default') {
17326: $resulttext .= '<li>'.$othertitle.': ';
17327: } elsif (ref($usertypes) eq 'HASH') {
17328: $resulttext .= '<li>'.$usertypes->{$status}.': ';
17329: } else {
17330: next;
17331: }
17332: if (ref($privacyhash{$key}{$status}) eq 'HASH') {
17333: if (keys(%{$privacyhash{$key}{$status}})) {
17334: $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$status}}))));
17335: } else {
17336: $resulttext .= &mt('none');
17337: }
17338: }
17339: $resulttext .= '</li>';
17340: }
17341: }
17342: } else {
17343: foreach my $item (@items) {
17344: if (ref($privacyhash{$key}{$item}) eq 'HASH') {
17345: $resulttext .= '<li>'.$names{$item}.': ';
17346: if (keys(%{$privacyhash{$key}{$item}})) {
17347: $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$item}}))));
17348: } else {
17349: $resulttext .= &mt('none');
17350: }
17351: $resulttext .= '</li>';
17352: }
17353: }
17354: }
17355: $resulttext .= '</ul></li>';
17356: }
17357: }
1.421 raeburn 17358: $resulttext .= '</ul>';
1.427 raeburn 17359: if ($changes{'approval'}) {
17360: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
17361: delete($domdefaults{'userapprovals'});
17362: if (ref($privacyhash{'approval'}) eq 'HASH') {
17363: foreach my $domtype ('instdom','extdom') {
17364: if (ref($privacyhash{'approval'}{$domtype}) eq 'HASH') {
17365: foreach my $roletype ('domain','author','course','community') {
17366: if ($privacyhash{'approval'}{$domtype}{$roletype} eq 'user') {
17367: $domdefaults{'userapprovals'} = 1;
17368: last;
17369: }
17370: }
17371: }
17372: last if ($domdefaults{'userapprovals'});
17373: }
17374: }
17375: my $cachetime = 24*60*60;
17376: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
17377: if (ref($lastactref) eq 'HASH') {
17378: $lastactref->{'domdefaults'} = 1;
17379: }
17380: }
1.357 raeburn 17381: } else {
17382: $resulttext = &mt('No changes made to user information settings');
17383: }
17384: } else {
17385: $resulttext = '<span class="LC_error">'.
17386: &mt('An error occurred: [_1]',$putresult).'</span>';
17387: }
17388: return $resulttext;
17389: }
17390:
1.354 raeburn 17391: sub modify_passwords {
17392: my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
1.355 raeburn 17393: my ($resulttext,%current,%changes,%newvalues,@oktypes,$errors,
17394: $updatedefaults,$updateconf);
1.354 raeburn 17395: my $customfn = 'resetpw.html';
17396: if (ref($domconfig{'passwords'}) eq 'HASH') {
17397: %current = %{$domconfig{'passwords'}};
17398: }
17399: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
17400: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
17401: if (ref($types) eq 'ARRAY') {
17402: @oktypes = @{$types};
17403: }
17404: push(@oktypes,'default');
17405:
17406: my %titles = &Apache::lonlocal::texthash (
17407: intauth_cost => 'Encryption cost for bcrypt (positive integer)',
17408: intauth_check => 'Check bcrypt cost if authenticated',
17409: intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',
17410: permanent => 'Permanent e-mail address',
17411: critical => 'Critical notification address',
17412: notify => 'Notification address',
17413: min => 'Minimum password length',
17414: max => 'Maximum password length',
17415: chars => 'Required characters',
17416: expire => 'Password expiration (days)',
1.356 raeburn 17417: numsaved => 'Number of previous passwords to save',
1.354 raeburn 17418: reset => 'Resetting Forgotten Password',
17419: intauth => 'Encryption of Stored Passwords (Internal Auth)',
17420: rules => 'Rules for LON-CAPA Passwords',
17421: crsownerchg => 'Course Owner Changing Student Passwords',
17422: username => 'Username',
17423: email => 'E-mail address',
17424: );
17425:
17426: #
17427: # Retrieve current domain configuration for internal authentication from $domconfig{'defaults'}.
17428: #
17429: my (%curr_defaults,%save_defaults);
17430: if (ref($domconfig{'defaults'}) eq 'HASH') {
17431: foreach my $key (keys(%{$domconfig{'defaults'}})) {
17432: if ($key =~ /^intauth_(cost|check|switch)$/) {
17433: $curr_defaults{$key} = $domconfig{'defaults'}{$key};
17434: } else {
17435: $save_defaults{$key} = $domconfig{'defaults'}{$key};
17436: }
17437: }
17438: }
17439: my %staticdefaults = (
17440: 'resetlink' => 2,
17441: 'resetcase' => \@oktypes,
17442: 'resetprelink' => 'both',
17443: 'resetemail' => ['critical','notify','permanent'],
17444: 'intauth_cost' => 10,
17445: 'intauth_check' => 0,
17446: 'intauth_switch' => 0,
17447: );
1.365 raeburn 17448: $staticdefaults{'min'} = $Apache::lonnet::passwdmin;
1.354 raeburn 17449: foreach my $type (@oktypes) {
17450: $staticdefaults{'resetpostlink'}{$type} = ['email','username'];
17451: }
17452: my $linklife = $env{'form.passwords_link'};
17453: $linklife =~ s/^\s+|\s+$//g;
17454: if (($linklife =~ /^\d+(|\.\d*)$/) && ($linklife > 0)) {
17455: $newvalues{'resetlink'} = $linklife;
17456: if ($current{'resetlink'}) {
17457: if ($current{'resetlink'} ne $linklife) {
17458: $changes{'reset'} = 1;
17459: }
1.368 raeburn 17460: } elsif (!ref($domconfig{passwords}) eq 'HASH') {
1.354 raeburn 17461: if ($staticdefaults{'resetlink'} ne $linklife) {
17462: $changes{'reset'} = 1;
17463: }
17464: }
17465: } elsif ($current{'resetlink'}) {
17466: $changes{'reset'} = 1;
17467: }
17468: my @casesens;
17469: my @posscase = &Apache::loncommon::get_env_multiple('form.passwords_case_sensitive');
17470: foreach my $case (sort(@posscase)) {
17471: if (grep(/^\Q$case\E$/,@oktypes)) {
17472: push(@casesens,$case);
17473: }
17474: }
17475: $newvalues{'resetcase'} = \@casesens;
17476: if (ref($current{'resetcase'}) eq 'ARRAY') {
17477: my @diffs = &Apache::loncommon::compare_arrays($current{'resetcase'},\@casesens);
17478: if (@diffs > 0) {
17479: $changes{'reset'} = 1;
17480: }
1.368 raeburn 17481: } elsif (!ref($domconfig{passwords}) eq 'HASH') {
1.354 raeburn 17482: my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetcase'},\@casesens);
17483: if (@diffs > 0) {
17484: $changes{'reset'} = 1;
17485: }
17486: }
17487: if ($env{'form.passwords_prelink'} =~ /^(both|either)$/) {
17488: $newvalues{'resetprelink'} = $env{'form.passwords_prelink'};
17489: if (exists($current{'resetprelink'})) {
17490: if ($current{'resetprelink'} ne $newvalues{'resetprelink'}) {
17491: $changes{'reset'} = 1;
17492: }
1.368 raeburn 17493: } elsif (!ref($domconfig{passwords}) eq 'HASH') {
1.354 raeburn 17494: if ($staticdefaults{'resetprelink'} ne $newvalues{'resetprelink'}) {
17495: $changes{'reset'} = 1;
17496: }
17497: }
17498: } elsif ($current{'resetprelink'}) {
17499: $changes{'reset'} = 1;
17500: }
17501: foreach my $type (@oktypes) {
17502: my @possplink = &Apache::loncommon::get_env_multiple('form.passwords_postlink_'.$type);
17503: my @postlink;
17504: foreach my $item (sort(@possplink)) {
17505: if ($item =~ /^(email|username)$/) {
17506: push(@postlink,$item);
17507: }
17508: }
17509: $newvalues{'resetpostlink'}{$type} = \@postlink;
17510: unless ($changes{'reset'}) {
17511: if (ref($current{'resetpostlink'}) eq 'HASH') {
17512: if (ref($current{'resetpostlink'}{$type}) eq 'ARRAY') {
17513: my @diffs = &Apache::loncommon::compare_arrays($current{'resetpostlink'}{$type},\@postlink);
17514: if (@diffs > 0) {
17515: $changes{'reset'} = 1;
17516: }
17517: } else {
17518: $changes{'reset'} = 1;
17519: }
1.368 raeburn 17520: } elsif (!ref($domconfig{passwords}) eq 'HASH') {
1.354 raeburn 17521: my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetpostlink'}{$type},\@postlink);
17522: if (@diffs > 0) {
17523: $changes{'reset'} = 1;
17524: }
17525: }
17526: }
17527: }
17528: my @possemailsrc = &Apache::loncommon::get_env_multiple('form.passwords_emailsrc');
17529: my @resetemail;
17530: foreach my $item (sort(@possemailsrc)) {
17531: if ($item =~ /^(permanent|critical|notify)$/) {
17532: push(@resetemail,$item);
17533: }
17534: }
17535: $newvalues{'resetemail'} = \@resetemail;
17536: unless ($changes{'reset'}) {
17537: if (ref($current{'resetemail'}) eq 'ARRAY') {
17538: my @diffs = &Apache::loncommon::compare_arrays($current{'resetemail'},\@resetemail);
17539: if (@diffs > 0) {
17540: $changes{'reset'} = 1;
17541: }
1.368 raeburn 17542: } elsif (!ref($domconfig{passwords}) eq 'HASH') {
1.354 raeburn 17543: my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetemail'},\@resetemail);
17544: if (@diffs > 0) {
17545: $changes{'reset'} = 1;
17546: }
17547: }
17548: }
17549: if ($env{'form.passwords_stdtext'} == 0) {
17550: $newvalues{'resetremove'} = 1;
17551: unless ($current{'resetremove'}) {
17552: $changes{'reset'} = 1;
17553: }
17554: } elsif ($current{'resetremove'}) {
17555: $changes{'reset'} = 1;
17556: }
17557: if ($env{'form.passwords_customfile.filename'} ne '') {
17558: my $servadm = $r->dir_config('lonAdmEMail');
17559: my ($configuserok,$author_ok,$switchserver) =
17560: &config_check($dom,$confname,$servadm);
17561: my $error;
17562: if ($configuserok eq 'ok') {
17563: if ($switchserver) {
17564: $error = &mt("Upload of file containing domain-specific text is not permitted to this server: [_1]",$switchserver);
17565: } else {
17566: if ($author_ok eq 'ok') {
1.421 raeburn 17567: my $modified = [];
1.354 raeburn 17568: my ($result,$customurl) =
1.421 raeburn 17569: &Apache::lonconfigsettings::publishlogo($r,'upload','passwords_customfile',$dom,
17570: $confname,'customtext/resetpw','','',$customfn,
17571: $modified);
1.354 raeburn 17572: if ($result eq 'ok') {
17573: $newvalues{'resetcustom'} = $customurl;
17574: $changes{'reset'} = 1;
1.421 raeburn 17575: &update_modify_urls($r,$modified);
1.354 raeburn 17576: } else {
17577: $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customfn,$result);
17578: }
17579: } else {
17580: $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].",$customfn,$confname,$dom,$author_ok);
17581: }
17582: }
17583: } else {
17584: $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$customfn,$confname,$dom,$configuserok);
17585: }
17586: if ($error) {
17587: &Apache::lonnet::logthis($error);
17588: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
17589: }
17590: } elsif ($current{'resetcustom'}) {
17591: if ($env{'form.passwords_custom_del'}) {
17592: $changes{'reset'} = 1;
17593: } else {
17594: $newvalues{'resetcustom'} = $current{'resetcustom'};
17595: }
17596: }
17597: $env{'form.intauth_cost'} =~ s/^\s+|\s+$//g;
17598: if (($env{'form.intauth_cost'} ne '') && ($env{'form.intauth_cost'} =~ /^\d+$/)) {
17599: $save_defaults{'intauth_cost'} = $env{'form.intauth_cost'};
17600: if ($save_defaults{'intauth_cost'} ne $curr_defaults{'intauth_cost'}) {
17601: $changes{'intauth'} = 1;
17602: }
17603: } else {
17604: $save_defaults{'intauth_cost'} = $curr_defaults{'intauth_cost'};
17605: }
17606: if ($env{'form.intauth_check'} =~ /^(0|1|2)$/) {
17607: $save_defaults{'intauth_check'} = $env{'form.intauth_check'};
17608: if ($save_defaults{'intauth_check'} ne $curr_defaults{'intauth_check'}) {
17609: $changes{'intauth'} = 1;
17610: }
17611: } else {
17612: $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};
17613: }
17614: if ($env{'form.intauth_switch'} =~ /^(0|1|2)$/) {
17615: $save_defaults{'intauth_switch'} = $env{'form.intauth_switch'};
17616: if ($save_defaults{'intauth_switch'} ne $curr_defaults{'intauth_switch'}) {
17617: $changes{'intauth'} = 1;
17618: }
17619: } else {
17620: $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};
17621: }
17622: foreach my $item ('cost','check','switch') {
17623: if ($save_defaults{'intauth_'.$item} ne $domdefaults{'intauth_'.$item}) {
17624: $domdefaults{'intauth_'.$item} = $save_defaults{'intauth_'.$item};
17625: $updatedefaults = 1;
17626: }
17627: }
1.405 raeburn 17628: &password_rule_changes('passwords',\%newvalues,\%current,\%changes);
1.359 raeburn 17629: my %crsownerchg = (
17630: by => [],
17631: for => [],
17632: );
17633: foreach my $item ('by','for') {
17634: my @posstypes = &Apache::loncommon::get_env_multiple('form.passwords_crsowner_'.$item);
17635: foreach my $type (sort(@posstypes)) {
17636: if (grep(/^\Q$type\E$/,@oktypes)) {
17637: push(@{$crsownerchg{$item}},$type);
17638: }
17639: }
17640: }
17641: $newvalues{'crsownerchg'} = \%crsownerchg;
17642: if (ref($current{'crsownerchg'}) eq 'HASH') {
17643: foreach my $item ('by','for') {
17644: if (ref($current{'crsownerchg'}{$item}) eq 'ARRAY') {
17645: my @diffs = &Apache::loncommon::compare_arrays($current{'crsownerchg'}{$item},$crsownerchg{$item});
17646: if (@diffs > 0) {
17647: $changes{'crsownerchg'} = 1;
17648: last;
17649: }
17650: }
17651: }
1.368 raeburn 17652: } elsif (!(ref($domconfig{passwords}) eq 'HASH')) {
1.359 raeburn 17653: foreach my $item ('by','for') {
17654: if (@{$crsownerchg{$item}} > 0) {
17655: $changes{'crsownerchg'} = 1;
17656: last;
17657: }
1.354 raeburn 17658: }
17659: }
17660:
17661: my %confighash = (
17662: defaults => \%save_defaults,
17663: passwords => \%newvalues,
17664: );
17665: &process_captcha('passwords',\%changes,$confighash{'passwords'},$domconfig{'passwords'});
17666:
17667: my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);
17668: if ($putresult eq 'ok') {
17669: if (keys(%changes) > 0) {
17670: $resulttext = &mt('Changes made: ').'<ul>';
17671: foreach my $key ('reset','intauth','rules','crsownerchg') {
17672: if ($changes{$key}) {
1.355 raeburn 17673: unless ($key eq 'intauth') {
17674: $updateconf = 1;
17675: }
1.354 raeburn 17676: $resulttext .= '<li>'.$titles{$key}.':<ul>';
17677: if ($key eq 'reset') {
17678: if ($confighash{'passwords'}{'captcha'} eq 'original') {
17679: $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: original CAPTCHA').'</li>';
17680: } elsif ($confighash{'passwords'}{'captcha'} eq 'recaptcha') {
17681: $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: reCAPTCHA').' '.
1.369 raeburn 17682: &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).'<br />';
17683: if (ref($confighash{'passwords'}{'recaptchakeys'}) eq 'HASH') {
17684: $resulttext .= &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'public'}).'</br>'.
17685: &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'private'}).'</li>';
17686: }
1.354 raeburn 17687: } else {
17688: $resulttext .= '<li>'.&mt('No CAPTCHA validation').'</li>';
17689: }
17690: if ($confighash{'passwords'}{'resetlink'}) {
17691: $resulttext .= '<li>'.&mt('Reset link expiration set to [quant,_1,hour]',$confighash{'passwords'}{'resetlink'}).'</li>';
17692: } else {
17693: $resulttext .= '<li>'.&mt('No reset link expiration set.').' '.
17694: &mt('Will default to 2 hours').'</li>';
17695: }
17696: if (ref($confighash{'passwords'}{'resetcase'}) eq 'ARRAY') {
17697: if (@{$confighash{'passwords'}{'resetcase'}} == 0) {
17698: $resulttext .= '<li>'.&mt('User input for username and/or e-mail address not case sensitive for "Forgot Password" web form').'</li>';
17699: } else {
17700: my $casesens;
17701: foreach my $type (@{$confighash{'passwords'}{'resetcase'}}) {
17702: if ($type eq 'default') {
17703: $casesens .= $othertitle.', ';
17704: } elsif ($usertypes->{$type} ne '') {
17705: $casesens .= $usertypes->{$type}.', ';
17706: }
17707: }
17708: $casesens =~ s/\Q, \E$//;
17709: $resulttext .= '<li>'.&mt('"Forgot Password" web form input for username and/or e-mail address is case-sensitive for: [_1]',$casesens).'</li>';
17710: }
17711: } else {
17712: $resulttext .= '<li>'.&mt('Case-sensitivity not set for "Forgot Password" web form').' '.&mt('Will default to case-sensitive for username and/or e-mail address for all').'</li>';
17713: }
17714: if ($confighash{'passwords'}{'resetprelink'} eq 'either') {
17715: $resulttext .= '<li>'.&mt('Users can enter either a username or an e-mail address in "Forgot Password" web form').'</li>';
17716: } else {
17717: $resulttext .= '<li>'.&mt('Users can enter both a username and an e-mail address in "Forgot Password" web form').'</li>';
17718: }
17719: if (ref($confighash{'passwords'}{'resetpostlink'}) eq 'HASH') {
17720: my $output;
17721: if (ref($types) eq 'ARRAY') {
17722: foreach my $type (@{$types}) {
17723: if (ref($confighash{'passwords'}{'resetpostlink'}{$type}) eq 'ARRAY') {
17724: if (@{$confighash{'passwords'}{'resetpostlink'}{$type}} == 0) {
17725: $output .= $usertypes->{$type}.' -- '.&mt('none');
17726: } else {
17727: $output .= $usertypes->{$type}.' -- '.
17728: join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{$type}})).'; ';
17729: }
17730: }
17731: }
17732: }
17733: if (ref($confighash{'passwords'}{'resetpostlink'}{'default'}) eq 'ARRAY') {
17734: if (@{$confighash{'passwords'}{'resetpostlink'}{'default'}} == 0) {
17735: $output .= $othertitle.' -- '.&mt('none');
17736: } else {
17737: $output .= $othertitle.' -- '.
17738: join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{'default'}}));
17739: }
17740: }
17741: if ($output) {
17742: $resulttext .= '<li>'.&mt('Information required for new password form (by user type) set to: [_1]',$output).'</li>';
17743: } else {
17744: $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';
17745: }
17746: } else {
17747: $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';
17748: }
17749: if (ref($confighash{'passwords'}{'resetemail'}) eq 'ARRAY') {
17750: if (@{$confighash{'passwords'}{'resetemail'}} > 0) {
17751: $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$confighash{'passwords'}{'resetemail'}})).'</li>';
17752: } else {
17753: $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
17754: }
17755: } else {
1.379 raeburn 17756: $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
1.354 raeburn 17757: }
17758: if ($confighash{'passwords'}{'resetremove'}) {
17759: $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form not shown').'</li>';
17760: } else {
17761: $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form is shown').'</li>';
17762: }
17763: if ($confighash{'passwords'}{'resetcustom'}) {
17764: my $customlink = &Apache::loncommon::modal_link($confighash{'passwords'}{'resetcustom'},
1.369 raeburn 17765: &mt('custom text'),600,500,undef,undef,
17766: undef,undef,'background-color:#ffffff');
17767: $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" form includes: [_1]',$customlink).'</li>';
1.354 raeburn 17768: } else {
17769: $resulttext .= '<li>'.&mt('No custom text included in preamble to "Forgot Password" form').'</li>';
17770: }
17771: } elsif ($key eq 'intauth') {
17772: foreach my $item ('cost','switch','check') {
17773: my $value = $save_defaults{$key.'_'.$item};
17774: if ($item eq 'switch') {
17775: my %optiondesc = &Apache::lonlocal::texthash (
17776: 0 => 'No',
17777: 1 => 'Yes',
17778: 2 => 'Yes, and copy existing passwd file to passwd.bak file',
17779: );
17780: if ($value =~ /^(0|1|2)$/) {
17781: $value = $optiondesc{$value};
17782: } else {
17783: $value = &mt('none -- defaults to No');
17784: }
17785: } elsif ($item eq 'check') {
17786: my %optiondesc = &Apache::lonlocal::texthash (
17787: 0 => 'No',
17788: 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
17789: 2 => 'Yes, disallow login if stored cost is less than domain default',
17790: );
17791: if ($value =~ /^(0|1|2)$/) {
17792: $value = $optiondesc{$value};
17793: } else {
17794: $value = &mt('none -- defaults to No');
17795: }
17796: }
17797: $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).'</li>';
17798: }
17799: } elsif ($key eq 'rules') {
1.356 raeburn 17800: foreach my $rule ('min','max','expire','numsaved') {
1.354 raeburn 17801: if ($confighash{'passwords'}{$rule} eq '') {
17802: if ($rule eq 'min') {
1.356 raeburn 17803: $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});
1.365 raeburn 17804: ' '.&mt('Default of [_1] will be used',
17805: $Apache::lonnet::passwdmin).'</li>';
1.356 raeburn 17806: } else {
17807: $resulttext .= '<li>'.&mt('[_1] set to none',$titles{$rule}).'</li>';
1.354 raeburn 17808: }
17809: } else {
17810: $resulttext .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).'</li>';
17811: }
17812: }
1.370 raeburn 17813: if (ref($confighash{'passwords'}{'chars'}) eq 'ARRAY') {
17814: if (@{$confighash{'passwords'}{'chars'}} > 0) {
17815: my %rulenames = &Apache::lonlocal::texthash(
17816: uc => 'At least one upper case letter',
17817: lc => 'At least one lower case letter',
17818: num => 'At least one number',
17819: spec => 'At least one non-alphanumeric',
17820: );
17821: my $needed = '<ul><li>'.
17822: join('</li><li>',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).
1.425 raeburn 17823: '</li></ul>';
1.370 raeburn 17824: $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).'</li>';
17825: } else {
17826: $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';
17827: }
17828: } else {
17829: $resulttext .= '<li>'.&mt('[_1] set to none',$titles{'chars'}).'</li>';
17830: }
1.354 raeburn 17831: } elsif ($key eq 'crsownerchg') {
1.359 raeburn 17832: if (ref($confighash{'passwords'}{'crsownerchg'}) eq 'HASH') {
17833: if ((@{$confighash{'passwords'}{'crsownerchg'}{'by'}} == 0) ||
17834: (@{$confighash{'passwords'}{'crsownerchg'}{'for'}} == 0)) {
17835: $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';
17836: } else {
17837: my %crsownerstr;
17838: foreach my $item ('by','for') {
17839: if (ref($confighash{'passwords'}{'crsownerchg'}{$item}) eq 'ARRAY') {
17840: foreach my $type (@{$confighash{'passwords'}{'crsownerchg'}{$item}}) {
17841: if ($type eq 'default') {
17842: $crsownerstr{$item} .= $othertitle.', ';
17843: } elsif ($usertypes->{$type} ne '') {
17844: $crsownerstr{$item} .= $usertypes->{$type}.', ';
17845: }
17846: }
17847: $crsownerstr{$item} =~ s/\Q, \E$//;
17848: }
17849: }
17850: $resulttext .= '<li>'.&mt('Course owner (with status: [_1]) may change passwords for students (with status: [_2]).',
17851: $crsownerstr{'by'},$crsownerstr{'for'}).'</li>';
17852: }
1.354 raeburn 17853: } else {
1.359 raeburn 17854: $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';
1.354 raeburn 17855: }
17856: }
17857: $resulttext .= '</ul></li>';
17858: }
17859: }
17860: $resulttext .= '</ul>';
17861: } else {
17862: $resulttext = &mt('No changes made to password settings');
17863: }
1.355 raeburn 17864: my $cachetime = 24*60*60;
1.354 raeburn 17865: if ($updatedefaults) {
17866: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
17867: if (ref($lastactref) eq 'HASH') {
17868: $lastactref->{'domdefaults'} = 1;
17869: }
17870: }
1.355 raeburn 17871: if ($updateconf) {
17872: &Apache::lonnet::do_cache_new('passwdconf',$dom,$confighash{'passwords'},$cachetime);
17873: if (ref($lastactref) eq 'HASH') {
17874: $lastactref->{'passwdconf'} = 1;
17875: }
17876: }
1.354 raeburn 17877: } else {
17878: $resulttext = '<span class="LC_error">'.
17879: &mt('An error occurred: [_1]',$putresult).'</span>';
17880: }
17881: if ($errors) {
17882: $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.
17883: $errors.'</ul></p>';
17884: }
17885: return $resulttext;
17886: }
17887:
1.405 raeburn 17888: sub password_rule_changes {
17889: my ($prefix,$newvalues,$current,$changes) = @_;
17890: return unless ((ref($newvalues) eq 'HASH') &&
17891: (ref($current) eq 'HASH') &&
17892: (ref($changes) eq 'HASH'));
17893: my (@rules,%staticdefaults);
17894: if ($prefix eq 'passwords') {
17895: @rules = ('min','max','expire','numsaved');
1.421 raeburn 17896: } elsif (($prefix eq 'ltisecrets') || ($prefix eq 'toolsecrets')) {
1.405 raeburn 17897: @rules = ('min','max');
17898: }
17899: $staticdefaults{'min'} = $Apache::lonnet::passwdmin;
17900: foreach my $rule (@rules) {
17901: $env{'form.'.$prefix.'_'.$rule} =~ s/^\s+|\s+$//g;
17902: my $ruleok;
17903: if ($rule eq 'expire') {
17904: if (($env{'form.'.$prefix.'_'.$rule} =~ /^\d+(|\.\d*)$/) &&
17905: ($env{'form.'.$prefix.'_'.$rule} ne '0')) {
17906: $ruleok = 1;
17907: }
17908: } elsif ($rule eq 'min') {
17909: if ($env{'form.'.$prefix.'_'.$rule} =~ /^\d+$/) {
17910: if ($env{'form.'.$prefix.'_'.$rule} >= $staticdefaults{$rule}) {
17911: $ruleok = 1;
17912: }
17913: }
17914: } elsif (($env{'form.'.$prefix.'_'.$rule} =~ /^\d+$/) &&
17915: ($env{'form.'.$prefix.'_'.$rule} ne '0')) {
17916: $ruleok = 1;
17917: }
17918: if ($ruleok) {
17919: $newvalues->{$rule} = $env{'form.'.$prefix.'_'.$rule};
17920: if (exists($current->{$rule})) {
17921: if ($newvalues->{$rule} ne $current->{$rule}) {
17922: $changes->{'rules'} = 1;
17923: }
17924: } elsif ($rule eq 'min') {
17925: if ($staticdefaults{$rule} ne $newvalues->{$rule}) {
17926: $changes->{'rules'} = 1;
17927: }
17928: } else {
17929: $changes->{'rules'} = 1;
17930: }
17931: } elsif (exists($current->{$rule})) {
17932: $changes->{'rules'} = 1;
17933: }
17934: }
17935: my @posschars = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_chars');
17936: my @chars;
17937: foreach my $item (sort(@posschars)) {
17938: if ($item =~ /^(uc|lc|num|spec)$/) {
17939: push(@chars,$item);
17940: }
17941: }
17942: $newvalues->{'chars'} = \@chars;
17943: unless ($changes->{'rules'}) {
17944: if (ref($current->{'chars'}) eq 'ARRAY') {
17945: my @diffs = &Apache::loncommon::compare_arrays($current->{'chars'},\@chars);
17946: if (@diffs > 0) {
17947: $changes->{'rules'} = 1;
17948: }
17949: } else {
17950: if (@chars > 0) {
17951: $changes->{'rules'} = 1;
17952: }
17953: }
17954: }
17955: return;
17956: }
17957:
1.28 raeburn 17958: sub modify_usercreation {
1.27 raeburn 17959: my ($dom,%domconfig) = @_;
1.224 raeburn 17960: my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
1.43 raeburn 17961: my $warningmsg;
1.27 raeburn 17962: if (ref($domconfig{'usercreation'}) eq 'HASH') {
17963: foreach my $key (keys(%{$domconfig{'usercreation'}})) {
1.224 raeburn 17964: if ($key eq 'cancreate') {
17965: if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
17966: foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
1.303 raeburn 17967: if (($item eq 'requestcrs') || ($item eq 'course') || ($item eq 'author')) {
17968: $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
17969: } else {
1.224 raeburn 17970: $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
17971: }
17972: }
17973: }
17974: } elsif ($key eq 'email_rule') {
17975: $save_usercreate{$key} = $domconfig{'usercreation'}{$key};
17976: } else {
17977: $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
17978: }
1.27 raeburn 17979: }
17980: }
17981: my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule');
1.32 raeburn 17982: my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule');
1.224 raeburn 17983: my @contexts = ('author','course','requestcrs');
1.34 raeburn 17984: foreach my $item(@contexts) {
1.224 raeburn 17985: $cancreate{$item} = $env{'form.can_createuser_'.$item};
1.93 raeburn 17986: }
1.34 raeburn 17987: if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
17988: foreach my $item (@contexts) {
1.224 raeburn 17989: if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) {
17990: push(@{$changes{'cancreate'}},$item);
1.50 raeburn 17991: }
1.27 raeburn 17992: }
1.34 raeburn 17993: } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') {
17994: foreach my $item (@contexts) {
1.43 raeburn 17995: if (!grep(/^\Q$item\E$/,@{$curr_usercreation{'cancreate'}})) {
1.34 raeburn 17996: if ($cancreate{$item} ne 'any') {
17997: push(@{$changes{'cancreate'}},$item);
17998: }
17999: } else {
18000: if ($cancreate{$item} ne 'none') {
18001: push(@{$changes{'cancreate'}},$item);
18002: }
1.27 raeburn 18003: }
18004: }
18005: } else {
1.43 raeburn 18006: foreach my $item (@contexts) {
1.34 raeburn 18007: push(@{$changes{'cancreate'}},$item);
18008: }
1.27 raeburn 18009: }
1.34 raeburn 18010:
1.27 raeburn 18011: if (ref($curr_usercreation{'username_rule'}) eq 'ARRAY') {
18012: foreach my $type (@{$curr_usercreation{'username_rule'}}) {
18013: if (!grep(/^\Q$type\E$/,@username_rule)) {
18014: push(@{$changes{'username_rule'}},$type);
18015: }
18016: }
18017: foreach my $type (@username_rule) {
18018: if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'username_rule'}})) {
18019: push(@{$changes{'username_rule'}},$type);
18020: }
18021: }
18022: } else {
18023: push(@{$changes{'username_rule'}},@username_rule);
18024: }
18025:
1.32 raeburn 18026: if (ref($curr_usercreation{'id_rule'}) eq 'ARRAY') {
18027: foreach my $type (@{$curr_usercreation{'id_rule'}}) {
18028: if (!grep(/^\Q$type\E$/,@id_rule)) {
18029: push(@{$changes{'id_rule'}},$type);
18030: }
18031: }
18032: foreach my $type (@id_rule) {
18033: if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'id_rule'}})) {
18034: push(@{$changes{'id_rule'}},$type);
18035: }
18036: }
18037: } else {
18038: push(@{$changes{'id_rule'}},@id_rule);
18039: }
18040:
1.43 raeburn 18041: my @authen_contexts = ('author','course','domain');
1.325 raeburn 18042: my @authtypes = ('int','krb4','krb5','loc','lti');
1.28 raeburn 18043: my %authhash;
1.43 raeburn 18044: foreach my $item (@authen_contexts) {
1.28 raeburn 18045: my @authallowed = &Apache::loncommon::get_env_multiple('form.'.$item.'_auth');
18046: foreach my $auth (@authtypes) {
18047: if (grep(/^\Q$auth\E$/,@authallowed)) {
18048: $authhash{$item}{$auth} = 1;
18049: } else {
18050: $authhash{$item}{$auth} = 0;
18051: }
18052: }
18053: }
18054: if (ref($curr_usercreation{'authtypes'}) eq 'HASH') {
1.43 raeburn 18055: foreach my $item (@authen_contexts) {
1.28 raeburn 18056: if (ref($curr_usercreation{'authtypes'}{$item}) eq 'HASH') {
18057: foreach my $auth (@authtypes) {
18058: if ($authhash{$item}{$auth} ne $curr_usercreation{'authtypes'}{$item}{$auth}) {
18059: push(@{$changes{'authtypes'}},$item);
18060: last;
18061: }
18062: }
18063: }
18064: }
18065: } else {
1.43 raeburn 18066: foreach my $item (@authen_contexts) {
1.28 raeburn 18067: push(@{$changes{'authtypes'}},$item);
18068: }
18069: }
18070:
1.224 raeburn 18071: $save_usercreate{'cancreate'}{'course'} = $cancreate{'course'};
18072: $save_usercreate{'cancreate'}{'author'} = $cancreate{'author'};
18073: $save_usercreate{'cancreate'}{'requestcrs'} = $cancreate{'requestcrs'};
18074: $save_usercreate{'id_rule'} = \@id_rule;
18075: $save_usercreate{'username_rule'} = \@username_rule,
18076: $save_usercreate{'authtypes'} = \%authhash;
18077:
1.27 raeburn 18078: my %usercreation_hash = (
1.224 raeburn 18079: usercreation => \%save_usercreate,
18080: );
1.27 raeburn 18081:
18082: my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash,
18083: $dom);
1.50 raeburn 18084:
1.224 raeburn 18085: if ($putresult eq 'ok') {
18086: if (keys(%changes) > 0) {
18087: $resulttext = &mt('Changes made:').'<ul>';
18088: if (ref($changes{'cancreate'}) eq 'ARRAY') {
18089: my %lt = &usercreation_types();
18090: foreach my $type (@{$changes{'cancreate'}}) {
18091: my $chgtext = $lt{$type}.', ';
18092: if ($cancreate{$type} eq 'none') {
18093: $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.');
18094: } elsif ($cancreate{$type} eq 'any') {
18095: $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.');
18096: } elsif ($cancreate{$type} eq 'official') {
18097: $chgtext .= &mt('creation of new users is only permitted for institutional usernames.');
18098: } elsif ($cancreate{$type} eq 'unofficial') {
18099: $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.');
18100: }
18101: $resulttext .= '<li>'.$chgtext.'</li>';
18102: }
18103: }
18104: if (ref($changes{'username_rule'}) eq 'ARRAY') {
18105: my ($rules,$ruleorder) =
18106: &Apache::lonnet::inst_userrules($dom,'username');
18107: my $chgtext = '<ul>';
18108: foreach my $type (@username_rule) {
18109: if (ref($rules->{$type}) eq 'HASH') {
18110: $chgtext .= '<li>'.$rules->{$type}{'name'}.'</li>';
18111: }
18112: }
18113: $chgtext .= '</ul>';
18114: if (@username_rule > 0) {
18115: $resulttext .= '<li>'.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';
18116: } else {
18117: $resulttext .= '<li>'.&mt('There are now no username formats restricted to verified users in the institutional directory.').'</li>';
18118: }
18119: }
18120: if (ref($changes{'id_rule'}) eq 'ARRAY') {
18121: my ($idrules,$idruleorder) =
18122: &Apache::lonnet::inst_userrules($dom,'id');
18123: my $chgtext = '<ul>';
18124: foreach my $type (@id_rule) {
18125: if (ref($idrules->{$type}) eq 'HASH') {
18126: $chgtext .= '<li>'.$idrules->{$type}{'name'}.'</li>';
18127: }
18128: }
18129: $chgtext .= '</ul>';
18130: if (@id_rule > 0) {
18131: $resulttext .= '<li>'.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'</li>';
18132: } else {
18133: $resulttext .= '<li>'.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'</li>';
18134: }
18135: }
18136: my %authname = &authtype_names();
18137: my %context_title = &context_names();
18138: if (ref($changes{'authtypes'}) eq 'ARRAY') {
18139: my $chgtext = '<ul>';
18140: foreach my $type (@{$changes{'authtypes'}}) {
18141: my @allowed;
18142: $chgtext .= '<li><span class="LC_cusr_emph">'.$context_title{$type}.'</span> - '.&mt('assignable authentication types: ');
18143: foreach my $auth (@authtypes) {
18144: if ($authhash{$type}{$auth}) {
18145: push(@allowed,$authname{$auth});
18146: }
18147: }
18148: if (@allowed > 0) {
18149: $chgtext .= join(', ',@allowed).'</li>';
18150: } else {
18151: $chgtext .= &mt('none').'</li>';
18152: }
18153: }
18154: $chgtext .= '</ul>';
18155: $resulttext .= '<li>'.&mt('Authentication types available for assignment to new users').'<br />'.$chgtext;
18156: $resulttext .= '</li>';
18157: }
18158: $resulttext .= '</ul>';
18159: } else {
18160: $resulttext = &mt('No changes made to user creation settings');
18161: }
18162: } else {
18163: $resulttext = '<span class="LC_error">'.
18164: &mt('An error occurred: [_1]',$putresult).'</span>';
18165: }
18166: if ($warningmsg ne '') {
18167: $resulttext .= '<br /><span class="LC_warning">'.$warningmsg.'</span><br />';
18168: }
18169: return $resulttext;
18170: }
18171:
18172: sub modify_selfcreation {
1.305 raeburn 18173: my ($dom,$lastactref,%domconfig) = @_;
18174: my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%curr_inststatus,%changes,%cancreate);
18175: my (%save_usercreate,%save_usermodify,%save_inststatus,@types,%usertypes);
18176: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
1.303 raeburn 18177: my ($othertitle,$usertypesref,$typesref) = &Apache::loncommon::sorted_inst_types($dom);
18178: if (ref($typesref) eq 'ARRAY') {
18179: @types = @{$typesref};
18180: }
18181: if (ref($usertypesref) eq 'HASH') {
18182: %usertypes = %{$usertypesref};
1.228 raeburn 18183: }
1.303 raeburn 18184: $usertypes{'default'} = $othertitle;
1.224 raeburn 18185: #
18186: # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}.
18187: #
18188: if (ref($domconfig{'usercreation'}) eq 'HASH') {
18189: foreach my $key (keys(%{$domconfig{'usercreation'}})) {
18190: if ($key eq 'cancreate') {
18191: if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') {
18192: foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) {
18193: if (($item eq 'selfcreate') || ($item eq 'statustocreate') ||
1.303 raeburn 18194: ($item eq 'captcha') || ($item eq 'recaptchakeys') ||
18195: ($item eq 'recaptchaversion') || ($item eq 'notify') ||
18196: ($item eq 'emailusername') || ($item eq 'shibenv') ||
18197: ($item eq 'selfcreateprocessing') || ($item eq 'emailverified') ||
1.305 raeburn 18198: ($item eq 'emailoptions') || ($item eq 'emaildomain')) {
1.224 raeburn 18199: $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
18200: } else {
18201: $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item};
18202: }
18203: }
18204: }
18205: } elsif ($key eq 'email_rule') {
18206: $curr_usercreation{$key} = $domconfig{'usercreation'}{$key};
18207: } else {
18208: $save_usercreate{$key} = $domconfig{'usercreation'}{$key};
18209: }
18210: }
18211: }
18212: #
18213: # Retrieve current domain configuration for self-creation of usernames from $domconfig{'usermodification'}.
18214: #
18215: if (ref($domconfig{'usermodification'}) eq 'HASH') {
18216: foreach my $key (keys(%{$domconfig{'usermodification'}})) {
18217: if ($key eq 'selfcreate') {
18218: $curr_usermodify{$key} = $domconfig{'usermodification'}{$key};
18219: } else {
18220: $save_usermodify{$key} = $domconfig{'usermodification'}{$key};
18221: }
18222: }
18223: }
1.305 raeburn 18224: #
18225: # Retrieve current domain configuration for institutional status types from $domconfig{'inststatus'}.
18226: #
18227: if (ref($domconfig{'inststatus'}) eq 'HASH') {
18228: foreach my $key (keys(%{$domconfig{'inststatus'}})) {
18229: if ($key eq 'inststatusguest') {
18230: $curr_inststatus{$key} = $domconfig{'inststatus'}{$key};
18231: } else {
18232: $save_inststatus{$key} = $domconfig{'inststatus'}{$key};
18233: }
18234: }
18235: }
1.224 raeburn 18236:
18237: my @contexts = ('selfcreate');
18238: @{$cancreate{'selfcreate'}} = ();
18239: %{$cancreate{'emailusername'}} = ();
1.305 raeburn 18240: if (@types) {
18241: @{$cancreate{'statustocreate'}} = ();
18242: }
1.236 raeburn 18243: %{$cancreate{'selfcreateprocessing'}} = ();
1.240 raeburn 18244: %{$cancreate{'shibenv'}} = ();
1.303 raeburn 18245: %{$cancreate{'emailverified'}} = ();
1.305 raeburn 18246: %{$cancreate{'emailoptions'}} = ();
1.303 raeburn 18247: %{$cancreate{'emaildomain'}} = ();
1.50 raeburn 18248: my %selfcreatetypes = (
18249: sso => 'users authenticated by institutional single sign on',
18250: login => 'users authenticated by institutional log-in',
1.303 raeburn 18251: email => 'users verified by e-mail',
1.50 raeburn 18252: );
1.224 raeburn 18253: #
18254: # Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts
18255: # is permitted.
18256: #
1.305 raeburn 18257: my ($emailrules,$emailruleorder) = &Apache::lonnet::inst_userrules($dom,'email');
1.236 raeburn 18258:
1.305 raeburn 18259: my (@statuses,%email_rule);
1.228 raeburn 18260: foreach my $item ('login','sso','email') {
1.224 raeburn 18261: if ($item eq 'email') {
1.236 raeburn 18262: if ($env{'form.cancreate_email'}) {
1.305 raeburn 18263: if (@types) {
18264: my @poss_statuses = &Apache::loncommon::get_env_multiple('form.selfassign');
18265: foreach my $status (@poss_statuses) {
18266: if (grep(/^\Q$status\E$/,(@types,'default'))) {
18267: push(@statuses,$status);
18268: }
18269: }
18270: $save_inststatus{'inststatusguest'} = \@statuses;
18271: } else {
18272: push(@statuses,'default');
18273: }
18274: if (@statuses) {
18275: my %curr_rule;
18276: if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') {
18277: foreach my $type (@statuses) {
18278: $curr_rule{$type} = $curr_usercreation{'email_rule'};
1.303 raeburn 18279: }
1.305 raeburn 18280: } elsif (ref($curr_usercreation{'email_rule'}) eq 'HASH') {
18281: foreach my $type (@statuses) {
18282: $curr_rule{$type} = $curr_usercreation{'email_rule'}{$type};
18283: }
18284: }
18285: push(@{$cancreate{'selfcreate'}},'email');
18286: push(@contexts,('selfcreateprocessing','emailverified','emailoptions'));
18287: my %curremaildom;
18288: if (ref($curr_usercreation{'cancreate'}{'emaildomain'}) eq 'HASH') {
18289: %curremaildom = %{$curr_usercreation{'cancreate'}{'emaildomain'}};
18290: }
18291: foreach my $type (@statuses) {
18292: if ($env{'form.cancreate_emailprocess_'.$type} =~ /^(?:approval|automatic)$/) {
18293: $cancreate{'selfcreateprocessing'}{$type} = $env{'form.cancreate_emailprocess_'.$type};
18294: }
18295: if ($env{'form.cancreate_usernameoptions_'.$type} =~ /^(?:all|first|free)$/) {
18296: $cancreate{'emailverified'}{$type} = $env{'form.cancreate_usernameoptions_'.$type};
18297: }
18298: if ($env{'form.cancreate_emailoptions_'.$type} =~ /^(any|inst|noninst|custom)$/) {
18299: #
18300: # Retrieve rules (if any) governing types of e-mail address which may be used to verify a username.
18301: #
18302: my $chosen = $1;
18303: if (($chosen eq 'inst') || ($chosen eq 'noninst')) {
18304: my $emaildom;
18305: if ($env{'form.cancreate_emaildomain_'.$chosen.'_'.$type} =~ /^\@[^\@]+$/) {
1.425 raeburn 18306: $emaildom = $env{'form.cancreate_emaildomain_'.$chosen.'_'.$type};
1.305 raeburn 18307: $cancreate{'emaildomain'}{$type}{$chosen} = $emaildom;
18308: if (ref($curremaildom{$type}) eq 'HASH') {
18309: if (exists($curremaildom{$type}{$chosen})) {
18310: if ($curremaildom{$type}{$chosen} ne $emaildom) {
18311: push(@{$changes{'cancreate'}},'emaildomain');
18312: }
18313: } elsif ($emaildom ne '') {
18314: push(@{$changes{'cancreate'}},'emaildomain');
18315: }
18316: } elsif ($emaildom ne '') {
18317: push(@{$changes{'cancreate'}},'emaildomain');
1.425 raeburn 18318: }
1.305 raeburn 18319: }
18320: $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};
18321: } elsif ($chosen eq 'custom') {
18322: my @possemail_rules = &Apache::loncommon::get_env_multiple('form.email_rule_'.$type);
18323: $email_rule{$type} = [];
18324: if (ref($emailrules) eq 'HASH') {
18325: foreach my $rule (@possemail_rules) {
18326: if (exists($emailrules->{$rule})) {
18327: push(@{$email_rule{$type}},$rule);
18328: }
18329: }
18330: }
18331: if (@{$email_rule{$type}}) {
18332: $cancreate{'emailoptions'}{$type} = 'custom';
18333: if (ref($curr_rule{$type}) eq 'ARRAY') {
18334: if (@{$curr_rule{$type}} > 0) {
18335: foreach my $rule (@{$curr_rule{$type}}) {
18336: if (!grep(/^\Q$rule\E$/,@{$email_rule{$type}})) {
18337: push(@{$changes{'email_rule'}},$type);
18338: }
18339: }
18340: }
18341: foreach my $type (@{$email_rule{$type}}) {
18342: if (!grep(/^\Q$type\E$/,@{$curr_rule{$type}})) {
18343: push(@{$changes{'email_rule'}},$type);
18344: }
18345: }
18346: } else {
18347: push(@{$changes{'email_rule'}},$type);
18348: }
18349: }
18350: } else {
18351: $cancreate{'emailoptions'}{$type} = $env{'form.cancreate_emailoptions_'.$type};
18352: }
18353: }
18354: }
18355: if (@types) {
18356: if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {
18357: my @changed = &Apache::loncommon::compare_arrays(\@statuses,$curr_inststatus{'inststatusguest'});
18358: if (@changed) {
18359: push(@{$changes{'inststatus'}},'inststatusguest');
18360: }
18361: } else {
18362: push(@{$changes{'inststatus'}},'inststatusguest');
18363: }
18364: }
18365: } else {
18366: delete($env{'form.cancreate_email'});
18367: if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {
18368: if (@{$curr_inststatus{'inststatusguest'}} > 0) {
18369: push(@{$changes{'inststatus'}},'inststatusguest');
18370: }
18371: }
18372: }
18373: } else {
18374: $save_inststatus{'inststatusguest'} = [];
18375: if (ref($curr_inststatus{'inststatusguest'}) eq 'ARRAY') {
18376: if (@{$curr_inststatus{'inststatusguest'}} > 0) {
18377: push(@{$changes{'inststatus'}},'inststatusguest');
1.236 raeburn 18378: }
18379: }
1.224 raeburn 18380: }
18381: } else {
18382: if ($env{'form.cancreate_'.$item}) {
18383: push(@{$cancreate{'selfcreate'}},$item);
18384: }
18385: }
18386: }
1.305 raeburn 18387: my (%userinfo,%savecaptcha);
1.224 raeburn 18388: my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info();
18389: #
1.228 raeburn 18390: # Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data
18391: # value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc.
1.224 raeburn 18392: #
1.236 raeburn 18393:
1.244 raeburn 18394: if ($env{'form.cancreate_email'}) {
1.228 raeburn 18395: push(@contexts,'emailusername');
1.305 raeburn 18396: if (@statuses) {
18397: foreach my $type (@statuses) {
1.228 raeburn 18398: if (ref($infofields) eq 'ARRAY') {
18399: foreach my $field (@{$infofields}) {
18400: if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) {
18401: $cancreate{'emailusername'}{$type}{$field} = $1;
18402: }
18403: }
1.224 raeburn 18404: }
18405: }
18406: }
18407: #
18408: # Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of
1.303 raeburn 18409: # queued requests for self-creation of account verified by e-mail.
1.224 raeburn 18410: #
18411:
18412: my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval');
18413: @approvalnotify = sort(@approvalnotify);
18414: $cancreate{'notify'}{'approval'} = join(',',@approvalnotify);
18415: if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
18416: if (ref($curr_usercreation{'cancreate'}{'notify'}) eq 'HASH') {
18417: if ($curr_usercreation{'cancreate'}{'notify'}{'approval'} ne $cancreate{'notify'}{'approval'}) {
18418: push(@{$changes{'cancreate'}},'notify');
18419: }
18420: } else {
18421: if ($cancreate{'notify'}{'approval'}) {
18422: push(@{$changes{'cancreate'}},'notify');
18423: }
18424: }
18425: } elsif ($cancreate{'notify'}{'approval'}) {
18426: push(@{$changes{'cancreate'}},'notify');
18427: }
18428:
18429: &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'});
18430: }
18431: #
1.236 raeburn 18432: # Check if domain default is set appropriately, if self-creation of accounts is to be available for
1.224 raeburn 18433: # institutional log-in.
18434: #
18435: if (grep(/^login$/,@{$cancreate{'selfcreate'}})) {
18436: if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) ||
18437: ($domdefaults{'auth_def'} eq 'localauth'))) {
18438: $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.
18439: &mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.');
18440: }
18441: }
18442: my @fields = ('lastname','firstname','middlename','generation',
18443: 'permanentemail','id');
1.240 raeburn 18444: my @shibfields = (@fields,'inststatus');
1.224 raeburn 18445: my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
18446: #
18447: # Where usernames may created for institutional log-in and/or institutional single sign on:
18448: # (a) populate $cancreate{'statustocreate'} array reference with institutional status types who
18449: # may self-create accounts
18450: # (b) populate $save_usermodify{'selfcreate'} hash reference with status types, and information fields
18451: # which the user may supply, if institutional data is unavailable.
18452: #
18453: if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) {
1.303 raeburn 18454: if (@types) {
1.305 raeburn 18455: @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate');
18456: push(@contexts,'statustocreate');
1.303 raeburn 18457: foreach my $type (@types) {
1.224 raeburn 18458: my @modifiable = &Apache::loncommon::get_env_multiple('form.canmodify_'.$type);
18459: foreach my $field (@fields) {
18460: if (grep(/^\Q$field\E$/,@modifiable)) {
18461: $save_usermodify{'selfcreate'}{$type}{$field} = 1;
18462: } else {
18463: $save_usermodify{'selfcreate'}{$type}{$field} = 0;
18464: }
18465: }
18466: }
18467: if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') {
1.303 raeburn 18468: foreach my $type (@types) {
1.224 raeburn 18469: if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') {
18470: foreach my $field (@fields) {
18471: if ($save_usermodify{'selfcreate'}{$type}{$field} ne
18472: $curr_usermodify{'selfcreate'}{$type}{$field}) {
18473: push(@{$changes{'selfcreate'}},$type);
18474: last;
18475: }
18476: }
18477: }
18478: }
18479: } else {
1.303 raeburn 18480: foreach my $type (@types) {
1.224 raeburn 18481: push(@{$changes{'selfcreate'}},$type);
18482: }
18483: }
18484: }
1.240 raeburn 18485: foreach my $field (@shibfields) {
18486: if ($env{'form.shibenv_'.$field} ne '') {
18487: $cancreate{'shibenv'}{$field} = $env{'form.shibenv_'.$field};
18488: }
18489: }
18490: if (ref($curr_usercreation{'cancreate'}) eq 'HASH') {
18491: if (ref($curr_usercreation{'cancreate'}{'shibenv'}) eq 'HASH') {
18492: foreach my $field (@shibfields) {
18493: if ($env{'form.shibenv_'.$field} ne $curr_usercreation{'cancreate'}{'shibenv'}{$field}) {
18494: push(@{$changes{'cancreate'}},'shibenv');
18495: }
18496: }
18497: } else {
18498: foreach my $field (@shibfields) {
18499: if ($env{'form.shibenv_'.$field}) {
18500: push(@{$changes{'cancreate'}},'shibenv');
18501: last;
18502: }
18503: }
18504: }
18505: }
1.224 raeburn 18506: }
18507: foreach my $item (@contexts) {
18508: if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') {
18509: foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) {
18510: if (ref($cancreate{$item}) eq 'ARRAY') {
18511: if (!grep(/^$curr$/,@{$cancreate{$item}})) {
18512: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18513: push(@{$changes{'cancreate'}},$item);
18514: }
18515: }
18516: }
18517: }
18518: if (ref($cancreate{$item}) eq 'ARRAY') {
18519: foreach my $type (@{$cancreate{$item}}) {
18520: if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) {
18521: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18522: push(@{$changes{'cancreate'}},$item);
18523: }
18524: }
18525: }
18526: }
18527: } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') {
18528: if (ref($cancreate{$item}) eq 'HASH') {
1.305 raeburn 18529: foreach my $type (keys(%{$curr_usercreation{'cancreate'}{$item}})) {
18530: if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {
18531: foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$type}})) {
18532: unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {
1.228 raeburn 18533: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18534: push(@{$changes{'cancreate'}},$item);
18535: }
18536: }
18537: }
1.305 raeburn 18538: } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {
18539: if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {
1.228 raeburn 18540: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18541: push(@{$changes{'cancreate'}},$item);
18542: }
1.224 raeburn 18543: }
18544: }
18545: }
1.305 raeburn 18546: foreach my $type (keys(%{$cancreate{$item}})) {
18547: if (ref($cancreate{$item}{$type}) eq 'HASH') {
18548: foreach my $field (keys(%{$cancreate{$item}{$type}})) {
18549: if (ref($curr_usercreation{'cancreate'}{$item}{$type}) eq 'HASH') {
18550: unless ($curr_usercreation{'cancreate'}{$item}{$type}{$field} eq $cancreate{$item}{$type}{$field}) {
1.228 raeburn 18551: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18552: push(@{$changes{'cancreate'}},$item);
18553: }
18554: }
18555: } else {
18556: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18557: push(@{$changes{'cancreate'}},$item);
18558: }
18559: }
18560: }
1.305 raeburn 18561: } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {
18562: if ($cancreate{$item}{$type} ne $curr_usercreation{'cancreate'}{$item}{$type}) {
1.228 raeburn 18563: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18564: push(@{$changes{'cancreate'}},$item);
18565: }
1.224 raeburn 18566: }
18567: }
18568: }
18569: }
18570: } elsif ($curr_usercreation{'cancreate'}{$item}) {
18571: if (ref($cancreate{$item}) eq 'ARRAY') {
18572: if (!grep(/^\Q$curr_usercreation{'cancreate'}{$item}\E$/,@{$cancreate{$item}})) {
18573: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18574: push(@{$changes{'cancreate'}},$item);
18575: }
18576: }
1.305 raeburn 18577: }
18578: } elsif (($item eq 'selfcreateprocessing') || ($item eq 'emailverified') || ($item eq 'emailoptions')) {
18579: if (ref($cancreate{$item}) eq 'HASH') {
18580: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18581: push(@{$changes{'cancreate'}},$item);
1.224 raeburn 18582: }
18583: }
18584: } elsif ($item eq 'emailusername') {
1.228 raeburn 18585: if (ref($cancreate{$item}) eq 'HASH') {
18586: foreach my $type (keys(%{$cancreate{$item}})) {
18587: if (ref($cancreate{$item}{$type}) eq 'HASH') {
18588: foreach my $field (keys(%{$cancreate{$item}{$type}})) {
18589: if ($cancreate{$item}{$type}{$field}) {
18590: if (!grep(/^$item$/,@{$changes{'cancreate'}})) {
18591: push(@{$changes{'cancreate'}},$item);
18592: }
18593: last;
18594: }
18595: }
18596: }
18597: }
1.224 raeburn 18598: }
18599: }
18600: }
18601: #
18602: # Populate %save_usercreate hash with updates to self-creation configuration.
18603: #
18604: $save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'};
18605: $save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'};
1.269 raeburn 18606: $save_usercreate{'cancreate'}{'recaptchaversion'} = $savecaptcha{'recaptchaversion'};
1.224 raeburn 18607: $save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'};
18608: if (ref($cancreate{'notify'}) eq 'HASH') {
18609: $save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'};
18610: }
1.236 raeburn 18611: if (ref($cancreate{'selfcreateprocessing'}) eq 'HASH') {
18612: $save_usercreate{'cancreate'}{'selfcreateprocessing'} = $cancreate{'selfcreateprocessing'};
18613: }
1.303 raeburn 18614: if (ref($cancreate{'emailverified'}) eq 'HASH') {
18615: $save_usercreate{'cancreate'}{'emailverified'} = $cancreate{'emailverified'};
18616: }
1.305 raeburn 18617: if (ref($cancreate{'emailoptions'}) eq 'HASH') {
18618: $save_usercreate{'cancreate'}{'emailoptions'} = $cancreate{'emailoptions'};
18619: }
1.303 raeburn 18620: if (ref($cancreate{'emaildomain'}) eq 'HASH') {
18621: $save_usercreate{'cancreate'}{'emaildomain'} = $cancreate{'emaildomain'};
18622: }
1.224 raeburn 18623: if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
18624: $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'};
18625: }
1.240 raeburn 18626: if (ref($cancreate{'shibenv'}) eq 'HASH') {
18627: $save_usercreate{'cancreate'}{'shibenv'} = $cancreate{'shibenv'};
18628: }
1.224 raeburn 18629: $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'};
1.305 raeburn 18630: $save_usercreate{'email_rule'} = \%email_rule;
1.224 raeburn 18631:
18632: my %userconfig_hash = (
18633: usercreation => \%save_usercreate,
18634: usermodification => \%save_usermodify,
1.305 raeburn 18635: inststatus => \%save_inststatus,
1.224 raeburn 18636: );
1.305 raeburn 18637:
1.224 raeburn 18638: my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash,
18639: $dom);
18640: #
1.305 raeburn 18641: # Accumulate details of changes to domain configuration for self-creation of usernames in $resulttext
1.224 raeburn 18642: #
1.27 raeburn 18643: if ($putresult eq 'ok') {
18644: if (keys(%changes) > 0) {
18645: $resulttext = &mt('Changes made:').'<ul>';
18646: if (ref($changes{'cancreate'}) eq 'ARRAY') {
1.224 raeburn 18647: my %lt = &selfcreation_types();
1.34 raeburn 18648: foreach my $type (@{$changes{'cancreate'}}) {
1.303 raeburn 18649: my $chgtext = '';
1.45 raeburn 18650: if ($type eq 'selfcreate') {
1.50 raeburn 18651: if (@{$cancreate{$type}} == 0) {
1.224 raeburn 18652: $chgtext .= &mt('Self creation of a new user account is not permitted.');
1.50 raeburn 18653: } else {
1.224 raeburn 18654: $chgtext .= &mt('Self-creation of a new account is permitted for:').
18655: '<ul>';
1.50 raeburn 18656: foreach my $case (@{$cancreate{$type}}) {
18657: $chgtext .= '<li>'.$selfcreatetypes{$case}.'</li>';
18658: }
18659: $chgtext .= '</ul>';
1.100 raeburn 18660: if (ref($cancreate{$type}) eq 'ARRAY') {
18661: if (grep(/^(login|sso)$/,@{$cancreate{$type}})) {
18662: if (ref($cancreate{'statustocreate'}) eq 'ARRAY') {
18663: if (@{$cancreate{'statustocreate'}} == 0) {
1.303 raeburn 18664: $chgtext .= '<span class="LC_warning">'.
18665: &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts via log-in or single sign-on.").
18666: '</span><br />';
18667: }
18668: }
18669: }
18670: if (grep(/^email$/,@{$cancreate{$type}})) {
1.305 raeburn 18671: if (!@statuses) {
18672: $chgtext .= '<span class="LC_warning">'.
18673: &mt("However, e-mail verification is currently set to 'unavailable' for all user types (including 'other'), so self-creation of accounts is not possible for non-institutional log-in.").
18674: '</span><br />';
1.303 raeburn 18675:
1.100 raeburn 18676: }
18677: }
18678: }
1.43 raeburn 18679: }
1.240 raeburn 18680: } elsif ($type eq 'shibenv') {
18681: if (keys(%{$cancreate{$type}}) == 0) {
1.303 raeburn 18682: $chgtext .= &mt('Shibboleth-autheticated user does not use environment variables to set user information').'<br />';
1.240 raeburn 18683: } else {
18684: $chgtext .= &mt('Shibboleth-autheticated user information set from environment variables, as follows:').
18685: '<ul>';
18686: foreach my $field (@shibfields) {
18687: next if ($cancreate{$type}{$field} eq '');
18688: if ($field eq 'inststatus') {
18689: $chgtext .= '<li>'.&mt('Institutional status').' -- '.$cancreate{$type}{$field}.'</li>';
18690: } else {
18691: $chgtext .= '<li>'.$fieldtitles{$field}.' -- '.$cancreate{$type}{$field}.'</li>';
18692: }
18693: }
18694: $chgtext .= '</ul>';
1.303 raeburn 18695: }
1.93 raeburn 18696: } elsif ($type eq 'statustocreate') {
1.96 raeburn 18697: if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') &&
18698: (ref($cancreate{'statustocreate'}) eq 'ARRAY')) {
18699: if (@{$cancreate{'selfcreate'}} > 0) {
18700: if (@{$cancreate{'statustocreate'}} == 0) {
1.100 raeburn 18701: $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'.");
1.96 raeburn 18702: if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) {
1.224 raeburn 18703: $chgtext .= '<br />'.
18704: '<span class="LC_warning">'.
18705: &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").
18706: '</span>';
18707: }
1.303 raeburn 18708: } elsif (keys(%usertypes) > 0) {
1.96 raeburn 18709: if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
1.100 raeburn 18710: $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):');
18711: } else {
18712: $chgtext .= &mt('Institutional affiliations permitted to create accounts with institutional authentication were set as follows:');
18713: }
18714: $chgtext .= '<ul>';
18715: foreach my $case (@{$cancreate{$type}}) {
18716: if ($case eq 'default') {
18717: $chgtext .= '<li>'.$othertitle.'</li>';
18718: } else {
1.303 raeburn 18719: $chgtext .= '<li>'.$usertypes{$case}.'</li>';
1.93 raeburn 18720: }
18721: }
1.100 raeburn 18722: $chgtext .= '</ul>';
18723: if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) {
1.303 raeburn 18724: $chgtext .= '<span class="LC_warning">'.
1.224 raeburn 18725: &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').
18726: '</span>';
1.100 raeburn 18727: }
18728: }
18729: } else {
18730: if (@{$cancreate{$type}} == 0) {
18731: $chgtext .= &mt("Institutional affiliations permitted to create accounts were set to 'none'.");
18732: } else {
18733: $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.');
1.93 raeburn 18734: }
18735: }
1.303 raeburn 18736: $chgtext .= '<br />';
1.93 raeburn 18737: }
1.236 raeburn 18738: } elsif ($type eq 'selfcreateprocessing') {
18739: my %choices = &Apache::lonlocal::texthash (
18740: automatic => 'Automatic approval',
18741: approval => 'Queued for approval',
18742: );
1.305 raeburn 18743: if (@types) {
18744: if (@statuses) {
1.425 raeburn 18745: $chgtext .= &mt('Processing of requests to create account with e-mail verification set as follows:').
1.309 raeburn 18746: '<ul>';
1.305 raeburn 18747: foreach my $status (@statuses) {
18748: if ($status eq 'default') {
18749: $chgtext .= '<li>'.$othertitle.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';
1.303 raeburn 18750: } else {
1.305 raeburn 18751: $chgtext .= '<li>'.$usertypes{$status}.' -- '.$choices{$cancreate{'selfcreateprocessing'}{$status}}.'</li>';
1.303 raeburn 18752: }
18753: }
18754: $chgtext .= '</ul>';
18755: }
18756: } else {
18757: $chgtext .= &mt('Processing of requests to create account with e-mail verification set to: "[_1]"',
18758: $choices{$cancreate{'selfcreateprocessing'}{'default'}});
18759: }
18760: } elsif ($type eq 'emailverified') {
18761: my %options = &Apache::lonlocal::texthash (
1.305 raeburn 18762: all => 'Same as e-mail',
18763: first => 'Omit @domain',
18764: free => 'Free to choose',
1.303 raeburn 18765: );
1.305 raeburn 18766: if (@types) {
18767: if (@statuses) {
1.303 raeburn 18768: $chgtext .= &mt('For self-created accounts verified by e-mail address, username is set as follows:').
18769: '<ul>';
1.305 raeburn 18770: foreach my $status (@statuses) {
1.362 raeburn 18771: if ($status eq 'default') {
1.305 raeburn 18772: $chgtext .= '<li>'.$othertitle.' -- '.$options{$cancreate{'emailverified'}{$status}}.'</li>';
1.303 raeburn 18773: } else {
1.305 raeburn 18774: $chgtext .= '<li>'.$usertypes{$status}.' -- '.$options{$cancreate{'emailverified'}{$status}}.'</li>';
1.303 raeburn 18775: }
18776: }
18777: $chgtext .= '</ul>';
18778: }
18779: } else {
1.305 raeburn 18780: $chgtext .= &mt("For self-created accounts verified by e-mail address, user's username is: '[_1]'",
1.304 raeburn 18781: $options{$cancreate{'emailverified'}{'default'}});
1.303 raeburn 18782: }
1.305 raeburn 18783: } elsif ($type eq 'emailoptions') {
18784: my %options = &Apache::lonlocal::texthash (
18785: any => 'Any e-mail',
18786: inst => 'Institutional only',
18787: noninst => 'Non-institutional only',
18788: custom => 'Custom restrictions',
18789: );
18790: if (@types) {
18791: if (@statuses) {
18792: $chgtext .= &mt('For self-created accounts verified by e-mail address, requirements for e-mail address are as follows:').
18793: '<ul>';
18794: foreach my $status (@statuses) {
18795: if ($type eq 'default') {
18796: $chgtext .= '<li>'.$othertitle.' -- '.$options{$cancreate{'emailoptions'}{$status}}.'</li>';
18797: } else {
18798: $chgtext .= '<li>'.$usertypes{$status}.' -- '.$options{$cancreate{'emailoptions'}{$status}}.'</li>';
1.303 raeburn 18799: }
18800: }
1.305 raeburn 18801: $chgtext .= '</ul>';
18802: }
18803: } else {
18804: if ($cancreate{'emailoptions'}{'default'} eq 'any') {
18805: $chgtext .= &mt('For self-created accounts verified by e-mail address, any e-mail may be used');
18806: } else {
18807: $chgtext .= &mt('For self-created accounts verified by e-mail address, e-mail restricted to: "[_1]"',
18808: $options{$cancreate{'emailoptions'}{'default'}});
1.303 raeburn 18809: }
1.305 raeburn 18810: }
18811: } elsif ($type eq 'emaildomain') {
18812: my $output;
18813: if (@statuses) {
18814: foreach my $type (@statuses) {
18815: if (ref($cancreate{'emaildomain'}{$type}) eq 'HASH') {
18816: if ($cancreate{'emailoptions'}{$type} eq 'inst') {
18817: if ($type eq 'default') {
18818: if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||
18819: ($cancreate{'emaildomain'}{$type}{'inst'} eq '')) {
18820: $output = '<li>'.$othertitle.' -- '.&mt('No restriction on e-mail domain').'</li>';
18821: } else {
18822: $output = '<li>'.$othertitle.' -- '.&mt("User's e-mail address needs to end: [_1]",
18823: $cancreate{'emaildomain'}{$type}{'inst'}).'</li>';
18824: }
1.303 raeburn 18825: } else {
1.305 raeburn 18826: if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||
18827: ($cancreate{'emaildomain'}{$type}{'inst'} eq '')) {
18828: $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';
18829: } else {
18830: $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address needs to end: [_1]",
1.421 raeburn 18831: $cancreate{'emaildomain'}{$type}{'inst'}).'</li>';
1.305 raeburn 18832: }
1.303 raeburn 18833: }
1.305 raeburn 18834: } elsif ($cancreate{'emailoptions'}{$type} eq 'noninst') {
18835: if ($type eq 'default') {
18836: if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||
18837: ($cancreate{'emaildomain'}{$type}{'noninst'} eq '')) {
18838: $output = '<li>'.$othertitle.' -- '.&mt('No restriction on e-mail domain').'</li>';
18839: } else {
18840: $output = '<li>'.$othertitle.' -- '.&mt("User's e-mail address must not end: [_1]",
18841: $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';
18842: }
1.303 raeburn 18843: } else {
1.305 raeburn 18844: if ((ref($cancreate{'emaildomain'}{$type}) ne 'HASH') ||
18845: ($cancreate{'emaildomain'}{$type}{'noninst'} eq '')) {
18846: $output = '<li>'.$usertypes{$type}.' -- '.&mt('No restriction on e-mail domain').'</li>';
18847: } else {
18848: $output = '<li>'.$usertypes{$type}.' -- '.&mt("User's e-mail address must not end: [_1]",
1.421 raeburn 18849: $cancreate{'emaildomain'}{$type}{'noninst'}).'</li>';
1.305 raeburn 18850: }
1.303 raeburn 18851: }
18852: }
18853: }
18854: }
1.305 raeburn 18855: }
18856: if ($output ne '') {
18857: $chgtext .= &mt('For self-created accounts verified by e-mail address:').
18858: '<ul>'.$output.'</ul>';
1.236 raeburn 18859: }
1.165 raeburn 18860: } elsif ($type eq 'captcha') {
1.224 raeburn 18861: if ($savecaptcha{$type} eq 'notused') {
1.165 raeburn 18862: $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.');
18863: } else {
18864: my %captchas = &captcha_phrases();
1.224 raeburn 18865: if ($captchas{$savecaptcha{$type}}) {
18866: $chgtext .= &mt("Validation for self-creation screen set to $captchas{$savecaptcha{$type}}.");
1.165 raeburn 18867: } else {
1.210 raeburn 18868: $chgtext .= &mt('Validation for self-creation screen set to unknown type.');
1.165 raeburn 18869: }
18870: }
18871: } elsif ($type eq 'recaptchakeys') {
18872: my ($privkey,$pubkey);
1.224 raeburn 18873: if (ref($savecaptcha{$type}) eq 'HASH') {
18874: $pubkey = $savecaptcha{$type}{'public'};
18875: $privkey = $savecaptcha{$type}{'private'};
1.165 raeburn 18876: }
18877: $chgtext .= &mt('ReCAPTCHA keys changes').'<ul>';
18878: if (!$pubkey) {
18879: $chgtext .= '<li>'.&mt('Public key deleted').'</li>';
18880: } else {
18881: $chgtext .= '<li>'.&mt('Public key set to [_1]',$pubkey).'</li>';
18882: }
18883: if (!$privkey) {
18884: $chgtext .= '<li>'.&mt('Private key deleted').'</li>';
18885: } else {
18886: $chgtext .= '<li>'.&mt('Private key set to [_1]',$pubkey).'</li>';
18887: }
18888: $chgtext .= '</ul>';
1.269 raeburn 18889: } elsif ($type eq 'recaptchaversion') {
18890: if ($savecaptcha{'captcha'} eq 'recaptcha') {
1.270 raeburn 18891: $chgtext .= &mt('ReCAPTCHA set to version [_1]',$savecaptcha{$type});
1.269 raeburn 18892: }
1.224 raeburn 18893: } elsif ($type eq 'emailusername') {
18894: if (ref($cancreate{'emailusername'}) eq 'HASH') {
1.305 raeburn 18895: if (@statuses) {
18896: foreach my $type (@statuses) {
1.228 raeburn 18897: if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') {
18898: if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) {
1.303 raeburn 18899: $chgtext .= &mt('When self-creating account with e-mail verification, the following information will be provided by [_1]:',"'$usertypes{$type}'").
1.228 raeburn 18900: '<ul>';
18901: foreach my $field (@{$infofields}) {
18902: if ($cancreate{'emailusername'}{$type}{$field}) {
18903: $chgtext .= '<li>'.$infotitles->{$field}.'</li>';
18904: }
18905: }
1.245 raeburn 18906: $chgtext .= '</ul>';
18907: } else {
1.303 raeburn 18908: $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';
1.228 raeburn 18909: }
18910: } else {
1.303 raeburn 18911: $chgtext .= &mt('When self creating account with e-mail verification, no information besides e-mail address will be provided by [_1].',"'$usertypes{$type}'").'<br />';
1.224 raeburn 18912: }
18913: }
18914: }
18915: }
18916: } elsif ($type eq 'notify') {
1.303 raeburn 18917: my $numapprove = 0;
1.224 raeburn 18918: if (ref($changes{'cancreate'}) eq 'ARRAY') {
18919: if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) {
18920: if ($cancreate{'notify'}{'approval'}) {
1.303 raeburn 18921: $chgtext .= &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'};
18922: $numapprove ++;
1.224 raeburn 18923: }
18924: }
1.43 raeburn 18925: }
1.303 raeburn 18926: unless ($numapprove) {
18927: $chgtext .= &mt('No Domain Coordinators will receive notification of username requests requiring approval.');
18928: }
1.34 raeburn 18929: }
1.224 raeburn 18930: if ($chgtext) {
18931: $resulttext .= '<li>'.$chgtext.'</li>';
1.32 raeburn 18932: }
18933: }
18934: }
1.305 raeburn 18935: if ((ref($changes{'email_rule'}) eq 'ARRAY') && (@{$changes{'email_rule'}} > 0)) {
1.43 raeburn 18936: my ($emailrules,$emailruleorder) =
18937: &Apache::lonnet::inst_userrules($dom,'email');
1.305 raeburn 18938: foreach my $type (@{$changes{'email_rule'}}) {
18939: if (ref($email_rule{$type}) eq 'ARRAY') {
18940: my $chgtext = '<ul>';
18941: foreach my $rule (@{$email_rule{$type}}) {
18942: if (ref($emailrules->{$rule}) eq 'HASH') {
18943: $chgtext .= '<li>'.$emailrules->{$rule}{'name'}.'</li>';
18944: }
18945: }
18946: $chgtext .= '</ul>';
1.310 raeburn 18947: my $typename;
1.305 raeburn 18948: if (@types) {
18949: if ($type eq 'default') {
18950: $typename = $othertitle;
18951: } else {
18952: $typename = $usertypes{$type};
1.425 raeburn 18953: }
1.305 raeburn 18954: $chgtext .= &mt('(Affiliation: [_1])',$typename);
18955: }
18956: if (@{$email_rule{$type}} > 0) {
18957: $resulttext .= '<li>'.
18958: &mt('Accounts may not be created by users verified by e-mail, for e-mail addresses of the following types: ',
18959: $usertypes{$type}).
18960: $chgtext.
18961: '</li>';
18962: } else {
18963: $resulttext .= '<li>'.
1.310 raeburn 18964: &mt('There are now no restrictions on e-mail addresses which may be used for verification when a user requests an account.').
1.305 raeburn 18965: '</li>'.
1.310 raeburn 18966: &mt('(Affiliation: [_1])',$typename);
1.305 raeburn 18967: }
1.43 raeburn 18968: }
18969: }
1.305 raeburn 18970: }
18971: if (ref($changes{'inststatus'}) eq 'ARRAY') {
18972: if (ref($save_inststatus{'inststatusguest'}) eq 'ARRAY') {
18973: if (@{$save_inststatus{'inststatusguest'}} > 0) {
18974: my $chgtext = '<ul>';
18975: foreach my $type (@{$save_inststatus{'inststatusguest'}}) {
18976: $chgtext .= '<li>'.$usertypes{$type}.'</li>';
18977: }
18978: $chgtext .= '</ul>';
18979: $resulttext .= '<li>'.
18980: &mt('A user will self-report one of the following affiliations when requesting an account verified by e-mail: ').
18981: $chgtext.
18982: '</li>';
18983: } else {
18984: $resulttext .= '<li>'.
18985: &mt('No affiliations available for self-reporting when requesting an account verified by e-mail.').
18986: '</li>';
18987: }
1.43 raeburn 18988: }
18989: }
1.224 raeburn 18990: if (ref($changes{'selfcreate'}) eq 'ARRAY') {
18991: $resulttext .= '<li>'.&mt('When self-creating institutional account:').'<ul>';
18992: my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
18993: foreach my $type (@{$changes{'selfcreate'}}) {
18994: my $typename = $type;
1.303 raeburn 18995: if (keys(%usertypes) > 0) {
18996: if ($usertypes{$type} ne '') {
18997: $typename = $usertypes{$type};
1.224 raeburn 18998: }
18999: }
19000: my @modifiable;
19001: $resulttext .= '<li>'.
19002: &mt('Self-creation of account by users with status: [_1]',
19003: '<span class="LC_cusr_emph">'.$typename.'</span>').
19004: ' - '.&mt('modifiable fields (if institutional data blank): ');
19005: foreach my $field (@fields) {
19006: if ($save_usermodify{'selfcreate'}{$type}{$field}) {
19007: push(@modifiable,'<b>'.$fieldtitles{$field}.'</b>');
1.28 raeburn 19008: }
19009: }
1.224 raeburn 19010: if (@modifiable > 0) {
19011: $resulttext .= join(', ',@modifiable);
1.43 raeburn 19012: } else {
1.224 raeburn 19013: $resulttext .= &mt('none');
1.43 raeburn 19014: }
1.224 raeburn 19015: $resulttext .= '</li>';
1.28 raeburn 19016: }
1.224 raeburn 19017: $resulttext .= '</ul></li>';
1.28 raeburn 19018: }
1.27 raeburn 19019: $resulttext .= '</ul>';
1.305 raeburn 19020: my $cachetime = 24*60*60;
19021: $domdefaults{'inststatusguest'} = $save_inststatus{'inststatusguest'};
19022: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
19023: if (ref($lastactref) eq 'HASH') {
19024: $lastactref->{'domdefaults'} = 1;
19025: }
1.27 raeburn 19026: } else {
1.224 raeburn 19027: $resulttext = &mt('No changes made to self-creation settings');
1.27 raeburn 19028: }
19029: } else {
19030: $resulttext = '<span class="LC_error">'.
1.23 raeburn 19031: &mt('An error occurred: [_1]',$putresult).'</span>';
19032: }
1.43 raeburn 19033: if ($warningmsg ne '') {
19034: $resulttext .= '<br /><span class="LC_warning">'.$warningmsg.'</span><br />';
19035: }
1.23 raeburn 19036: return $resulttext;
19037: }
19038:
1.165 raeburn 19039: sub process_captcha {
1.369 raeburn 19040: my ($container,$changes,$newsettings,$currsettings) = @_;
19041: return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH'));
1.165 raeburn 19042: $newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
19043: unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
19044: $newsettings->{'captcha'} = 'original';
19045: }
1.369 raeburn 19046: my %current;
19047: if (ref($currsettings) eq 'HASH') {
19048: %current = %{$currsettings};
19049: }
19050: if ($current{'captcha'} ne $newsettings->{'captcha'}) {
1.210 raeburn 19051: if ($container eq 'cancreate') {
1.169 raeburn 19052: if (ref($changes->{'cancreate'}) eq 'ARRAY') {
19053: push(@{$changes->{'cancreate'}},'captcha');
19054: } elsif (!defined($changes->{'cancreate'})) {
19055: $changes->{'cancreate'} = ['captcha'];
19056: }
1.368 raeburn 19057: } elsif ($container eq 'passwords') {
19058: $changes->{'reset'} = 1;
1.169 raeburn 19059: } else {
19060: $changes->{'captcha'} = 1;
1.165 raeburn 19061: }
19062: }
1.269 raeburn 19063: my ($newpub,$newpriv,$currpub,$currpriv,$newversion,$currversion);
1.165 raeburn 19064: if ($newsettings->{'captcha'} eq 'recaptcha') {
19065: $newpub = $env{'form.'.$container.'_recaptchapub'};
19066: $newpriv = $env{'form.'.$container.'_recaptchapriv'};
1.250 raeburn 19067: $newpub =~ s/[^\w\-]//g;
19068: $newpriv =~ s/[^\w\-]//g;
1.169 raeburn 19069: $newsettings->{'recaptchakeys'} = {
19070: public => $newpub,
19071: private => $newpriv,
19072: };
1.269 raeburn 19073: $newversion = $env{'form.'.$container.'_recaptchaversion'};
19074: $newversion =~ s/\D//g;
19075: if ($newversion ne '2') {
19076: $newversion = 1;
19077: }
19078: $newsettings->{'recaptchaversion'} = $newversion;
1.165 raeburn 19079: }
1.369 raeburn 19080: if (ref($current{'recaptchakeys'}) eq 'HASH') {
19081: $currpub = $current{'recaptchakeys'}{'public'};
19082: $currpriv = $current{'recaptchakeys'}{'private'};
1.179 raeburn 19083: unless ($newsettings->{'captcha'} eq 'recaptcha') {
19084: $newsettings->{'recaptchakeys'} = {
19085: public => '',
19086: private => '',
19087: }
19088: }
1.165 raeburn 19089: }
1.369 raeburn 19090: if ($current{'captcha'} eq 'recaptcha') {
19091: $currversion = $current{'recaptchaversion'};
1.269 raeburn 19092: if ($currversion ne '2') {
19093: $currversion = 1;
19094: }
19095: }
19096: if ($currversion ne $newversion) {
19097: if ($container eq 'cancreate') {
19098: if (ref($changes->{'cancreate'}) eq 'ARRAY') {
19099: push(@{$changes->{'cancreate'}},'recaptchaversion');
19100: } elsif (!defined($changes->{'cancreate'})) {
19101: $changes->{'cancreate'} = ['recaptchaversion'];
19102: }
1.368 raeburn 19103: } elsif ($container eq 'passwords') {
19104: $changes->{'reset'} = 1;
1.269 raeburn 19105: } else {
19106: $changes->{'recaptchaversion'} = 1;
19107: }
19108: }
1.165 raeburn 19109: if (($newpub ne $currpub) || ($newpriv ne $currpriv)) {
1.169 raeburn 19110: if ($container eq 'cancreate') {
19111: if (ref($changes->{'cancreate'}) eq 'ARRAY') {
19112: push(@{$changes->{'cancreate'}},'recaptchakeys');
19113: } elsif (!defined($changes->{'cancreate'})) {
19114: $changes->{'cancreate'} = ['recaptchakeys'];
19115: }
1.368 raeburn 19116: } elsif ($container eq 'passwords') {
19117: $changes->{'reset'} = 1;
1.169 raeburn 19118: } else {
1.210 raeburn 19119: $changes->{'recaptchakeys'} = 1;
1.165 raeburn 19120: }
19121: }
19122: return;
19123: }
19124:
1.33 raeburn 19125: sub modify_usermodification {
19126: my ($dom,%domconfig) = @_;
1.224 raeburn 19127: my ($resulttext,%curr_usermodification,%changes,%modifyhash);
1.33 raeburn 19128: if (ref($domconfig{'usermodification'}) eq 'HASH') {
19129: foreach my $key (keys(%{$domconfig{'usermodification'}})) {
1.224 raeburn 19130: if ($key eq 'selfcreate') {
19131: $modifyhash{$key} = $domconfig{'usermodification'}{$key};
19132: } else {
19133: $curr_usermodification{$key} = $domconfig{'usermodification'}{$key};
19134: }
1.33 raeburn 19135: }
19136: }
1.224 raeburn 19137: my @contexts = ('author','course');
1.33 raeburn 19138: my %context_title = (
19139: author => 'In author context',
19140: course => 'In course context',
19141: );
19142: my @fields = ('lastname','firstname','middlename','generation',
19143: 'permanentemail','id');
19144: my %roles = (
19145: author => ['ca','aa'],
19146: course => ['st','ep','ta','in','cr'],
19147: );
19148: my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
19149: foreach my $context (@contexts) {
19150: foreach my $role (@{$roles{$context}}) {
19151: my @modifiable = &Apache::loncommon::get_env_multiple('form.canmodify_'.$role);
19152: foreach my $item (@fields) {
19153: if (grep(/^\Q$item\E$/,@modifiable)) {
19154: $modifyhash{$context}{$role}{$item} = 1;
19155: } else {
19156: $modifyhash{$context}{$role}{$item} = 0;
19157: }
19158: }
19159: }
19160: if (ref($curr_usermodification{$context}) eq 'HASH') {
19161: foreach my $role (@{$roles{$context}}) {
19162: if (ref($curr_usermodification{$context}{$role}) eq 'HASH') {
19163: foreach my $field (@fields) {
19164: if ($modifyhash{$context}{$role}{$field} ne
19165: $curr_usermodification{$context}{$role}{$field}) {
19166: push(@{$changes{$context}},$role);
19167: last;
19168: }
19169: }
19170: }
19171: }
19172: } else {
19173: foreach my $context (@contexts) {
19174: foreach my $role (@{$roles{$context}}) {
19175: push(@{$changes{$context}},$role);
19176: }
19177: }
19178: }
19179: }
19180: my %usermodification_hash = (
19181: usermodification => \%modifyhash,
19182: );
19183: my $putresult = &Apache::lonnet::put_dom('configuration',
19184: \%usermodification_hash,$dom);
19185: if ($putresult eq 'ok') {
19186: if (keys(%changes) > 0) {
19187: $resulttext = &mt('Changes made: ').'<ul>';
19188: foreach my $context (@contexts) {
19189: if (ref($changes{$context}) eq 'ARRAY') {
19190: $resulttext .= '<li>'.$context_title{$context}.':<ul>';
19191: if (ref($changes{$context}) eq 'ARRAY') {
19192: foreach my $role (@{$changes{$context}}) {
19193: my $rolename;
1.224 raeburn 19194: if ($role eq 'cr') {
19195: $rolename = &mt('Custom');
1.33 raeburn 19196: } else {
1.224 raeburn 19197: $rolename = &Apache::lonnet::plaintext($role);
1.33 raeburn 19198: }
19199: my @modifiable;
1.224 raeburn 19200: $resulttext .= '<li><span class="LC_cusr_emph">'.&mt('Target user with [_1] role',$rolename).'</span> - '.&mt('modifiable fields: ');
1.33 raeburn 19201: foreach my $field (@fields) {
19202: if ($modifyhash{$context}{$role}{$field}) {
19203: push(@modifiable,$fieldtitles{$field});
19204: }
19205: }
19206: if (@modifiable > 0) {
19207: $resulttext .= join(', ',@modifiable);
19208: } else {
19209: $resulttext .= &mt('none');
19210: }
19211: $resulttext .= '</li>';
19212: }
19213: $resulttext .= '</ul></li>';
19214: }
19215: }
19216: }
19217: $resulttext .= '</ul>';
19218: } else {
19219: $resulttext = &mt('No changes made to user modification settings');
19220: }
19221: } else {
19222: $resulttext = '<span class="LC_error">'.
19223: &mt('An error occurred: [_1]',$putresult).'</span>';
19224: }
19225: return $resulttext;
19226: }
19227:
1.43 raeburn 19228: sub modify_defaults {
1.212 raeburn 19229: my ($dom,$lastactref,%domconfig) = @_;
1.43 raeburn 19230: my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);
1.212 raeburn 19231: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
1.294 raeburn 19232: my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
1.354 raeburn 19233: 'portal_def');
1.325 raeburn 19234: my @authtypes = ('internal','krb4','krb5','localauth','lti');
1.43 raeburn 19235: foreach my $item (@items) {
19236: $newvalues{$item} = $env{'form.'.$item};
19237: if ($item eq 'auth_def') {
19238: if ($newvalues{$item} ne '') {
19239: if (!grep(/^\Q$newvalues{$item}\E$/,@authtypes)) {
19240: push(@errors,$item);
19241: }
19242: }
19243: } elsif ($item eq 'lang_def') {
19244: if ($newvalues{$item} ne '') {
19245: if ($newvalues{$item} =~ /^(\w+)/) {
19246: my $langcode = $1;
1.103 raeburn 19247: if ($langcode ne 'x_chef') {
19248: if (code2language($langcode) eq '') {
19249: push(@errors,$item);
19250: }
1.43 raeburn 19251: }
19252: } else {
19253: push(@errors,$item);
19254: }
19255: }
1.54 raeburn 19256: } elsif ($item eq 'timezone_def') {
19257: if ($newvalues{$item} ne '') {
1.62 raeburn 19258: if (!DateTime::TimeZone->is_valid_name($newvalues{$item})) {
1.54 raeburn 19259: push(@errors,$item);
19260: }
19261: }
1.68 raeburn 19262: } elsif ($item eq 'datelocale_def') {
19263: if ($newvalues{$item} ne '') {
19264: my @datelocale_ids = DateTime::Locale->ids();
19265: if (!grep(/^\Q$newvalues{$item}\E$/,@datelocale_ids)) {
19266: push(@errors,$item);
19267: }
19268: }
1.141 raeburn 19269: } elsif ($item eq 'portal_def') {
19270: if ($newvalues{$item} ne '') {
1.414 raeburn 19271: if ($newvalues{$item} =~ /^https?\:\/\/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])\/?$/) {
19272: foreach my $field ('email','web') {
19273: if ($env{'form.'.$item.'_'.$field}) {
19274: $newvalues{$item.'_'.$field} = $env{'form.'.$item.'_'.$field};
19275: }
19276: }
19277: } else {
1.141 raeburn 19278: push(@errors,$item);
19279: }
19280: }
1.43 raeburn 19281: }
19282: if (grep(/^\Q$item\E$/,@errors)) {
19283: $newvalues{$item} = $domdefaults{$item};
1.414 raeburn 19284: if ($item eq 'portal_def') {
19285: if ($domdefaults{$item}) {
19286: foreach my $field ('email','web') {
19287: if (exists($domdefaults{$item.'_'.$field})) {
19288: $newvalues{$item.'_'.$field} = $domdefaults{$item.'_'.$field};
19289: }
19290: }
19291: }
19292: }
1.43 raeburn 19293: } elsif ($domdefaults{$item} ne $newvalues{$item}) {
19294: $changes{$item} = 1;
19295: }
1.414 raeburn 19296: if ($item eq 'portal_def') {
19297: unless (grep(/^\Q$item\E$/,@errors)) {
1.425 raeburn 19298: if ($newvalues{$item} eq '') {
1.414 raeburn 19299: foreach my $field ('email','web') {
19300: if (exists($domdefaults{$item.'_'.$field})) {
19301: delete($domdefaults{$item.'_'.$field});
19302: }
19303: }
19304: } else {
19305: unless ($changes{$item}) {
19306: foreach my $field ('email','web') {
19307: if ($domdefaults{$item.'_'.$field} ne $newvalues{$item.'_'.$field}) {
19308: $changes{$item} = 1;
19309: last;
19310: }
19311: }
19312: }
19313: foreach my $field ('email','web') {
19314: if ($newvalues{$item.'_'.$field}) {
19315: $domdefaults{$item.'_'.$field} = $newvalues{$item.'_'.$field};
19316: } elsif (exists($domdefaults{$item.'_'.$field})) {
19317: delete($domdefaults{$item.'_'.$field});
19318: }
19319: }
19320: }
19321: }
19322: }
1.72 raeburn 19323: $domdefaults{$item} = $newvalues{$item};
1.43 raeburn 19324: }
1.354 raeburn 19325: my %staticdefaults = (
19326: 'intauth_cost' => 10,
19327: 'intauth_check' => 0,
19328: 'intauth_switch' => 0,
19329: );
19330: foreach my $item ('intauth_cost','intauth_check','intauth_switch') {
19331: if (exists($domdefaults{$item})) {
19332: $newvalues{$item} = $domdefaults{$item};
19333: } else {
19334: $newvalues{$item} = $staticdefaults{$item};
19335: }
19336: }
1.409 raeburn 19337: my ($unamemaprules,$ruleorder);
19338: my @possunamemaprules = &Apache::loncommon::get_env_multiple('form.unamemap_rule');
19339: if (@possunamemaprules) {
19340: ($unamemaprules,$ruleorder) =
19341: &Apache::lonnet::inst_userrules($dom,'unamemap');
19342: if ((ref($unamemaprules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {
19343: if (@{$ruleorder} > 0) {
19344: my %possrules;
19345: map { $possrules{$_} = 1; } @possunamemaprules;
19346: foreach my $rule (@{$ruleorder}) {
19347: if ($possrules{$rule}) {
19348: push(@{$newvalues{'unamemap_rule'}},$rule);
19349: }
19350: }
19351: }
19352: }
19353: }
19354: if (ref($domdefaults{'unamemap_rule'}) eq 'ARRAY') {
19355: if (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {
19356: my @rulediffs = &Apache::loncommon::compare_arrays($domdefaults{'unamemap_rule'},
19357: $newvalues{'unamemap_rule'});
19358: if (@rulediffs) {
19359: $changes{'unamemap_rule'} = 1;
19360: $domdefaults{'unamemap_rule'} = $newvalues{'unamemap_rule'};
19361: }
19362: } elsif (@{$domdefaults{'unamemap_rule'}} > 0) {
19363: $changes{'unamemap_rule'} = 1;
19364: delete($domdefaults{'unamemap_rule'});
19365: }
19366: } elsif (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {
19367: if (@{$newvalues{'unamemap_rule'}} > 0) {
19368: $changes{'unamemap_rule'} = 1;
19369: $domdefaults{'unamemap_rule'} = $newvalues{'unamemap_rule'};
19370: }
19371: }
1.43 raeburn 19372: my %defaults_hash = (
1.72 raeburn 19373: defaults => \%newvalues,
19374: );
1.43 raeburn 19375: my $title = &defaults_titles();
1.236 raeburn 19376:
19377: my $currinststatus;
19378: if (ref($domconfig{'inststatus'}) eq 'HASH') {
19379: $currinststatus = $domconfig{'inststatus'};
19380: } else {
19381: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
19382: $currinststatus = {
19383: inststatustypes => $usertypes,
19384: inststatusorder => $types,
19385: inststatusguest => [],
19386: };
19387: }
19388: my @todelete = &Apache::loncommon::get_env_multiple('form.inststatus_delete');
19389: my @allpos;
19390: my %alltypes;
1.305 raeburn 19391: my @inststatusguest;
19392: if (ref($currinststatus->{'inststatusguest'}) eq 'ARRAY') {
19393: foreach my $type (@{$currinststatus->{'inststatusguest'}}) {
19394: unless (grep(/^\Q$type\E$/,@todelete)) {
19395: push(@inststatusguest,$type);
19396: }
19397: }
19398: }
19399: my ($currtitles,$currorder);
1.236 raeburn 19400: if (ref($currinststatus) eq 'HASH') {
19401: if (ref($currinststatus->{'inststatusorder'}) eq 'ARRAY') {
19402: foreach my $type (@{$currinststatus->{'inststatusorder'}}) {
19403: if (ref($currinststatus->{inststatustypes}) eq 'HASH') {
19404: if ($currinststatus->{inststatustypes}->{$type} ne '') {
19405: $currtitles .= $currinststatus->{inststatustypes}->{$type}.',';
19406: }
19407: }
19408: unless (grep(/^\Q$type\E$/,@todelete)) {
19409: my $position = $env{'form.inststatus_pos_'.$type};
19410: $position =~ s/\D+//g;
19411: $allpos[$position] = $type;
19412: $alltypes{$type} = $env{'form.inststatus_title_'.$type};
19413: $alltypes{$type} =~ s/`//g;
19414: }
19415: }
19416: $currorder = join(',',@{$currinststatus->{'inststatusorder'}});
19417: $currtitles =~ s/,$//;
19418: }
19419: }
19420: if ($env{'form.addinststatus'}) {
19421: my $newtype = $env{'form.addinststatus'};
19422: $newtype =~ s/\W//g;
19423: unless (exists($alltypes{$newtype})) {
19424: $alltypes{$newtype} = $env{'form.addinststatus_title'};
19425: $alltypes{$newtype} =~ s/`//g;
19426: my $position = $env{'form.addinststatus_pos'};
19427: $position =~ s/\D+//g;
19428: if ($position ne '') {
19429: $allpos[$position] = $newtype;
19430: }
19431: }
19432: }
1.305 raeburn 19433: my @orderedstatus;
1.236 raeburn 19434: foreach my $type (@allpos) {
19435: unless (($type eq '') || (grep(/^\Q$type\E$/,@orderedstatus))) {
19436: push(@orderedstatus,$type);
19437: }
19438: }
19439: foreach my $type (keys(%alltypes)) {
19440: unless (grep(/^\Q$type\E$/,@orderedstatus)) {
19441: delete($alltypes{$type});
19442: }
19443: }
19444: $defaults_hash{'inststatus'} = {
19445: inststatustypes => \%alltypes,
19446: inststatusorder => \@orderedstatus,
1.305 raeburn 19447: inststatusguest => \@inststatusguest,
1.236 raeburn 19448: };
19449: if (ref($defaults_hash{'inststatus'}) eq 'HASH') {
19450: foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
19451: $domdefaults{$item} = $defaults_hash{'inststatus'}{$item};
19452: }
19453: }
19454: if ($currorder ne join(',',@orderedstatus)) {
19455: $changes{'inststatus'}{'inststatusorder'} = 1;
19456: }
19457: my $newtitles;
19458: foreach my $item (@orderedstatus) {
19459: $newtitles .= $alltypes{$item}.',';
19460: }
19461: $newtitles =~ s/,$//;
19462: if ($currtitles ne $newtitles) {
19463: $changes{'inststatus'}{'inststatustypes'} = 1;
19464: }
1.43 raeburn 19465: my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash,
19466: $dom);
19467: if ($putresult eq 'ok') {
19468: if (keys(%changes) > 0) {
19469: $resulttext = &mt('Changes made:').'<ul>';
1.212 raeburn 19470: my $version = &Apache::lonnet::get_server_loncaparev($dom);
1.43 raeburn 19471: my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n";
19472: foreach my $item (sort(keys(%changes))) {
1.236 raeburn 19473: if ($item eq 'inststatus') {
19474: if (ref($changes{'inststatus'}) eq 'HASH') {
1.305 raeburn 19475: if (@orderedstatus) {
1.236 raeburn 19476: $resulttext .= '<li>'.&mt('Institutional user status types set to:').' ';
19477: foreach my $type (@orderedstatus) {
19478: $resulttext .= $alltypes{$type}.', ';
19479: }
19480: $resulttext =~ s/, $//;
19481: $resulttext .= '</li>';
1.305 raeburn 19482: } else {
1.425 raeburn 19483: $resulttext .= '<li>'.&mt('Institutional user status types deleted').'</li>';
1.236 raeburn 19484: }
19485: }
1.409 raeburn 19486: } elsif ($item eq 'unamemap_rule') {
19487: if (ref($newvalues{'unamemap_rule'}) eq 'ARRAY') {
19488: my @rulenames;
19489: if (ref($unamemaprules) eq 'HASH') {
19490: foreach my $rule (@{$newvalues{'unamemap_rule'}}) {
19491: if (ref($unamemaprules->{$rule}) eq 'HASH') {
19492: push(@rulenames,$unamemaprules->{$rule}->{'name'});
19493: }
19494: }
19495: }
19496: if (@rulenames) {
19497: $resulttext .= '<li>'.&mt('Mapping for missing usernames includes: [_1]',
19498: '<ul><li>'.join('</li><li>',@rulenames).'</li></ul>').
19499: '</li>';
19500: } else {
19501: $resulttext .= '<li>'.&mt('No mapping for missing usernames via standard log-in').'</li>';
19502: }
19503: } else {
19504: $resulttext .= '<li>'.&mt('Mapping for missing usernames via standard log-in deleted').'</li>';
19505: }
1.236 raeburn 19506: } else {
19507: my $value = $env{'form.'.$item};
19508: if ($value eq '') {
19509: $value = &mt('none');
19510: } elsif ($item eq 'auth_def') {
19511: my %authnames = &authtype_names();
19512: my %shortauth = (
19513: internal => 'int',
19514: krb4 => 'krb4',
19515: krb5 => 'krb5',
19516: localauth => 'loc',
1.325 raeburn 19517: lti => 'lti',
1.236 raeburn 19518: );
19519: $value = $authnames{$shortauth{$value}};
19520: }
19521: $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
1.414 raeburn 19522: $mailmsgtext .= "$title->{$item} set to $value\n";
19523: if ($item eq 'portal_def') {
19524: if ($env{'form.'.$item} ne '') {
19525: foreach my $field ('email','web') {
19526: $value = $env{'form.'.$item.'_'.$field};
19527: if ($value) {
19528: $value = &mt('Yes');
19529: } else {
19530: $value = &mt('No');
19531: }
19532: $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$field},$value).'</li>';
19533: }
19534: }
19535: }
1.43 raeburn 19536: }
19537: }
19538: $resulttext .= '</ul>';
19539: $mailmsgtext .= "\n";
19540: my $cachetime = 24*60*60;
1.72 raeburn 19541: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
1.212 raeburn 19542: if (ref($lastactref) eq 'HASH') {
19543: $lastactref->{'domdefaults'} = 1;
19544: }
1.68 raeburn 19545: if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) {
1.203 raeburn 19546: my $notify = 1;
19547: if (ref($domconfig{'contacts'}) eq 'HASH') {
19548: if ($domconfig{'contacts'}{'reportupdates'} == 0) {
19549: $notify = 0;
19550: }
19551: }
19552: if ($notify) {
19553: &Apache::lonmsg::sendemail('installrecord@loncapa.org',
19554: "LON-CAPA Domain Settings Change - $dom",
19555: $mailmsgtext);
19556: }
1.54 raeburn 19557: }
1.43 raeburn 19558: } else {
1.54 raeburn 19559: $resulttext = &mt('No changes made to default authentication/language/timezone settings');
1.43 raeburn 19560: }
19561: } else {
19562: $resulttext = '<span class="LC_error">'.
19563: &mt('An error occurred: [_1]',$putresult).'</span>';
19564: }
19565: if (@errors > 0) {
19566: $resulttext .= '<br />'.&mt('The following were left unchanged because the values entered were invalid:');
19567: foreach my $item (@errors) {
19568: $resulttext .= ' "'.$title->{$item}.'",';
19569: }
19570: $resulttext =~ s/,$//;
19571: }
19572: return $resulttext;
19573: }
19574:
1.46 raeburn 19575: sub modify_scantron {
1.205 raeburn 19576: my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
1.46 raeburn 19577: my ($resulttext,%confhash,%changes,$errors);
19578: my $custom = 'custom.tab';
19579: my $default = 'default.tab';
19580: my $servadm = $r->dir_config('lonAdmEMail');
1.346 raeburn 19581: my ($configuserok,$author_ok,$switchserver) =
1.46 raeburn 19582: &config_check($dom,$confname,$servadm);
19583: if ($env{'form.scantronformat.filename'} ne '') {
19584: my $error;
19585: if ($configuserok eq 'ok') {
19586: if ($switchserver) {
1.130 raeburn 19587: $error = &mt("Upload of bubblesheet format file is not permitted to this server: [_1]",$switchserver);
1.46 raeburn 19588: } else {
19589: if ($author_ok eq 'ok') {
1.421 raeburn 19590: my $modified = [];
1.46 raeburn 19591: my ($result,$scantronurl) =
1.421 raeburn 19592: &Apache::lonconfigsettings::publishlogo($r,'upload','scantronformat',$dom,
19593: $confname,'scantron','','',$custom,
19594: $modified);
1.46 raeburn 19595: if ($result eq 'ok') {
19596: $confhash{'scantron'}{'scantronformat'} = $scantronurl;
1.48 raeburn 19597: $changes{'scantronformat'} = 1;
1.421 raeburn 19598: &update_modify_urls($r,$modified);
1.46 raeburn 19599: } else {
19600: $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$custom,$result);
19601: }
19602: } else {
19603: $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$custom,$confname,$dom,$author_ok);
19604: }
19605: }
19606: } else {
19607: $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$custom,$confname,$dom,$configuserok);
19608: }
19609: if ($error) {
19610: &Apache::lonnet::logthis($error);
19611: $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
19612: }
19613: }
1.48 raeburn 19614: if (ref($domconfig{'scantron'}) eq 'HASH') {
19615: if ($domconfig{'scantron'}{'scantronformat'} ne '') {
19616: if ($env{'form.scantronformat_del'}) {
19617: $confhash{'scantron'}{'scantronformat'} = '';
19618: $changes{'scantronformat'} = 1;
1.347 raeburn 19619: } else {
19620: $confhash{'scantron'}{'scantronformat'} = $domconfig{'scantron'}{'scantronformat'};
1.46 raeburn 19621: }
19622: }
19623: }
1.347 raeburn 19624: my @options = ('hdr','pad','rem');
1.346 raeburn 19625: my @fields = &scantroncsv_fields();
19626: my %titles = &scantronconfig_titles();
1.347 raeburn 19627: my @formats = &Apache::loncommon::get_env_multiple('form.scantronconfig');
1.346 raeburn 19628: my ($newdat,$currdat,%newcol,%currcol);
19629: if (grep(/^dat$/,@formats)) {
19630: $confhash{'scantron'}{config}{dat} = 1;
19631: $newdat = 1;
19632: } else {
19633: $newdat = 0;
19634: }
19635: if (grep(/^csv$/,@formats)) {
19636: my %bynum;
19637: foreach my $field (@fields) {
19638: if ($env{'form.scantronconfig_csv_'.$field} =~ /^(\d+)$/) {
19639: my $posscol = $1;
19640: if (($posscol < 20) && (!$bynum{$posscol})) {
1.347 raeburn 19641: $confhash{'scantron'}{config}{csv}{fields}{$field} = $posscol;
1.346 raeburn 19642: $bynum{$posscol} = $field;
19643: $newcol{$field} = $posscol;
19644: }
19645: }
19646: }
1.347 raeburn 19647: if (keys(%newcol)) {
19648: foreach my $option (@options) {
19649: if ($env{'form.scantroncsv_'.$option}) {
19650: $confhash{'scantron'}{config}{csv}{options}{$option} = 1;
19651: }
19652: }
19653: }
1.346 raeburn 19654: }
19655: $currdat = 1;
19656: if (ref($domconfig{'scantron'}) eq 'HASH') {
19657: if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {
1.347 raeburn 19658: unless (exists($domconfig{'scantron'}{'config'}{'dat'})) {
1.346 raeburn 19659: $currdat = 0;
19660: }
19661: if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
1.347 raeburn 19662: if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
19663: %currcol = %{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}};
19664: }
1.346 raeburn 19665: }
19666: }
19667: }
19668: if ($currdat != $newdat) {
19669: $changes{'config'} = 1;
19670: } else {
19671: foreach my $field (@fields) {
19672: if ($currcol{$field} ne '') {
19673: if ($currcol{$field} ne $newcol{$field}) {
19674: $changes{'config'} = 1;
19675: last;
1.347 raeburn 19676: }
1.346 raeburn 19677: } elsif ($newcol{$field} ne '') {
19678: $changes{'config'} = 1;
19679: last;
19680: }
19681: }
19682: }
1.46 raeburn 19683: if (keys(%confhash) > 0) {
19684: my $putresult = &Apache::lonnet::put_dom('configuration',\%confhash,
19685: $dom);
19686: if ($putresult eq 'ok') {
19687: if (keys(%changes) > 0) {
1.48 raeburn 19688: if (ref($confhash{'scantron'}) eq 'HASH') {
19689: $resulttext = &mt('Changes made:').'<ul>';
1.346 raeburn 19690: if ($changes{'scantronformat'}) {
19691: if ($confhash{'scantron'}{'scantronformat'} eq '') {
19692: $resulttext .= '<li>'.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).'</li>';
19693: } else {
19694: $resulttext .= '<li>'.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).'</li>';
19695: }
19696: }
1.347 raeburn 19697: if ($changes{'config'}) {
1.346 raeburn 19698: if (ref($confhash{'scantron'}{'config'}) eq 'HASH') {
19699: if ($confhash{'scantron'}{'config'}{'dat'}) {
19700: $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .dat format').'</li>';
19701: }
19702: if (ref($confhash{'scantron'}{'config'}{'csv'}) eq 'HASH') {
1.347 raeburn 19703: if (ref($confhash{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
19704: if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'fields'}})) {
19705: $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .csv format, with following fields/column numbers supported:').'<ul>';
19706: foreach my $field (@fields) {
19707: if ($confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} ne '') {
19708: my $showcol = $confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} + 1;
19709: $resulttext .= '<li>'.$titles{$field}.': '.$showcol.'</li>';
19710: }
19711: }
19712: $resulttext .= '</ul></li>';
19713: if (ref($confhash{'scantron'}{'config'}{'csv'}{'options'}) eq 'HASH') {
19714: if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'options'}})) {
19715: $resulttext .= '<li>'.&mt('Bubblesheet data upload formats includes .csv format, with following options:').'<ul>';
19716: foreach my $option (@options) {
19717: if ($confhash{'scantron'}{'config'}{'csv'}{'options'}{$option} ne '') {
19718: $resulttext .= '<li>'.$titles{$option}.'</li>';
19719: }
19720: }
19721: $resulttext .= '</ul></li>';
19722: }
1.346 raeburn 19723: }
19724: }
19725: }
19726: }
19727: } else {
19728: $resulttext .= '<li>'.&mt('No bubblesheet data upload formats set -- will default to assuming .dat format').'</li>';
19729: }
1.46 raeburn 19730: }
1.48 raeburn 19731: $resulttext .= '</ul>';
19732: } else {
1.130 raeburn 19733: $resulttext = &mt('Changes made to bubblesheet format file.');
1.46 raeburn 19734: }
19735: &Apache::loncommon::devalidate_domconfig_cache($dom);
1.212 raeburn 19736: if (ref($lastactref) eq 'HASH') {
19737: $lastactref->{'domainconfig'} = 1;
19738: }
1.46 raeburn 19739: } else {
1.346 raeburn 19740: $resulttext = &mt('No changes made to bubblesheet format settings');
1.46 raeburn 19741: }
19742: } else {
19743: $resulttext = '<span class="LC_error">'.
19744: &mt('An error occurred: [_1]',$putresult).'</span>';
19745: }
19746: } else {
1.130 raeburn 19747: $resulttext = &mt('No changes made to bubblesheet format file');
1.46 raeburn 19748: }
19749: if ($errors) {
1.353 raeburn 19750: $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.
19751: $errors.'</ul></p>';
1.46 raeburn 19752: }
19753: return $resulttext;
19754: }
19755:
1.48 raeburn 19756: sub modify_coursecategories {
1.239 raeburn 19757: my ($dom,$lastactref,%domconfig) = @_;
1.57 raeburn 19758: my ($resulttext,%deletions,%reorderings,%needreordering,%adds,%changes,$errors,
19759: $cathash);
1.48 raeburn 19760: my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory');
1.238 raeburn 19761: my @catitems = ('unauth','auth');
19762: my @cattypes = ('std','domonly','codesrch','none');
1.55 raeburn 19763: if (ref($domconfig{'coursecategories'}) eq 'HASH') {
1.57 raeburn 19764: $cathash = $domconfig{'coursecategories'}{'cats'};
19765: if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) {
19766: $changes{'togglecats'} = 1;
19767: $domconfig{'coursecategories'}{'togglecats'} = $env{'form.togglecats'};
19768: }
19769: if ($domconfig{'coursecategories'}{'categorize'} ne $env{'form.categorize'}) {
19770: $changes{'categorize'} = 1;
19771: $domconfig{'coursecategories'}{'categorize'} = $env{'form.categorize'};
19772: }
1.120 raeburn 19773: if ($domconfig{'coursecategories'}{'togglecatscomm'} ne $env{'form.togglecatscomm'}) {
19774: $changes{'togglecatscomm'} = 1;
19775: $domconfig{'coursecategories'}{'togglecatscomm'} = $env{'form.togglecatscomm'};
19776: }
19777: if ($domconfig{'coursecategories'}{'categorizecomm'} ne $env{'form.categorizecomm'}) {
19778: $changes{'categorizecomm'} = 1;
19779: $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'};
1.272 raeburn 19780:
19781: }
19782: if ($domconfig{'coursecategories'}{'togglecatsplace'} ne $env{'form.togglecatsplace'}) {
19783: $changes{'togglecatsplace'} = 1;
19784: $domconfig{'coursecategories'}{'togglecatsplace'} = $env{'form.togglecatsplace'};
19785: }
19786: if ($domconfig{'coursecategories'}{'categorizeplace'} ne $env{'form.categorizeplace'}) {
19787: $changes{'categorizeplace'} = 1;
19788: $domconfig{'coursecategories'}{'categorizeplace'} = $env{'form.categorizeplace'};
1.120 raeburn 19789: }
1.238 raeburn 19790: foreach my $item (@catitems) {
19791: if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
19792: if ($domconfig{'coursecategories'}{$item} ne $env{'form.coursecat_'.$item}) {
19793: $changes{$item} = 1;
19794: $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};
19795: }
19796: }
19797: }
1.57 raeburn 19798: } else {
19799: $changes{'togglecats'} = 1;
19800: $changes{'categorize'} = 1;
1.124 raeburn 19801: $changes{'togglecatscomm'} = 1;
19802: $changes{'categorizecomm'} = 1;
1.272 raeburn 19803: $changes{'togglecatsplace'} = 1;
19804: $changes{'categorizeplace'} = 1;
1.87 raeburn 19805: $domconfig{'coursecategories'} = {
19806: togglecats => $env{'form.togglecats'},
19807: categorize => $env{'form.categorize'},
1.124 raeburn 19808: togglecatscomm => $env{'form.togglecatscomm'},
19809: categorizecomm => $env{'form.categorizecomm'},
1.272 raeburn 19810: togglecatsplace => $env{'form.togglecatsplace'},
19811: categorizeplace => $env{'form.categorizeplace'},
1.120 raeburn 19812: };
1.238 raeburn 19813: foreach my $item (@catitems) {
19814: if ($env{'form.coursecat_'.$item} ne 'std') {
19815: $changes{$item} = 1;
19816: }
19817: if (grep(/^\Q$env{'form.coursecat_'.$item}\E$/,@cattypes)) {
19818: $domconfig{'coursecategories'}{$item} = $env{'form.coursecat_'.$item};
19819: }
19820: }
1.57 raeburn 19821: }
19822: if (ref($cathash) eq 'HASH') {
19823: if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '') && ($env{'form.instcode'} == 0)) {
1.55 raeburn 19824: push (@deletecategory,'instcode::0');
19825: }
1.120 raeburn 19826: if (($domconfig{'coursecategories'}{'cats'}{'communities::0'} ne '') && ($env{'form.communities'} == 0)) {
19827: push(@deletecategory,'communities::0');
19828: }
1.272 raeburn 19829: if (($domconfig{'coursecategories'}{'cats'}{'placement::0'} ne '') && ($env{'form.placement'} == 0)) {
19830: push(@deletecategory,'placement::0');
19831: }
1.48 raeburn 19832: }
1.57 raeburn 19833: my (@predelcats,@predeltrails,%predelallitems,%sort_by_deltrail);
19834: if (ref($cathash) eq 'HASH') {
1.48 raeburn 19835: if (@deletecategory > 0) {
19836: #FIXME Need to remove category from all courses using a deleted category
1.57 raeburn 19837: &Apache::loncommon::extract_categories($cathash,\@predelcats,\@predeltrails,\%predelallitems);
1.48 raeburn 19838: foreach my $item (@deletecategory) {
1.57 raeburn 19839: if ($domconfig{'coursecategories'}{'cats'}{$item} ne '') {
19840: delete($domconfig{'coursecategories'}{'cats'}{$item});
1.48 raeburn 19841: $deletions{$item} = 1;
1.57 raeburn 19842: &recurse_cat_deletes($item,$cathash,\%deletions);
1.48 raeburn 19843: }
19844: }
19845: }
1.57 raeburn 19846: foreach my $item (keys(%{$cathash})) {
1.48 raeburn 19847: my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item);
1.57 raeburn 19848: if ($cathash->{$item} ne $env{'form.'.$item}) {
1.48 raeburn 19849: $reorderings{$item} = 1;
1.57 raeburn 19850: $domconfig{'coursecategories'}{'cats'}{$item} = $env{'form.'.$item};
1.48 raeburn 19851: }
19852: if ($env{'form.addcategory_name_'.$item} ne '') {
19853: my $newcat = $env{'form.addcategory_name_'.$item};
19854: my $newdepth = $depth+1;
19855: my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;
1.57 raeburn 19856: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos_'.$item};
1.48 raeburn 19857: $adds{$newitem} = 1;
19858: }
19859: if ($env{'form.subcat_'.$item} ne '') {
19860: my $newcat = $env{'form.subcat_'.$item};
19861: my $newdepth = $depth+1;
19862: my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth;
1.57 raeburn 19863: $domconfig{'coursecategories'}{'cats'}{$newitem} = 0;
1.48 raeburn 19864: $adds{$newitem} = 1;
19865: }
19866: }
19867: }
19868: if ($env{'form.instcode'} eq '1') {
1.57 raeburn 19869: if (ref($cathash) eq 'HASH') {
1.48 raeburn 19870: my $newitem = 'instcode::0';
1.57 raeburn 19871: if ($cathash->{$newitem} eq '') {
19872: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'};
1.48 raeburn 19873: $adds{$newitem} = 1;
19874: }
19875: } else {
19876: my $newitem = 'instcode::0';
1.57 raeburn 19877: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'};
1.48 raeburn 19878: $adds{$newitem} = 1;
19879: }
19880: }
1.120 raeburn 19881: if ($env{'form.communities'} eq '1') {
19882: if (ref($cathash) eq 'HASH') {
19883: my $newitem = 'communities::0';
19884: if ($cathash->{$newitem} eq '') {
19885: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'};
19886: $adds{$newitem} = 1;
19887: }
19888: } else {
19889: my $newitem = 'communities::0';
19890: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'};
19891: $adds{$newitem} = 1;
19892: }
19893: }
1.272 raeburn 19894: if ($env{'form.placement'} eq '1') {
19895: if (ref($cathash) eq 'HASH') {
19896: my $newitem = 'placement::0';
19897: if ($cathash->{$newitem} eq '') {
19898: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.placement_pos'};
19899: $adds{$newitem} = 1;
19900: }
19901: } else {
19902: my $newitem = 'placement::0';
19903: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.placement_pos'};
19904: $adds{$newitem} = 1;
19905: }
19906: }
1.48 raeburn 19907: if ($env{'form.addcategory_name'} ne '') {
1.120 raeburn 19908: if (($env{'form.addcategory_name'} ne 'instcode') &&
1.272 raeburn 19909: ($env{'form.addcategory_name'} ne 'communities') &&
19910: ($env{'form.addcategory_name'} ne 'placement')) {
1.120 raeburn 19911: my $newitem = &escape($env{'form.addcategory_name'}).'::0';
19912: $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos'};
19913: $adds{$newitem} = 1;
19914: }
1.48 raeburn 19915: }
1.57 raeburn 19916: my $putresult;
1.48 raeburn 19917: if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
19918: if (keys(%deletions) > 0) {
19919: foreach my $key (keys(%deletions)) {
19920: if ($predelallitems{$key} ne '') {
19921: $sort_by_deltrail{$predelallitems{$key}} = $predeltrails[$predelallitems{$key}];
19922: }
19923: }
19924: }
19925: my (@chkcats,@chktrails,%chkallitems);
1.57 raeburn 19926: &Apache::loncommon::extract_categories($domconfig{'coursecategories'}{'cats'},\@chkcats,\@chktrails,\%chkallitems);
1.48 raeburn 19927: if (ref($chkcats[0]) eq 'ARRAY') {
19928: my $depth = 0;
19929: my $chg = 0;
19930: for (my $i=0; $i<@{$chkcats[0]}; $i++) {
19931: my $name = $chkcats[0][$i];
19932: my $item;
19933: if ($name eq '') {
19934: $chg ++;
19935: } else {
19936: $item = &escape($name).'::0';
19937: if ($chg) {
1.57 raeburn 19938: $domconfig{'coursecategories'}{'cats'}{$item} -= $chg;
1.48 raeburn 19939: }
19940: $depth ++;
1.57 raeburn 19941: &recurse_check(\@chkcats,$domconfig{'coursecategories'}{'cats'},$depth,$name);
1.48 raeburn 19942: $depth --;
19943: }
19944: }
19945: }
1.57 raeburn 19946: }
19947: if ((keys(%changes) > 0) || (keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
19948: $putresult = &Apache::lonnet::put_dom('configuration',\%domconfig,$dom);
1.48 raeburn 19949: if ($putresult eq 'ok') {
1.57 raeburn 19950: my %title = (
1.120 raeburn 19951: togglecats => 'Show/Hide a course in catalog',
19952: categorize => 'Assign a category to a course',
19953: togglecatscomm => 'Show/Hide a community in catalog',
19954: categorizecomm => 'Assign a category to a community',
1.57 raeburn 19955: );
19956: my %level = (
1.120 raeburn 19957: dom => 'set in Domain ("Modify Course/Community")',
19958: crs => 'set in Course ("Course Configuration")',
19959: comm => 'set in Community ("Community Configuration")',
1.238 raeburn 19960: none => 'No catalog',
19961: std => 'Standard catalog',
19962: domonly => 'Domain-only catalog',
19963: codesrch => 'Code search form',
1.57 raeburn 19964: );
1.48 raeburn 19965: $resulttext = &mt('Changes made:').'<ul>';
1.57 raeburn 19966: if ($changes{'togglecats'}) {
19967: $resulttext .= '<li>'.&mt("$title{'togglecats'} $level{$env{'form.togglecats'}}").'</li>';
19968: }
19969: if ($changes{'categorize'}) {
19970: $resulttext .= '<li>'.&mt("$title{'categorize'} $level{$env{'form.categorize'}}").'</li>';
1.48 raeburn 19971: }
1.120 raeburn 19972: if ($changes{'togglecatscomm'}) {
19973: $resulttext .= '<li>'.&mt("$title{'togglecatscomm'} $level{$env{'form.togglecatscomm'}}").'</li>';
19974: }
19975: if ($changes{'categorizecomm'}) {
19976: $resulttext .= '<li>'.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'</li>';
19977: }
1.238 raeburn 19978: if ($changes{'unauth'}) {
19979: $resulttext .= '<li>'.&mt('Catalog type for unauthenticated users set to "'.$level{$env{'form.coursecat_unauth'}}.'"').'</li>';
19980: }
19981: if ($changes{'auth'}) {
19982: $resulttext .= '<li>'.&mt('Catalog type for authenticated users set to "'.$level{$env{'form.coursecat_auth'}}.'"').'</li>';
19983: }
1.57 raeburn 19984: if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) {
19985: my $cathash;
19986: if (ref($domconfig{'coursecategories'}) eq 'HASH') {
19987: $cathash = $domconfig{'coursecategories'}{'cats'};
19988: } else {
19989: $cathash = {};
19990: }
19991: my (@cats,@trails,%allitems);
19992: &Apache::loncommon::extract_categories($cathash,\@cats,\@trails,\%allitems);
19993: if (keys(%deletions) > 0) {
19994: $resulttext .= '<li>'.&mt('Deleted categories:').'<ul>';
19995: foreach my $predeltrail (sort {$a <=> $b } (keys(%sort_by_deltrail))) {
19996: $resulttext .= '<li>'.$predeltrails[$predeltrail].'</li>';
19997: }
19998: $resulttext .= '</ul></li>';
19999: }
20000: if (keys(%reorderings) > 0) {
20001: my %sort_by_trail;
20002: $resulttext .= '<li>'.&mt('Reordered categories:').'<ul>';
20003: foreach my $key (keys(%reorderings)) {
20004: if ($allitems{$key} ne '') {
20005: $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];
20006: }
1.48 raeburn 20007: }
1.57 raeburn 20008: foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {
20009: $resulttext .= '<li>'.$trails[$trail].'</li>';
20010: }
20011: $resulttext .= '</ul></li>';
1.48 raeburn 20012: }
1.57 raeburn 20013: if (keys(%adds) > 0) {
20014: my %sort_by_trail;
20015: $resulttext .= '<li>'.&mt('Added categories:').'<ul>';
20016: foreach my $key (keys(%adds)) {
20017: if ($allitems{$key} ne '') {
20018: $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}];
20019: }
20020: }
20021: foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) {
20022: $resulttext .= '<li>'.$trails[$trail].'</li>';
1.48 raeburn 20023: }
1.57 raeburn 20024: $resulttext .= '</ul></li>';
1.48 raeburn 20025: }
1.364 raeburn 20026: &Apache::lonnet::do_cache_new('cats',$dom,$cathash,3600);
20027: if (ref($lastactref) eq 'HASH') {
20028: $lastactref->{'cats'} = 1;
20029: }
1.48 raeburn 20030: }
20031: $resulttext .= '</ul>';
1.239 raeburn 20032: if ($changes{'unauth'} || $changes{'auth'}) {
1.246 raeburn 20033: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
20034: if ($changes{'auth'}) {
20035: $domdefaults{'catauth'} = $domconfig{'coursecategories'}{'auth'};
20036: }
20037: if ($changes{'unauth'}) {
20038: $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};
20039: }
20040: my $cachetime = 24*60*60;
20041: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
1.239 raeburn 20042: if (ref($lastactref) eq 'HASH') {
1.246 raeburn 20043: $lastactref->{'domdefaults'} = 1;
1.239 raeburn 20044: }
20045: }
1.48 raeburn 20046: } else {
20047: $resulttext = '<span class="LC_error">'.
1.57 raeburn 20048: &mt('An error occurred: [_1]',$putresult).'</span>';
1.48 raeburn 20049: }
20050: } else {
1.120 raeburn 20051: $resulttext = &mt('No changes made to course and community categories');
1.48 raeburn 20052: }
20053: return $resulttext;
20054: }
20055:
1.69 raeburn 20056: sub modify_serverstatuses {
20057: my ($dom,%domconfig) = @_;
20058: my ($resulttext,%changes,%currserverstatus,%newserverstatus);
20059: if (ref($domconfig{'serverstatuses'}) eq 'HASH') {
20060: %currserverstatus = %{$domconfig{'serverstatuses'}};
20061: }
20062: my @pages = &serverstatus_pages();
20063: foreach my $type (@pages) {
20064: $newserverstatus{$type}{'namedusers'} = '';
20065: $newserverstatus{$type}{'machines'} = '';
20066: if (defined($env{'form.'.$type.'_namedusers'})) {
20067: my @users = split(/,/,$env{'form.'.$type.'_namedusers'});
20068: my @okusers;
20069: foreach my $user (@users) {
20070: my ($uname,$udom) = split(/:/,$user);
20071: if (($udom =~ /^$match_domain$/) &&
20072: (&Apache::lonnet::domain($udom)) &&
20073: ($uname =~ /^$match_username$/)) {
20074: if (!grep(/^\Q$user\E/,@okusers)) {
20075: push(@okusers,$user);
20076: }
20077: }
20078: }
20079: if (@okusers > 0) {
20080: @okusers = sort(@okusers);
20081: $newserverstatus{$type}{'namedusers'} = join(',',@okusers);
20082: }
20083: }
20084: if (defined($env{'form.'.$type.'_machines'})) {
20085: my @machines = split(/,/,$env{'form.'.$type.'_machines'});
20086: my @okmachines;
20087: foreach my $ip (@machines) {
20088: my @parts = split(/\./,$ip);
20089: next if (@parts < 4);
20090: my $badip = 0;
20091: for (my $i=0; $i<4; $i++) {
20092: if (!(($parts[$i] >= 0) && ($parts[$i] <= 255))) {
20093: $badip = 1;
20094: last;
20095: }
20096: }
20097: if (!$badip) {
20098: push(@okmachines,$ip);
20099: }
20100: }
20101: @okmachines = sort(@okmachines);
20102: $newserverstatus{$type}{'machines'} = join(',',@okmachines);
20103: }
20104: }
20105: my %serverstatushash = (
20106: serverstatuses => \%newserverstatus,
20107: );
20108: foreach my $type (@pages) {
1.83 raeburn 20109: foreach my $setting ('namedusers','machines') {
1.84 raeburn 20110: my (@current,@new);
1.83 raeburn 20111: if (ref($currserverstatus{$type}) eq 'HASH') {
1.84 raeburn 20112: if ($currserverstatus{$type}{$setting} ne '') {
20113: @current = split(/,/,$currserverstatus{$type}{$setting});
20114: }
20115: }
20116: if ($newserverstatus{$type}{$setting} ne '') {
20117: @new = split(/,/,$newserverstatus{$type}{$setting});
1.83 raeburn 20118: }
20119: if (@current > 0) {
20120: if (@new > 0) {
20121: foreach my $item (@current) {
20122: if (!grep(/^\Q$item\E$/,@new)) {
20123: $changes{$type}{$setting} = 1;
1.82 raeburn 20124: last;
20125: }
20126: }
1.84 raeburn 20127: foreach my $item (@new) {
20128: if (!grep(/^\Q$item\E$/,@current)) {
20129: $changes{$type}{$setting} = 1;
20130: last;
1.82 raeburn 20131: }
20132: }
20133: } else {
1.83 raeburn 20134: $changes{$type}{$setting} = 1;
1.69 raeburn 20135: }
1.83 raeburn 20136: } elsif (@new > 0) {
20137: $changes{$type}{$setting} = 1;
1.69 raeburn 20138: }
20139: }
20140: }
20141: if (keys(%changes) > 0) {
1.81 raeburn 20142: my $titles= &LONCAPA::lonauthcgi::serverstatus_titles();
1.69 raeburn 20143: my $putresult = &Apache::lonnet::put_dom('configuration',
20144: \%serverstatushash,$dom);
20145: if ($putresult eq 'ok') {
20146: $resulttext .= &mt('Changes made:').'<ul>';
20147: foreach my $type (@pages) {
1.84 raeburn 20148: if (ref($changes{$type}) eq 'HASH') {
1.69 raeburn 20149: $resulttext .= '<li>'.$titles->{$type}.'<ul>';
1.84 raeburn 20150: if ($changes{$type}{'namedusers'}) {
1.69 raeburn 20151: if ($newserverstatus{$type}{'namedusers'} eq '') {
20152: $resulttext .= '<li>'.&mt("Access terminated for all specific (named) users").'</li>'."\n";
20153: } else {
20154: $resulttext .= '<li>'.&mt("Access available for the following specified users: ").$newserverstatus{$type}{'namedusers'}.'</li>'."\n";
20155: }
1.84 raeburn 20156: }
20157: if ($changes{$type}{'machines'}) {
1.69 raeburn 20158: if ($newserverstatus{$type}{'machines'} eq '') {
20159: $resulttext .= '<li>'.&mt("Access terminated for all specific IP addresses").'</li>'."\n";
20160: } else {
20161: $resulttext .= '<li>'.&mt("Access available for the following specified IP addresses: ").$newserverstatus{$type}{'machines'}.'</li>'."\n";
20162: }
20163:
20164: }
20165: $resulttext .= '</ul></li>';
20166: }
20167: }
20168: $resulttext .= '</ul>';
20169: } else {
20170: $resulttext = '<span class="LC_error">'.
20171: &mt('An error occurred saving access settings for server status pages: [_1].',$putresult).'</span>';
20172:
20173: }
20174: } else {
20175: $resulttext = &mt('No changes made to access to server status pages');
20176: }
20177: return $resulttext;
20178: }
20179:
1.118 jms 20180: sub modify_helpsettings {
1.285 raeburn 20181: my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
1.166 raeburn 20182: my ($resulttext,$errors,%changes,%helphash);
20183: my %defaultchecked = ('submitbugs' => 'on');
20184: my @offon = ('off','on');
1.118 jms 20185: my @toggles = ('submitbugs');
1.285 raeburn 20186: my %current = ('submitbugs' => '',
20187: 'adhoc' => {},
20188: );
1.118 jms 20189: if (ref($domconfig{'helpsettings'}) eq 'HASH') {
1.282 raeburn 20190: %current = %{$domconfig{'helpsettings'}};
20191: }
1.285 raeburn 20192: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
1.282 raeburn 20193: foreach my $item (@toggles) {
20194: if ($defaultchecked{$item} eq 'on') {
20195: if ($current{$item} eq '') {
20196: if ($env{'form.'.$item} eq '0') {
20197: $changes{$item} = 1;
20198: }
20199: } elsif ($current{$item} ne $env{'form.'.$item}) {
20200: $changes{$item} = 1;
20201: }
20202: } elsif ($defaultchecked{$item} eq 'off') {
20203: if ($current{$item} eq '') {
20204: if ($env{'form.'.$item} eq '1') {
1.166 raeburn 20205: $changes{$item} = 1;
20206: }
1.282 raeburn 20207: } elsif ($current{$item} ne $env{'form.'.$item}) {
20208: $changes{$item} = 1;
20209: }
20210: }
20211: if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) {
20212: $helphash{'helpsettings'}{$item} = $env{'form.'.$item};
20213: }
20214: }
1.285 raeburn 20215: my $maxnum = $env{'form.helproles_maxnum'};
1.282 raeburn 20216: my $confname = $dom.'-domainconfig';
20217: my %existing=&Apache::lonnet::dump('roles',$dom,$confname,'rolesdef_');
1.285 raeburn 20218: my (@allpos,%newsettings,%changedprivs,$newrole);
20219: my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
1.292 raeburn 20220: my @accesstypes = ('all','dh','da','none','status','inc','exc');
1.290 raeburn 20221: my %domhelpdesk = &Apache::lonnet::get_active_domroles($dom,['dh','da']);
1.285 raeburn 20222: my %lt = &Apache::lonlocal::texthash(
20223: s => 'system',
20224: d => 'domain',
20225: order => 'Display order',
20226: access => 'Role usage',
1.291 raeburn 20227: all => 'All with domain helpdesk or helpdesk assistant role',
1.292 raeburn 20228: dh => 'All with domain helpdesk role',
20229: da => 'All with domain helpdesk assistant role',
1.285 raeburn 20230: none => 'None',
20231: status => 'Determined based on institutional status',
20232: inc => 'Include all, but exclude specific personnel',
20233: exc => 'Exclude all, but include specific personnel',
20234: );
20235: for (my $num=0; $num<=$maxnum; $num++) {
20236: my ($prefix,$identifier,$rolename,%curr);
20237: if ($num == $maxnum) {
20238: next unless ($env{'form.newcusthelp'} == $maxnum);
20239: $identifier = 'custhelp'.$num;
20240: $prefix = 'helproles_'.$num;
20241: $rolename = $env{'form.custhelpname'.$num};
20242: $rolename=~s/[^A-Za-z0-9]//gs;
20243: next if ($rolename eq '');
20244: next if (exists($existing{'rolesdef_'.$rolename}));
20245: my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);
20246: my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
20247: $newprivs{'c'},$confname,$dom);
20248: if ($result ne 'ok') {
20249: $errors .= '<li><span class="LC_error">'.
20250: &mt('An error occurred storing the new custom role: [_1]',
20251: $result).'</span></li>';
20252: next;
20253: } else {
20254: $changedprivs{$rolename} = \%newprivs;
20255: $newrole = $rolename;
20256: }
20257: } else {
20258: $prefix = 'helproles_'.$num;
20259: $rolename = $env{'form.'.$prefix};
20260: next if ($rolename eq '');
20261: next unless (exists($existing{'rolesdef_'.$rolename}));
20262: $identifier = 'custhelp'.$num;
20263: my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$identifier);
20264: my %currprivs;
1.289 raeburn 20265: ($currprivs{'s'},$currprivs{'d'},$currprivs{'c'}) =
1.285 raeburn 20266: split(/\_/,$existing{'rolesdef_'.$rolename});
20267: foreach my $level ('c','d','s') {
20268: if ($newprivs{$level} ne $currprivs{$level}) {
20269: my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
20270: $newprivs{'c'},$confname,$dom);
20271: if ($result ne 'ok') {
20272: $errors .= '<li><span class="LC_error">'.
20273: &mt('An error occurred storing privileges for existing role [_1]: [_2]',
20274: $rolename,$result).'</span></li>';
20275: } else {
20276: $changedprivs{$rolename} = \%newprivs;
20277: }
20278: last;
20279: }
20280: }
20281: if (ref($current{'adhoc'}) eq 'HASH') {
20282: if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {
20283: %curr = %{$current{'adhoc'}{$rolename}};
20284: }
20285: }
20286: }
20287: my $newpos = $env{'form.'.$prefix.'_pos'};
20288: $newpos =~ s/\D+//g;
20289: $allpos[$newpos] = $rolename;
20290: my $newdesc = $env{'form.'.$prefix.'_desc'};
20291: $helphash{'helpsettings'}{'adhoc'}{$rolename}{'desc'} = $newdesc;
20292: if ($curr{'desc'}) {
20293: if ($curr{'desc'} ne $newdesc) {
20294: $changes{'customrole'}{$rolename}{'desc'} = 1;
20295: $newsettings{$rolename}{'desc'} = $newdesc;
20296: }
20297: } elsif ($newdesc ne '') {
20298: $changes{'customrole'}{$rolename}{'desc'} = 1;
20299: $newsettings{$rolename}{'desc'} = $newdesc;
20300: }
20301: my $access = $env{'form.'.$prefix.'_access'};
20302: if (grep(/^\Q$access\E$/,@accesstypes)) {
20303: $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = $access;
20304: if ($access eq 'status') {
20305: my @statuses = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_status');
20306: if (scalar(@statuses) == 0) {
1.289 raeburn 20307: $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'none';
1.285 raeburn 20308: } else {
20309: my (@shownstatus,$numtypes);
20310: $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];
20311: if (ref($types) eq 'ARRAY') {
20312: $numtypes = scalar(@{$types});
20313: foreach my $type (sort(@statuses)) {
20314: if ($type eq 'default') {
20315: push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);
20316: } elsif (grep(/^\Q$type\E$/,@{$types})) {
20317: push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$type);
20318: push(@shownstatus,$usertypes->{$type});
20319: }
20320: }
20321: }
20322: if (grep(/^default$/,@statuses)) {
20323: push(@shownstatus,$othertitle);
20324: }
20325: if (scalar(@shownstatus) == 1+$numtypes) {
20326: $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'} = 'all';
20327: delete($helphash{'helpsettings'}{'adhoc'}{$rolename}{'status'});
20328: } else {
20329: $newsettings{$rolename}{'status'} = join(' '.&mt('or').' ',@shownstatus);
20330: if (ref($curr{'status'}) eq 'ARRAY') {
20331: my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});
20332: if (@diffs) {
20333: $changes{'customrole'}{$rolename}{$access} = 1;
20334: }
20335: } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
20336: $changes{'customrole'}{$rolename}{$access} = 1;
1.282 raeburn 20337: }
1.166 raeburn 20338: }
20339: }
1.285 raeburn 20340: } elsif (($access eq 'inc') || ($access eq 'exc')) {
20341: my @personnel = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_staff_'.$access);
20342: my @newspecstaff;
20343: $helphash{'helpsettings'}{'adhoc'}{$rolename}{$access} = [];
20344: foreach my $person (sort(@personnel)) {
20345: if ($domhelpdesk{$person}) {
20346: push(@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}},$person);
20347: }
20348: }
20349: if (ref($curr{$access}) eq 'ARRAY') {
20350: my @diffs = &Apache::loncommon::compare_arrays($helphash{'helpsettings'}{'adhoc'}{$rolename}{$access},$curr{$access});
20351: if (@diffs) {
20352: $changes{'customrole'}{$rolename}{$access} = 1;
20353: }
20354: } elsif (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
20355: $changes{'customrole'}{$rolename}{$access} = 1;
20356: }
20357: foreach my $person (@{$helphash{'helpsettings'}{'adhoc'}{$rolename}{$access}}) {
20358: my ($uname,$udom) = split(/:/,$person);
20359: push(@newspecstaff,&Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom,'lastname'),$uname,$udom));
20360: }
20361: $newsettings{$rolename}{$access} = join(', ',sort(@newspecstaff));
1.166 raeburn 20362: }
1.285 raeburn 20363: } else {
20364: $helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}= 'all';
20365: }
20366: unless ($curr{'access'} eq $access) {
20367: $changes{'customrole'}{$rolename}{'access'} = 1;
20368: $newsettings{$rolename}{'access'} = $lt{$helphash{'helpsettings'}{'adhoc'}{$rolename}{'access'}};
1.282 raeburn 20369: }
20370: }
1.285 raeburn 20371: if (@allpos > 0) {
20372: my $idx = 0;
20373: foreach my $rolename (@allpos) {
20374: if ($rolename ne '') {
20375: $helphash{'helpsettings'}{'adhoc'}{$rolename}{'order'} = $idx;
20376: if (ref($current{'adhoc'}) eq 'HASH') {
20377: if (ref($current{'adhoc'}{$rolename}) eq 'HASH') {
20378: if ($current{'adhoc'}{$rolename}{'order'} ne $idx) {
20379: $changes{'customrole'}{$rolename}{'order'} = 1;
1.289 raeburn 20380: $newsettings{$rolename}{'order'} = $idx+1;
1.285 raeburn 20381: }
20382: }
1.282 raeburn 20383: }
1.285 raeburn 20384: $idx ++;
1.166 raeburn 20385: }
20386: }
1.118 jms 20387: }
1.123 jms 20388: my $putresult;
20389: if (keys(%changes) > 0) {
1.166 raeburn 20390: $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom);
1.168 raeburn 20391: if ($putresult eq 'ok') {
1.285 raeburn 20392: if (ref($helphash{'helpsettings'}) eq 'HASH') {
20393: $domdefaults{'submitbugs'} = $helphash{'helpsettings'}{'submitbugs'};
20394: if (ref($helphash{'helpsettings'}{'adhoc'}) eq 'HASH') {
20395: $domdefaults{'adhocroles'} = $helphash{'helpsettings'}{'adhoc'};
20396: }
20397: }
20398: my $cachetime = 24*60*60;
20399: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
20400: if (ref($lastactref) eq 'HASH') {
20401: $lastactref->{'domdefaults'} = 1;
20402: }
20403: } else {
20404: $errors .= '<li><span class="LC_error">'.
20405: &mt('An error occurred storing the settings: [_1]',
20406: $putresult).'</span></li>';
20407: }
20408: }
20409: if ((keys(%changes) && ($putresult eq 'ok')) || (keys(%changedprivs))) {
20410: $resulttext = &mt('Changes made:').'<ul>';
20411: my (%shownprivs,@levelorder);
20412: @levelorder = ('c','d','s');
20413: if ((keys(%changes)) && ($putresult eq 'ok')) {
1.166 raeburn 20414: foreach my $item (sort(keys(%changes))) {
20415: if ($item eq 'submitbugs') {
20416: $resulttext .= '<li>'.&mt('Display link to: [_1] set to "'.$offon[$env{'form.'.$item}].'".',
20417: &Apache::loncommon::modal_link('http://bugs.loncapa.org',
20418: &mt('LON-CAPA bug tracker'),600,500)).'</li>';
1.282 raeburn 20419: } elsif ($item eq 'customrole') {
20420: if (ref($changes{'customrole'}) eq 'HASH') {
1.285 raeburn 20421: my @keyorder = ('order','desc','access','status','exc','inc');
20422: my %keytext = &Apache::lonlocal::texthash(
20423: order => 'Order',
20424: desc => 'Role description',
20425: access => 'Role usage',
1.300 droeschl 20426: status => 'Allowed institutional types',
1.285 raeburn 20427: exc => 'Allowed personnel',
20428: inc => 'Disallowed personnel',
20429: );
1.282 raeburn 20430: foreach my $role (sort(keys(%{$changes{'customrole'}}))) {
1.285 raeburn 20431: if (ref($changes{'customrole'}{$role}) eq 'HASH') {
20432: if ($role eq $newrole) {
20433: $resulttext .= '<li>'.&mt('New custom role added: [_1]',
20434: $role).'<ul>';
20435: } else {
20436: $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',
20437: $role).'<ul>';
20438: }
20439: foreach my $key (@keyorder) {
20440: if ($changes{'customrole'}{$role}{$key}) {
20441: $resulttext .= '<li>'.&mt("[_1] set to: [_2]",
20442: $keytext{$key},$newsettings{$role}{$key}).
20443: '</li>';
20444: }
20445: }
20446: if (ref($changedprivs{$role}) eq 'HASH') {
20447: $shownprivs{$role} = 1;
20448: $resulttext .= '<li>'.&mt('Privileges set to :').'<ul>';
20449: foreach my $level (@levelorder) {
20450: foreach my $item (split(/\:/,$changedprivs{$role}{$level})) {
20451: next if ($item eq '');
20452: my ($priv) = split(/\&/,$item,2);
20453: if (&Apache::lonnet::plaintext($priv)) {
20454: $resulttext .= '<li>'.&Apache::lonnet::plaintext($priv);
20455: unless ($level eq 'c') {
20456: $resulttext .= ' ('.$lt{$level}.')';
20457: }
20458: $resulttext .= '</li>';
20459: }
20460: }
20461: }
20462: $resulttext .= '</ul>';
20463: }
20464: $resulttext .= '</ul></li>';
20465: }
20466: }
20467: }
20468: }
20469: }
20470: }
20471: if (keys(%changedprivs)) {
20472: foreach my $role (sort(keys(%changedprivs))) {
20473: unless ($shownprivs{$role}) {
20474: $resulttext .= '<li>'.&mt('Existing custom role modified: [_1]',
20475: $role).'<ul>'.
20476: '<li>'.&mt('Privileges set to :').'<ul>';
20477: foreach my $level (@levelorder) {
20478: foreach my $item (split(/\:/,$changedprivs{$role}{$level})) {
20479: next if ($item eq '');
20480: my ($priv) = split(/\&/,$item,2);
20481: if (&Apache::lonnet::plaintext($priv)) {
20482: $resulttext .= '<li>'.&Apache::lonnet::plaintext($priv);
20483: unless ($level eq 'c') {
20484: $resulttext .= ' ('.$lt{$level}.')';
20485: }
20486: $resulttext .= '</li>';
20487: }
1.282 raeburn 20488: }
20489: }
1.285 raeburn 20490: $resulttext .= '</ul></li></ul></li>';
1.166 raeburn 20491: }
20492: }
20493: }
1.285 raeburn 20494: $resulttext .= '</ul>';
20495: } else {
20496: $resulttext = &mt('No changes made to help settings');
1.118 jms 20497: }
20498: if ($errors) {
1.168 raeburn 20499: $resulttext .= '<br />'.&mt('The following errors occurred: ').'<ul>'.
1.285 raeburn 20500: $errors.'</ul>';
1.118 jms 20501: }
20502: return $resulttext;
20503: }
20504:
1.121 raeburn 20505: sub modify_coursedefaults {
1.212 raeburn 20506: my ($dom,$lastactref,%domconfig) = @_;
1.121 raeburn 20507: my ($resulttext,$errors,%changes,%defaultshash);
1.257 raeburn 20508: my %defaultchecked = (
20509: 'canuse_pdfforms' => 'off',
20510: 'uselcmath' => 'on',
1.398 raeburn 20511: 'usejsme' => 'on',
20512: 'inline_chem' => 'on',
1.404 raeburn 20513: 'ltiauth' => 'off',
1.257 raeburn 20514: );
1.404 raeburn 20515: my @toggles = ('canuse_pdfforms','uselcmath','usejsme','inline_chem','ltiauth');
1.198 raeburn 20516: my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial',
1.276 raeburn 20517: 'uploadquota_community','uploadquota_textbook','uploadquota_placement',
1.428 ! raeburn 20518: 'coursequota_official','coursequota_unofficial','coursequota_community',
! 20519: 'coursequota_textbook','coursequota_placement','mysqltables_official',
! 20520: 'mysqltables_unofficial','mysqltables_community','mysqltables_textbook',
! 20521: 'mysqltables_placement');
1.271 raeburn 20522: my @types = ('official','unofficial','community','textbook','placement');
1.198 raeburn 20523: my %staticdefaults = (
20524: anonsurvey_threshold => 10,
20525: uploadquota => 500,
1.428 ! raeburn 20526: coursequota => 20,
1.257 raeburn 20527: postsubmit => 60,
1.276 raeburn 20528: mysqltables => 172800,
1.422 raeburn 20529: domexttool => 1,
1.198 raeburn 20530: );
1.314 raeburn 20531: my %texoptions = (
20532: MathJax => 'MathJax',
20533: mimetex => &mt('Convert to Images'),
20534: tth => &mt('TeX to HTML'),
20535: );
1.121 raeburn 20536: $defaultshash{'coursedefaults'} = {};
20537:
20538: if (ref($domconfig{'coursedefaults'}) ne 'HASH') {
20539: if ($domconfig{'coursedefaults'} eq '') {
20540: $domconfig{'coursedefaults'} = {};
20541: }
20542: }
20543:
20544: if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
20545: foreach my $item (@toggles) {
20546: if ($defaultchecked{$item} eq 'on') {
20547: if (($domconfig{'coursedefaults'}{$item} eq '') &&
20548: ($env{'form.'.$item} eq '0')) {
20549: $changes{$item} = 1;
1.192 raeburn 20550: } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {
1.121 raeburn 20551: $changes{$item} = 1;
20552: }
20553: } elsif ($defaultchecked{$item} eq 'off') {
20554: if (($domconfig{'coursedefaults'}{$item} eq '') &&
20555: ($env{'form.'.$item} eq '1')) {
20556: $changes{$item} = 1;
20557: } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) {
20558: $changes{$item} = 1;
20559: }
20560: }
20561: $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item};
20562: }
1.198 raeburn 20563: foreach my $item (@numbers) {
20564: my ($currdef,$newdef);
1.208 raeburn 20565: $newdef = $env{'form.'.$item};
1.198 raeburn 20566: if ($item eq 'anonsurvey_threshold') {
20567: $currdef = $domconfig{'coursedefaults'}{$item};
20568: $newdef =~ s/\D//g;
20569: if ($newdef eq '' || $newdef < 1) {
20570: $newdef = 1;
20571: }
20572: $defaultshash{'coursedefaults'}{$item} = $newdef;
20573: } else {
1.428 ! raeburn 20574: my ($setting,$type) = ($item =~ /^(uploadquota|coursequota|mysqltables)_(\w+)$/);
1.276 raeburn 20575: if (ref($domconfig{'coursedefaults'}{$setting}) eq 'HASH') {
20576: $currdef = $domconfig{'coursedefaults'}{$setting}{$type};
1.198 raeburn 20577: }
20578: $newdef =~ s/[^\w.\-]//g;
1.276 raeburn 20579: $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;
1.198 raeburn 20580: }
20581: if ($currdef ne $newdef) {
20582: if ($item eq 'anonsurvey_threshold') {
20583: unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
20584: $changes{$item} = 1;
20585: }
1.428 ! raeburn 20586: } elsif ($item =~ /^(uploadquota|coursequota|mysqltables)_/) {
1.289 raeburn 20587: my $setting = $1;
1.276 raeburn 20588: unless (($currdef eq '') && ($newdef == $staticdefaults{$setting})) {
20589: $changes{$setting} = 1;
1.198 raeburn 20590: }
20591: }
1.139 raeburn 20592: }
20593: }
1.314 raeburn 20594: my $texengine;
20595: if ($env{'form.texengine'} =~ /^(MathJax|mimetex|tth)$/) {
20596: $texengine = $env{'form.texengine'};
1.349 raeburn 20597: my $currdef = $domconfig{'coursedefaults'}{'texengine'};
20598: if ($currdef eq '') {
20599: unless ($texengine eq $Apache::lonnet::deftex) {
1.314 raeburn 20600: $changes{'texengine'} = 1;
20601: }
1.349 raeburn 20602: } elsif ($currdef ne $texengine) {
1.314 raeburn 20603: $changes{'texengine'} = 1;
20604: }
20605: }
20606: if ($texengine ne '') {
20607: $defaultshash{'coursedefaults'}{'texengine'} = $texengine;
20608: }
1.264 raeburn 20609: my $currclone = $domconfig{'coursedefaults'}{'canclone'};
20610: my @currclonecode;
20611: if (ref($currclone) eq 'HASH') {
20612: if (ref($currclone->{'instcode'}) eq 'ARRAY') {
20613: @currclonecode = @{$currclone->{'instcode'}};
20614: }
20615: }
20616: my $newclone;
1.289 raeburn 20617: if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) {
1.264 raeburn 20618: $newclone = $env{'form.canclone'};
20619: }
20620: if ($newclone eq 'instcode') {
20621: my @newcodes = &Apache::loncommon::get_env_multiple('form.clonecode');
20622: my (%codedefaults,@code_order,@clonecode);
20623: &Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults,
20624: \@code_order);
20625: foreach my $item (@code_order) {
20626: if (grep(/^\Q$item\E$/,@newcodes)) {
20627: push(@clonecode,$item);
20628: }
20629: }
20630: if (@clonecode) {
20631: $defaultshash{'coursedefaults'}{'canclone'} = { $newclone => \@clonecode };
20632: my @diffs = &Apache::loncommon::compare_arrays(\@currclonecode,\@clonecode);
20633: if (@diffs) {
20634: $changes{'canclone'} = 1;
20635: }
20636: } else {
20637: $newclone eq '';
20638: }
20639: } elsif ($newclone ne '') {
1.289 raeburn 20640: $defaultshash{'coursedefaults'}{'canclone'} = $newclone;
20641: }
1.264 raeburn 20642: if ($newclone ne $currclone) {
20643: $changes{'canclone'} = 1;
20644: }
1.257 raeburn 20645: my %credits;
20646: foreach my $type (@types) {
20647: unless ($type eq 'community') {
20648: $credits{$type} = $env{'form.'.$type.'_credits'};
20649: $credits{$type} =~ s/[^\d.]+//g;
20650: }
20651: }
20652: if ((ref($domconfig{'coursedefaults'}{'coursecredits'}) ne 'HASH') &&
20653: ($env{'form.coursecredits'} eq '1')) {
20654: $changes{'coursecredits'} = 1;
20655: foreach my $type (keys(%credits)) {
20656: $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
20657: }
20658: } else {
1.289 raeburn 20659: if ($env{'form.coursecredits'} eq '1') {
1.257 raeburn 20660: foreach my $type (@types) {
20661: unless ($type eq 'community') {
1.289 raeburn 20662: if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) {
1.257 raeburn 20663: $changes{'coursecredits'} = 1;
20664: }
20665: $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type};
20666: }
20667: }
20668: } elsif (ref($domconfig{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
20669: foreach my $type (@types) {
20670: unless ($type eq 'community') {
20671: if ($domconfig{'coursedefaults'}{'coursecredits'}{$type}) {
20672: $changes{'coursecredits'} = 1;
20673: last;
20674: }
20675: }
20676: }
20677: }
20678: }
20679: if ($env{'form.postsubmit'} eq '1') {
20680: $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'on';
20681: my %currtimeout;
20682: if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
20683: if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'off') {
20684: $changes{'postsubmit'} = 1;
20685: }
20686: if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
20687: %currtimeout = %{$domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}};
20688: }
20689: } else {
20690: $changes{'postsubmit'} = 1;
20691: }
20692: foreach my $type (@types) {
20693: my $timeout = $env{'form.'.$type.'_timeout'};
20694: $timeout =~ s/\D//g;
20695: if ($timeout == $staticdefaults{'postsubmit'}) {
20696: $timeout = '';
20697: } elsif (($timeout eq '') || ($timeout =~ /^0+$/)) {
20698: $timeout = '0';
20699: }
20700: unless ($timeout eq '') {
20701: $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type} = $timeout;
20702: }
20703: if (exists($currtimeout{$type})) {
20704: if ($timeout ne $currtimeout{$type}) {
1.289 raeburn 20705: $changes{'postsubmit'} = 1;
1.257 raeburn 20706: }
20707: } elsif ($timeout ne '') {
20708: $changes{'postsubmit'} = 1;
20709: }
20710: }
20711: } else {
20712: $defaultshash{'coursedefaults'}{'postsubmit'}{'client'} = 'off';
20713: if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
20714: if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'on') {
20715: $changes{'postsubmit'} = 1;
20716: }
20717: } else {
20718: $changes{'postsubmit'} = 1;
20719: }
1.192 raeburn 20720: }
1.422 raeburn 20721: my (%newdomexttool,%newexttool,%olddomexttool,%oldexttool);
20722: map { $newdomexttool{$_} = 1; } &Apache::loncommon::get_env_multiple('form.domexttool');
1.425 raeburn 20723: map { $newexttool{$_} = 1; } &Apache::loncommon::get_env_multiple('form.exttool');
1.422 raeburn 20724: if (ref($domconfig{'coursedefaults'}{'domexttool'}) eq 'HASH') {
20725: %olddomexttool = %{$domconfig{'coursedefaults'}{'domexttool'}};
20726: } else {
20727: foreach my $type (@types) {
20728: if ($staticdefaults{'domexttool'}) {
20729: $olddomexttool{$type} = 1;
20730: } else {
20731: $olddomexttool{$type} = 0;
20732: }
20733: }
20734: }
20735: if (ref($domconfig{'coursedefaults'}{'exttool'}) eq 'HASH') {
1.425 raeburn 20736: %oldexttool = %{$domconfig{'coursedefaults'}{'exttool'}};
1.422 raeburn 20737: } else {
20738: foreach my $type (@types) {
20739: if ($staticdefaults{'exttool'}) {
20740: $oldexttool{$type} = 1;
20741: } else {
20742: $oldexttool{$type} = 0;
20743: }
20744: }
20745: }
20746: foreach my $type (@types) {
20747: unless ($newdomexttool{$type}) {
20748: $newdomexttool{$type} = 0;
20749: }
20750: unless ($newexttool{$type}) {
20751: $newexttool{$type} = 0;
20752: }
20753: if ($newdomexttool{$type} != $olddomexttool{$type}) {
20754: $changes{'domexttool'} = 1;
20755: }
20756: if ($newexttool{$type} != $oldexttool{$type}) {
20757: $changes{'exttool'} = 1;
20758: }
20759: }
20760: $defaultshash{'coursedefaults'}{'domexttool'} = \%newdomexttool;
20761: $defaultshash{'coursedefaults'}{'exttool'} = \%newexttool;
1.121 raeburn 20762: }
20763: my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
20764: $dom);
20765: if ($putresult eq 'ok') {
20766: if (keys(%changes) > 0) {
1.213 raeburn 20767: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
1.257 raeburn 20768: if (($changes{'canuse_pdfforms'}) || ($changes{'uploadquota'}) || ($changes{'postsubmit'}) ||
1.264 raeburn 20769: ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) ||
1.398 raeburn 20770: ($changes{'canclone'}) || ($changes{'mysqltables'}) || ($changes{'texengine'}) ||
1.422 raeburn 20771: ($changes{'inline_chem'}) || ($changes{'ltiauth'}) || ($changes{'domexttool'}) ||
1.428 ! raeburn 20772: ($changes{'exttool'}) || ($changes{'coursequota'})) {
1.422 raeburn 20773: foreach my $item ('canuse_pdfforms','uselcmath','usejsme','inline_chem','texengine',
20774: 'ltiauth') {
1.257 raeburn 20775: if ($changes{$item}) {
20776: $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item};
20777: }
1.289 raeburn 20778: }
1.192 raeburn 20779: if ($changes{'coursecredits'}) {
20780: if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
1.257 raeburn 20781: foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'coursecredits'}})) {
20782: $domdefaults{$type.'credits'} =
20783: $defaultshash{'coursedefaults'}{'coursecredits'}{$type};
20784: }
20785: }
20786: }
20787: if ($changes{'postsubmit'}) {
20788: if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
20789: $domdefaults{'postsubmit'} = $defaultshash{'coursedefaults'}{'postsubmit'}{'client'};
20790: if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
20791: foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}})) {
20792: $domdefaults{$type.'postsubtimeout'} =
20793: $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};
20794: }
20795: }
1.192 raeburn 20796: }
20797: }
1.198 raeburn 20798: if ($changes{'uploadquota'}) {
20799: if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
20800: foreach my $type (@types) {
20801: $domdefaults{$type.'quota'}=$defaultshash{'coursedefaults'}{'uploadquota'}{$type};
20802: }
20803: }
20804: }
1.428 ! raeburn 20805: if ($changes{'coursequota'}) {
! 20806: if (ref($defaultshash{'coursedefaults'}{'coursequota'}) eq 'HASH') {
! 20807: foreach my $type (@types) {
! 20808: $domdefaults{$type.'coursequota'}=$defaultshash{'coursedefaults'}{'coursequota'}{$type};
! 20809: }
! 20810: }
! 20811: }
1.264 raeburn 20812: if ($changes{'canclone'}) {
20813: if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {
20814: if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {
20815: my @clonecodes = @{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}};
20816: if (@clonecodes) {
20817: $domdefaults{'canclone'} = join('+',@clonecodes);
20818: }
20819: }
20820: } else {
20821: $domdefaults{'canclone'}=$defaultshash{'coursedefaults'}{'canclone'};
20822: }
20823: }
1.422 raeburn 20824: if ($changes{'domexttool'}) {
20825: if (ref($defaultshash{'coursedefaults'}{'domexttool'}) eq 'HASH') {
20826: foreach my $type (@types) {
20827: $domdefaults{$type.'domexttool'}=$defaultshash{'coursedefaults'}{'domexttool'}{$type};
20828: }
20829: }
20830: }
20831: if ($changes{'exttool'}) {
20832: if (ref($defaultshash{'coursedefaults'}{'exttool'}) eq 'HASH') {
20833: foreach my $type (@types) {
20834: $domdefaults{$type.'exttool'}=$defaultshash{'coursedefaults'}{'exttool'}{$type};
20835: }
20836: }
20837: }
1.121 raeburn 20838: my $cachetime = 24*60*60;
20839: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
1.212 raeburn 20840: if (ref($lastactref) eq 'HASH') {
20841: $lastactref->{'domdefaults'} = 1;
20842: }
1.121 raeburn 20843: }
20844: $resulttext = &mt('Changes made:').'<ul>';
20845: foreach my $item (sort(keys(%changes))) {
20846: if ($item eq 'canuse_pdfforms') {
20847: if ($env{'form.'.$item} eq '1') {
20848: $resulttext .= '<li>'.&mt("Course/Community users can create/upload PDF forms set to 'on'").'</li>';
20849: } else {
20850: $resulttext .= '<li>'.&mt('Course/Community users can create/upload PDF forms set to "off"').'</li>';
20851: }
1.257 raeburn 20852: } elsif ($item eq 'uselcmath') {
20853: if ($env{'form.'.$item} eq '1') {
20854: $resulttext .= '<li>'.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'</li>';
20855: } else {
20856: $resulttext .= '<li>'.&mt('Math preview uses DragMath (Java), if supported by client OS.').'</li>';
20857: }
20858: } elsif ($item eq 'usejsme') {
20859: if ($env{'form.'.$item} eq '1') {
20860: $resulttext .= '<li>'.&mt('Molecule editor uses JSME (HTML5), if supported by browser.').'</li>';
20861: } else {
1.289 raeburn 20862: $resulttext .= '<li>'.&mt('Molecule editor uses JME (Java), if supported by client OS.').'</li>';
1.257 raeburn 20863: }
1.398 raeburn 20864: } elsif ($item eq 'inline_chem') {
20865: if ($env{'form.'.$item} eq '1') {
20866: $resulttext .= '<li>'.&mt('Chemical Reaction Response uses inline previewer').'</li>';
20867: } else {
20868: $resulttext .= '<li>'.&mt('Chemical Reaction Response uses pop-up previewer').'</li>';
20869: }
1.314 raeburn 20870: } elsif ($item eq 'texengine') {
20871: if ($defaultshash{'coursedefaults'}{'texengine'} ne '') {
20872: $resulttext .= '<li>'.&mt('Default method to display mathematics set to: "[_1]"',
20873: $texoptions{$defaultshash{'coursedefaults'}{'texengine'}}).'</li>';
20874: }
1.139 raeburn 20875: } elsif ($item eq 'anonsurvey_threshold') {
1.192 raeburn 20876: $resulttext .= '<li>'.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'</li>';
1.198 raeburn 20877: } elsif ($item eq 'uploadquota') {
20878: if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') {
20879: $resulttext .= '<li>'.&mt('Default quota for content uploaded to a course/community via Course Editor set as follows:').'<ul>'.
20880: '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'</b>').'</li>'.
20881: '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'</b>').'</li>'.
1.216 raeburn 20882: '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'</b>').'</li>'.
1.271 raeburn 20883: '<li>'.&mt('Placement tests: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'placement'}.'</b>').'</li>'.
1.198 raeburn 20884: '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'</b>').'</li>'.
20885: '</ul>'.
20886: '</li>';
20887: } else {
20888: $resulttext .= '<li>'.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'</li>';
20889: }
1.428 ! raeburn 20890: } elsif ($item eq 'coursequota') {
! 20891: if (ref($defaultshash{'coursedefaults'}{'coursequota'}) eq 'HASH') {
! 20892: $resulttext .= '<li>'.&mt('Default cumulative quota for all group portfolio spaces in course set as follows:').'<ul>'.
! 20893: '<li>'.&mt('Official courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'coursequota'}{'official'}.'</b>').'</li>'.
! 20894: '<li>'.&mt('Unofficial courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'coursequota'}{'unofficial'}.'</b>').'</li>'.
! 20895: '<li>'.&mt('Textbook courses: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'coursequota'}{'textbook'}.'</b>').'</li>'.
! 20896: '<li>'.&mt('Placement tests: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'coursequota'}{'placement'}.'</b>').'</li>'.
! 20897: '<li>'.&mt('Communities: [_1] MB','<b>'.$defaultshash{'coursedefaults'}{'coursequota'}{'community'}.'</b>').'</li>'.
! 20898: '</ul>'.
! 20899: '</li>';
! 20900: } else {
! 20901: $resulttext .= '<li>'.&mt('Default cumulative quota for all group portfolio spaces in course remains default: [_1] MB',$staticdefaults{'coursequota'}).'</li>';
! 20902: }
1.276 raeburn 20903: } elsif ($item eq 'mysqltables') {
20904: if (ref($defaultshash{'coursedefaults'}{'mysqltables'}) eq 'HASH') {
20905: $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver').'<ul>'.
20906: '<li>'.&mt('Official courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'</b>').'</li>'.
20907: '<li>'.&mt('Unofficial courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'</b>').'</li>'.
20908: '<li>'.&mt('Textbook courses: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'</b>').'</li>'.
20909: '<li>'.&mt('Placement tests: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'placement'}.'</b>').'</li>'.
20910: '<li>'.&mt('Communities: [_1] s','<b>'.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'</b>').'</li>'.
20911: '</ul>'.
20912: '</li>';
20913: } else {
20914: $resulttext .= '<li>'.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver remains default: [_1] s',$staticdefaults{'uploadquota'}).'</li>';
20915: }
1.257 raeburn 20916: } elsif ($item eq 'postsubmit') {
20917: if ($domdefaults{'postsubmit'} eq 'off') {
20918: $resulttext .= '<li>'.&mt('Submit button(s) remain enabled on page after student makes submission.');
20919: } else {
20920: $resulttext .= '<li>'.&mt('Submit button(s) disabled on page after student makes submission').'; ';
1.289 raeburn 20921: if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
1.257 raeburn 20922: $resulttext .= &mt('durations:').'<ul>';
20923: foreach my $type (@types) {
20924: $resulttext .= '<li>';
20925: my $timeout;
20926: if (ref($defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
20927: $timeout = $defaultshash{'coursedefaults'}{'postsubmit'}{'timeout'}{$type};
20928: }
20929: my $display;
20930: if ($timeout eq '0') {
20931: $display = &mt('unlimited');
20932: } elsif ($timeout eq '') {
20933: $display = &mt('[quant,_1,second] (default)',$staticdefaults{'postsubmit'});
20934: } else {
20935: $display = &mt('[quant,_1,second]',$timeout);
20936: }
20937: if ($type eq 'community') {
20938: $resulttext .= &mt('Communities');
20939: } elsif ($type eq 'official') {
20940: $resulttext .= &mt('Official courses');
20941: } elsif ($type eq 'unofficial') {
20942: $resulttext .= &mt('Unofficial courses');
20943: } elsif ($type eq 'textbook') {
20944: $resulttext .= &mt('Textbook courses');
1.271 raeburn 20945: } elsif ($type eq 'placement') {
20946: $resulttext .= &mt('Placement tests');
1.257 raeburn 20947: }
20948: $resulttext .= ' -- '.$display.'</li>';
20949: }
20950: $resulttext .= '</ul>';
20951: }
1.289 raeburn 20952: $resulttext .= '</li>';
1.257 raeburn 20953: }
1.192 raeburn 20954: } elsif ($item eq 'coursecredits') {
20955: if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') {
20956: if (($domdefaults{'officialcredits'} eq '') &&
1.216 raeburn 20957: ($domdefaults{'unofficialcredits'} eq '') &&
20958: ($domdefaults{'textbookcredits'} eq '')) {
1.192 raeburn 20959: $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
20960: } else {
20961: $resulttext .= '<li>'.&mt('Student credits can be set per course by a Domain Coordinator, with the following defaults applying:').'<ul>'.
20962: '<li>'.&mt('Official courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'official'}).'</li>'.
20963: '<li>'.&mt('Unofficial courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}).'</li>'.
1.216 raeburn 20964: '<li>'.&mt('Textbook courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'textbook'}).'</li>'.
1.192 raeburn 20965: '</ul>'.
20966: '</li>';
20967: }
20968: } else {
20969: $resulttext .= '<li>'.&mt('Student credits not in use for courses in this domain').'</li>';
20970: }
1.264 raeburn 20971: } elsif ($item eq 'canclone') {
20972: if (ref($defaultshash{'coursedefaults'}{'canclone'}) eq 'HASH') {
20973: if (ref($defaultshash{'coursedefaults'}{'canclone'}{'instcode'}) eq 'ARRAY') {
20974: my $clonecodes = join(' '.&mt('and').' ',@{$defaultshash{'coursedefaults'}{'canclone'}{'instcode'}});
20975: $resulttext .= '<li>'.&mt('By default, official courses can be cloned from existing courses with the same: [_1]','<b>'.$clonecodes.'</b>').'</li>';
20976: }
20977: } elsif ($defaultshash{'coursedefaults'}{'canclone'} eq 'domain') {
20978: $resulttext .= '<li>'.&mt('By default, a course requester can clone any course from his/her domain.').'</li>';
20979: } else {
1.289 raeburn 20980: $resulttext .= '<li>'.&mt('By default, only course owner and coordinators may clone a course.').'</li>';
1.264 raeburn 20981: }
1.404 raeburn 20982: } elsif ($item eq 'ltiauth') {
20983: if ($env{'form.'.$item} eq '1') {
20984: $resulttext .= '<li>'.&mt('LTI launch of deep-linked URL need not require re-authentication').'</li>';
20985: } else {
20986: $resulttext .= '<li>'.&mt('LTI launch of deep-linked URL will require re-authentication').'</li>';
20987: }
1.422 raeburn 20988: } elsif ($item eq 'domexttool') {
20989: my @noyes = (&mt('no'),&mt('yes'));
20990: if (ref($defaultshash{'coursedefaults'}{'domexttool'}) eq 'HASH') {
20991: $resulttext .= '<li>'.&mt('External Tools defined in the domain may be used as follows:').'<ul>'.
20992: '<li>'.&mt('Official courses: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'domexttool'}{'official'}].'</b>').'</li>'.
20993: '<li>'.&mt('Unofficial courses: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'domexttool'}{'unofficial'}].'</b>').'</li>'.
20994: '<li>'.&mt('Textbook courses: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'domexttool'}{'textbook'}].'</b>').'</li>'.
20995: '<li>'.&mt('Placement tests: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'domexttool'}{'placement'}].'</b>').'</li>'.
20996: '<li>'.&mt('Communities: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'domexttool'}{'community'}].'</b>').'</li>'.
20997: '</ul>'.
20998: '</li>';
20999: } else {
21000: $resulttext .= '<li>'.&mt('External Tools defined in the domain may be used in all course types, by default').'</li>';
21001: }
21002: } elsif ($item eq 'exttool') {
21003: my @noyes = (&mt('no'),&mt('yes'));
21004: if (ref($defaultshash{'coursedefaults'}{'exttool'}) eq 'HASH') {
21005: $resulttext .= '<li>'.&mt('External Tools can be defined and configured in course containers as follows:').'<ul>'.
21006: '<li>'.&mt('Official courses: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'exttool'}{'official'}].'</b>').'</li>'.
21007: '<li>'.&mt('Unofficial courses: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'exttool'}{'unofficial'}].'</b>').'</li>'.
21008: '<li>'.&mt('Textbook courses: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'exttool'}{'textbook'}].'</b>').'</li>'.
21009: '<li>'.&mt('Placement tests: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'exttool'}{'placement'}].'</b>').'</li>'.
21010: '<li>'.&mt('Communities: [_1]','<b>'.$noyes[$defaultshash{'coursedefaults'}{'exttool'}{'community'}].'</b>').'</li>'.
21011: '</ul>'.
21012: '</li>';
21013: } else {
21014: $resulttext .= '<li>'.&mt('External Tools can not be defined in any course types, by default').'</li>';
21015: }
1.140 raeburn 21016: }
1.121 raeburn 21017: }
21018: $resulttext .= '</ul>';
21019: } else {
21020: $resulttext = &mt('No changes made to course defaults');
21021: }
21022: } else {
21023: $resulttext = '<span class="LC_error">'.
21024: &mt('An error occurred: [_1]',$putresult).'</span>';
21025: }
21026: return $resulttext;
21027: }
21028:
1.231 raeburn 21029: sub modify_selfenrollment {
21030: my ($dom,$lastactref,%domconfig) = @_;
21031: my ($resulttext,$errors,%changes,%selfenrollhash,%ordered);
1.271 raeburn 21032: my @types = ('official','unofficial','community','textbook','placement');
1.231 raeburn 21033: my %titles = &tool_titles();
1.232 raeburn 21034: my %descs = &Apache::lonuserutils::selfenroll_default_descs();
21035: ($ordered{'admin'},my $titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
1.231 raeburn 21036: $ordered{'default'} = ['types','registered','approval','limit'];
21037:
21038: my (%roles,%shown,%toplevel);
21039: $roles{'0'} = &Apache::lonnet::plaintext('dc');
21040:
21041: if (ref($domconfig{'selfenrollment'}) ne 'HASH') {
21042: if ($domconfig{'selfenrollment'} eq '') {
21043: $domconfig{'selfenrollment'} = {};
21044: }
21045: }
21046: %toplevel = (
21047: admin => 'Configuration Rights',
21048: default => 'Default settings',
21049: validation => 'Validation of self-enrollment requests',
21050: );
1.233 raeburn 21051: my ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types();
1.231 raeburn 21052:
21053: if (ref($ordered{'admin'}) eq 'ARRAY') {
21054: foreach my $item (@{$ordered{'admin'}}) {
21055: foreach my $type (@types) {
21056: if ($env{'form.selfenrolladmin_'.$item.'_'.$type}) {
21057: $selfenrollhash{'admin'}{$type}{$item} = 1;
21058: } else {
21059: $selfenrollhash{'admin'}{$type}{$item} = 0;
21060: }
21061: if (ref($domconfig{'selfenrollment'}{'admin'}) eq 'HASH') {
21062: if (ref($domconfig{'selfenrollment'}{'admin'}{$type}) eq 'HASH') {
21063: if ($selfenrollhash{'admin'}{$type}{$item} ne
21064: $domconfig{'selfenrollment'}{'admin'}{$type}{$item}) {
21065: push(@{$changes{'admin'}{$type}},$item);
21066: }
21067: } else {
21068: if (!$selfenrollhash{'admin'}{$type}{$item}) {
21069: push(@{$changes{'admin'}{$type}},$item);
21070: }
21071: }
21072: } elsif (!$selfenrollhash{'admin'}{$type}{$item}) {
21073: push(@{$changes{'admin'}{$type}},$item);
21074: }
21075: }
21076: }
21077: }
21078:
21079: foreach my $item (@{$ordered{'default'}}) {
21080: foreach my $type (@types) {
21081: my $value = $env{'form.selfenrolldefault_'.$item.'_'.$type};
21082: if ($item eq 'types') {
21083: unless (($value eq 'all') || ($value eq 'dom')) {
21084: $value = '';
21085: }
21086: } elsif ($item eq 'registered') {
21087: unless ($value eq '1') {
21088: $value = 0;
21089: }
21090: } elsif ($item eq 'approval') {
21091: unless ($value =~ /^[012]$/) {
21092: $value = 0;
21093: }
21094: } else {
21095: unless (($value eq 'allstudents') || ($value eq 'selfenrolled')) {
21096: $value = 'none';
21097: }
21098: }
21099: $selfenrollhash{'default'}{$type}{$item} = $value;
21100: if (ref($domconfig{'selfenrollment'}{'default'}) eq 'HASH') {
21101: if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {
21102: if ($selfenrollhash{'default'}{$type}{$item} ne
21103: $domconfig{'selfenrollment'}{'default'}{$type}{$item}) {
21104: push(@{$changes{'default'}{$type}},$item);
21105: }
21106: } else {
21107: push(@{$changes{'default'}{$type}},$item);
21108: }
21109: } else {
21110: push(@{$changes{'default'}{$type}},$item);
21111: }
21112: if ($item eq 'limit') {
21113: if (($value eq 'allstudents') || ($value eq 'selfenrolled')) {
21114: $env{'form.selfenrolldefault_cap_'.$type} =~ s/\D//g;
21115: if ($env{'form.selfenrolldefault_cap_'.$type} ne '') {
21116: $selfenrollhash{'default'}{$type}{'cap'} = $env{'form.selfenrolldefault_cap_'.$type};
21117: }
21118: } else {
21119: $selfenrollhash{'default'}{$type}{'cap'} = '';
21120: }
21121: if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') {
21122: if ($selfenrollhash{'default'}{$type}{'cap'} ne
21123: $domconfig{'selfenrollment'}{'admin'}{$type}{'cap'}) {
21124: push(@{$changes{'default'}{$type}},'cap');
21125: }
21126: } elsif ($selfenrollhash{'default'}{$type}{'cap'} ne '') {
21127: push(@{$changes{'default'}{$type}},'cap');
21128: }
21129: }
21130: }
21131: }
21132:
21133: foreach my $item (@{$itemsref}) {
21134: if ($item eq 'fields') {
21135: my @changed;
21136: @{$selfenrollhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.selfenroll_validation_'.$item);
21137: if (@{$selfenrollhash{'validation'}{$item}} > 0) {
21138: @{$selfenrollhash{'validation'}{$item}} = sort(@{$selfenrollhash{'validation'}{$item}});
21139: }
21140: if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {
21141: if (ref($domconfig{'selfenrollment'}{'validation'}{$item}) eq 'ARRAY') {
21142: @changed = &Apache::loncommon::compare_arrays($selfenrollhash{'validation'}{$item},
21143: $domconfig{'selfenrollment'}{'validation'}{$item});
21144: } else {
21145: @changed = @{$selfenrollhash{'validation'}{$item}};
21146: }
21147: } else {
21148: @changed = @{$selfenrollhash{'validation'}{$item}};
21149: }
21150: if (@changed) {
21151: if ($selfenrollhash{'validation'}{$item}) {
21152: $changes{'validation'}{$item} = join(', ',@{$selfenrollhash{'validation'}{$item}});
21153: } else {
21154: $changes{'validation'}{$item} = &mt('None');
21155: }
21156: }
21157: } else {
21158: $selfenrollhash{'validation'}{$item} = $env{'form.selfenroll_validation_'.$item};
21159: if ($item eq 'markup') {
21160: if ($env{'form.selfenroll_validation_'.$item}) {
21161: $env{'form.selfenroll_validation_'.$item} =~ s/[\n\r\f]+/\s/gs;
21162: }
21163: }
21164: if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') {
21165: if ($domconfig{'selfenrollment'}{'validation'}{$item} ne $selfenrollhash{'validation'}{$item}) {
21166: $changes{'validation'}{$item} = $selfenrollhash{'validation'}{$item};
21167: }
21168: }
21169: }
21170: }
21171:
21172: my $putresult = &Apache::lonnet::put_dom('configuration',{'selfenrollment' => \%selfenrollhash},
21173: $dom);
21174: if ($putresult eq 'ok') {
21175: if (keys(%changes) > 0) {
21176: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
21177: $resulttext = &mt('Changes made:').'<ul>';
21178: foreach my $key ('admin','default','validation') {
21179: if (ref($changes{$key}) eq 'HASH') {
21180: $resulttext .= '<li>'.$toplevel{$key}.'<ul>';
21181: if ($key eq 'validation') {
21182: foreach my $item (@{$itemsref}) {
21183: if (exists($changes{$key}{$item})) {
21184: if ($item eq 'markup') {
21185: $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},
21186: '<br /><pre>'.$changes{$key}{$item}.'</pre>').'</li>';
21187: } else {
21188: $resulttext .= '<li>'.&mt('[_1] set to: [_2]',$namesref->{$item},
21189: '<b>'.$changes{$key}{$item}.'</b>').'</li>';
21190: }
21191: }
21192: }
21193: } else {
21194: foreach my $type (@types) {
21195: if ($type eq 'community') {
21196: $roles{'1'} = &mt('Community personnel');
21197: } else {
21198: $roles{'1'} = &mt('Course personnel');
21199: }
21200: if (ref($changes{$key}{$type}) eq 'ARRAY') {
1.232 raeburn 21201: if (ref($selfenrollhash{$key}{$type}) eq 'HASH') {
21202: if ($key eq 'admin') {
21203: my @mgrdc = ();
21204: if (ref($ordered{$key}) eq 'ARRAY') {
21205: foreach my $item (@{$ordered{'admin'}}) {
21206: if (ref($selfenrollhash{$key}{$type}) eq 'HASH') {
21207: if ($selfenrollhash{$key}{$type}{$item} eq '0') {
21208: push(@mgrdc,$item);
21209: }
21210: }
21211: }
21212: if (@mgrdc) {
21213: $domdefaults{$type.'selfenrolladmdc'} = join(',',@mgrdc);
21214: } else {
21215: delete($domdefaults{$type.'selfenrolladmdc'});
21216: }
21217: }
21218: } else {
21219: if (ref($ordered{$key}) eq 'ARRAY') {
21220: foreach my $item (@{$ordered{$key}}) {
21221: if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {
21222: $domdefaults{$type.'selfenroll'.$item} =
21223: $selfenrollhash{$key}{$type}{$item};
21224: }
21225: }
21226: }
21227: }
21228: }
1.231 raeburn 21229: $resulttext .= '<li>'.$titles{$type}.'<ul>';
21230: foreach my $item (@{$ordered{$key}}) {
21231: if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) {
21232: $resulttext .= '<li>';
21233: if ($key eq 'admin') {
21234: $resulttext .= &mt('[_1] -- management by: [_2]',$titlesref->{$item},
21235: '<b>'.$roles{$selfenrollhash{'admin'}{$type}{$item}}.'</b>');
21236: } else {
21237: $resulttext .= &mt('[_1] set to: [_2]',$titlesref->{$item},
21238: '<b>'.$descs{$item}{$selfenrollhash{'default'}{$type}{$item}}.'</b>');
21239: }
21240: $resulttext .= '</li>';
21241: }
21242: }
21243: $resulttext .= '</ul></li>';
21244: }
21245: }
21246: $resulttext .= '</ul></li>';
21247: }
21248: }
1.305 raeburn 21249: }
21250: if ((exists($changes{'admin'})) || (exists($changes{'default'}))) {
21251: my $cachetime = 24*60*60;
21252: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
21253: if (ref($lastactref) eq 'HASH') {
21254: $lastactref->{'domdefaults'} = 1;
1.232 raeburn 21255: }
1.231 raeburn 21256: }
21257: $resulttext .= '</ul>';
21258: } else {
21259: $resulttext = &mt('No changes made to self-enrollment settings');
21260: }
21261: } else {
21262: $resulttext = '<span class="LC_error">'.
21263: &mt('An error occurred: [_1]',$putresult).'</span>';
21264: }
21265: return $resulttext;
21266: }
21267:
1.373 raeburn 21268: sub modify_wafproxy {
21269: my ($dom,$action,$lastactref,%domconfig) = @_;
21270: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.388 raeburn 21271: my (%othercontrol,%canset,%values,%curralias,%currsaml,%currvalue,@warnings,
21272: %wafproxy,%changes,%expirecache,%expiresaml);
1.373 raeburn 21273: foreach my $server (sort(keys(%servers))) {
21274: my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
21275: if ($serverhome eq $server) {
21276: my $serverdom = &Apache::lonnet::host_domain($server);
21277: if ($serverdom eq $dom) {
21278: $canset{$server} = 1;
21279: }
21280: }
21281: }
1.381 raeburn 21282: if (ref($domconfig{'wafproxy'}) eq 'HASH') {
21283: %{$values{$dom}} = ();
21284: if (ref($domconfig{'wafproxy'}{'alias'}) eq 'HASH') {
21285: %curralias = %{$domconfig{'wafproxy'}{'alias'}};
21286: }
1.388 raeburn 21287: if (ref($domconfig{'wafproxy'}{'saml'}) eq 'HASH') {
21288: %currsaml = %{$domconfig{'wafproxy'}{'saml'}};
21289: }
1.382 raeburn 21290: foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
1.381 raeburn 21291: $currvalue{$item} = $domconfig{'wafproxy'}{$item};
21292: }
21293: }
1.373 raeburn 21294: my $output;
21295: if (keys(%canset)) {
21296: %{$wafproxy{'alias'}} = ();
1.388 raeburn 21297: %{$wafproxy{'saml'}} = ();
1.373 raeburn 21298: foreach my $key (sort(keys(%canset))) {
1.381 raeburn 21299: if ($env{'form.wafproxy_'.$dom}) {
21300: $wafproxy{'alias'}{$key} = $env{'form.wafproxy_alias_'.$key};
21301: $wafproxy{'alias'}{$key} =~ s/^\s+|\s+$//g;
21302: if ($wafproxy{'alias'}{$key} ne $curralias{$key}) {
21303: $changes{'alias'} = 1;
21304: }
1.388 raeburn 21305: if ($env{'form.wafproxy_alias_saml_'.$key}) {
21306: $wafproxy{'saml'}{$key} = 1;
21307: }
21308: if ($wafproxy{'saml'}{$key} ne $currsaml{$key}) {
21309: $changes{'saml'} = 1;
21310: }
1.381 raeburn 21311: } else {
21312: $wafproxy{'alias'}{$key} = '';
1.388 raeburn 21313: $wafproxy{'saml'}{$key} = '';
1.381 raeburn 21314: if ($curralias{$key}) {
21315: $changes{'alias'} = 1;
21316: }
1.388 raeburn 21317: if ($currsaml{$key}) {
21318: $changes{'saml'} = 1;
21319: }
1.373 raeburn 21320: }
21321: if ($wafproxy{'alias'}{$key} eq '') {
21322: if ($curralias{$key}) {
21323: $expirecache{$key} = 1;
21324: }
21325: delete($wafproxy{'alias'}{$key});
21326: }
1.388 raeburn 21327: if ($wafproxy{'saml'}{$key} eq '') {
21328: if ($currsaml{$key}) {
21329: $expiresaml{$key} = 1;
21330: }
21331: delete($wafproxy{'saml'}{$key});
21332: }
1.373 raeburn 21333: }
21334: unless (keys(%{$wafproxy{'alias'}})) {
21335: delete($wafproxy{'alias'});
21336: }
1.388 raeburn 21337: unless (keys(%{$wafproxy{'saml'}})) {
21338: delete($wafproxy{'saml'});
21339: }
21340: # Localization for values in %warn occurs in &mt() calls separately.
1.373 raeburn 21341: my %warn = (
21342: trusted => 'trusted IP range(s)',
1.381 raeburn 21343: vpnint => 'internal IP range(s) for VPN sessions(s)',
21344: vpnext => 'IP range(s) for backend WAF connections',
1.373 raeburn 21345: );
1.382 raeburn 21346: foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
1.373 raeburn 21347: my $possible = $env{'form.wafproxy_'.$item};
21348: $possible =~ s/^\s+|\s+$//g;
21349: if ($possible ne '') {
1.381 raeburn 21350: if ($item eq 'remoteip') {
21351: if ($possible =~ /^[mhn]$/) {
21352: $wafproxy{$item} = $possible;
21353: }
21354: } elsif ($item eq 'ipheader') {
21355: if ($wafproxy{'remoteip'} eq 'h') {
21356: $wafproxy{$item} = $possible;
21357: }
1.382 raeburn 21358: } elsif ($item eq 'sslopt') {
21359: if ($possible =~ /^0|1$/) {
21360: $wafproxy{$item} = $possible;
21361: }
1.373 raeburn 21362: } else {
21363: my (@ok,$count);
1.381 raeburn 21364: if (($item eq 'vpnint') || ($item eq 'vpnext')) {
21365: unless ($env{'form.wafproxy_vpnaccess'}) {
21366: $possible = '';
21367: }
21368: } elsif ($item eq 'trusted') {
21369: unless ($wafproxy{'remoteip'} eq 'h') {
21370: $possible = '';
21371: }
21372: }
21373: unless ($possible eq '') {
21374: $possible =~ s/[\r\n]+/\s/g;
21375: $possible =~ s/\s*-\s*/-/g;
21376: $possible =~ s/\s+/,/g;
1.393 raeburn 21377: $possible =~ s/,+/,/g;
1.381 raeburn 21378: }
1.373 raeburn 21379: $count = 0;
1.381 raeburn 21380: if ($possible ne '') {
1.373 raeburn 21381: foreach my $poss (split(/\,/,$possible)) {
21382: $count ++;
1.393 raeburn 21383: $poss = &validate_ip_pattern($poss);
21384: if ($poss ne '') {
1.373 raeburn 21385: push(@ok,$poss);
21386: }
21387: }
21388: my $diff = $count - scalar(@ok);
21389: if ($diff) {
21390: push(@warnings,'<li>'.
21391: &mt('[quant,_1,IP] invalid and excluded from saved value for [_2]',
21392: $diff,$warn{$item}).
21393: '</li>');
21394: }
1.393 raeburn 21395: if (@ok) {
21396: my @cidr_list;
21397: foreach my $item (@ok) {
21398: @cidr_list = &Net::CIDR::cidradd($item,@cidr_list);
21399: }
21400: $wafproxy{$item} = join(',',@cidr_list);
21401: }
1.373 raeburn 21402: }
21403: }
1.381 raeburn 21404: if ($wafproxy{$item} ne $currvalue{$item}) {
1.373 raeburn 21405: $changes{$item} = 1;
21406: }
1.381 raeburn 21407: } elsif ($currvalue{$item}) {
21408: $changes{$item} = 1;
1.425 raeburn 21409: }
1.381 raeburn 21410: }
21411: } else {
21412: if (keys(%curralias)) {
21413: $changes{'alias'} = 1;
1.388 raeburn 21414: }
21415: if (keys(%currsaml)) {
21416: $changes{'saml'} = 1;
1.425 raeburn 21417: }
1.381 raeburn 21418: if (keys(%currvalue)) {
21419: foreach my $key (keys(%currvalue)) {
21420: $changes{$key} = 1;
1.373 raeburn 21421: }
21422: }
21423: }
21424: if (keys(%changes)) {
21425: my %defaultshash = (
21426: wafproxy => \%wafproxy,
1.425 raeburn 21427: );
1.373 raeburn 21428: my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
21429: $dom);
21430: if ($putresult eq 'ok') {
21431: my $cachetime = 24*60*60;
21432: my (%domdefaults,$updatedomdefs);
1.382 raeburn 21433: foreach my $item ('ipheader','trusted','vpnint','vpnext','sslopt') {
1.373 raeburn 21434: if ($changes{$item}) {
21435: unless ($updatedomdefs) {
21436: %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
21437: $updatedomdefs = 1;
21438: }
21439: if ($wafproxy{$item}) {
21440: $domdefaults{'waf_'.$item} = $wafproxy{$item};
21441: } elsif (exists($domdefaults{'waf_'.$item})) {
21442: delete($domdefaults{'waf_'.$item});
1.425 raeburn 21443: }
1.373 raeburn 21444: }
21445: }
21446: if ($updatedomdefs) {
21447: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
21448: if (ref($lastactref) eq 'HASH') {
21449: $lastactref->{'domdefaults'} = 1;
21450: }
21451: }
21452: if ((exists($wafproxy{'alias'})) || (keys(%expirecache))) {
21453: my %updates = %expirecache;
21454: foreach my $key (keys(%expirecache)) {
21455: &Apache::lonnet::devalidate_cache_new('proxyalias',$key);
21456: }
21457: if (ref($wafproxy{'alias'}) eq 'HASH') {
21458: my $cachetime = 24*60*60;
21459: foreach my $key (keys(%{$wafproxy{'alias'}})) {
21460: $updates{$key} = 1;
21461: &Apache::lonnet::do_cache_new('proxyalias',$key,$wafproxy{'alias'}{$key},
21462: $cachetime);
21463: }
21464: }
21465: if (ref($lastactref) eq 'HASH') {
21466: $lastactref->{'proxyalias'} = \%updates;
21467: }
21468: }
1.388 raeburn 21469: if ((exists($wafproxy{'saml'})) || (keys(%expiresaml))) {
21470: my %samlupdates = %expiresaml;
21471: foreach my $key (keys(%expiresaml)) {
21472: &Apache::lonnet::devalidate_cache_new('proxysaml',$key);
21473: }
21474: if (ref($wafproxy{'saml'}) eq 'HASH') {
21475: my $cachetime = 24*60*60;
21476: foreach my $key (keys(%{$wafproxy{'saml'}})) {
21477: $samlupdates{$key} = 1;
21478: &Apache::lonnet::do_cache_new('proxysaml',$key,$wafproxy{'saml'}{$key},
21479: $cachetime);
21480: }
21481: }
21482: if (ref($lastactref) eq 'HASH') {
21483: $lastactref->{'proxysaml'} = \%samlupdates;
21484: }
21485: }
1.373 raeburn 21486: $output = &mt('Changes were made to Web Application Firewall/Reverse Proxy').'<ul>';
1.401 raeburn 21487: foreach my $item ('alias','saml','remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
1.373 raeburn 21488: if ($changes{$item}) {
21489: if ($item eq 'alias') {
21490: my $numaliased = 0;
21491: if (ref($wafproxy{'alias'}) eq 'HASH') {
21492: my $shown;
21493: if (keys(%{$wafproxy{'alias'}})) {
21494: foreach my $server (sort(keys(%{$wafproxy{'alias'}}))) {
21495: $shown .= '<li>'.&mt('[_1] aliased by [_2]',
21496: &Apache::lonnet::hostname($server),
21497: $wafproxy{'alias'}{$server}).'</li>';
21498: $numaliased ++;
21499: }
21500: if ($numaliased) {
21501: $output .= '<li>'.&mt('Aliases for hostnames set to: [_1]',
21502: '<ul>'.$shown.'</ul>').'</li>';
21503: }
21504: }
21505: }
21506: unless ($numaliased) {
21507: $output .= '<li>'.&mt('Aliases deleted for hostnames').'</li>';
21508: }
1.388 raeburn 21509: } elsif ($item eq 'saml') {
1.425 raeburn 21510: my $shown;
1.388 raeburn 21511: if (ref($wafproxy{'saml'}) eq 'HASH') {
21512: if (keys(%{$wafproxy{'saml'}})) {
21513: $shown = join(', ',sort(keys(%{$wafproxy{'saml'}})));
21514: }
21515: }
21516: if ($shown) {
1.396 raeburn 21517: $output .= '<li>'.&mt('Alias used by SSO Auth for: [_1]',
1.388 raeburn 21518: $shown).'</li>';
21519: } else {
1.396 raeburn 21520: $output .= '<li>'.&mt('No alias used for SSO Auth').'</li>';
1.388 raeburn 21521: }
1.373 raeburn 21522: } else {
1.381 raeburn 21523: if ($item eq 'remoteip') {
21524: my %ip_methods = &remoteip_methods();
21525: if ($wafproxy{$item} =~ /^[mh]$/) {
21526: $output .= '<li>'.&mt("Method for determining user's IP set to: [_1]",
21527: $ip_methods{$wafproxy{$item}}).'</li>';
21528: } else {
21529: if (($env{'form.wafproxy_'.$dom}) && (ref($wafproxy{'alias'}) eq 'HASH')) {
21530: $output .= '<li>'.&mt("No method in use to get user's real IP (will report IP used by WAF).").
21531: '</li>';
21532: } else {
21533: $output .= '<li>'.&mt('WAF/Reverse Proxy not in use').'</li>';
21534: }
21535: }
21536: } elsif ($item eq 'ipheader') {
1.373 raeburn 21537: if ($wafproxy{$item}) {
1.381 raeburn 21538: $output .= '<li>'.&mt('Request header with remote IP set to: [_1]',
1.373 raeburn 21539: $wafproxy{$item}).'</li>';
21540: } else {
1.381 raeburn 21541: $output .= '<li>'.&mt('Request header with remote IP deleted').'</li>';
1.373 raeburn 21542: }
21543: } elsif ($item eq 'trusted') {
21544: if ($wafproxy{$item}) {
1.381 raeburn 21545: $output .= '<li>'.&mt('Trusted IP range(s) set to: [_1]',
1.373 raeburn 21546: $wafproxy{$item}).'</li>';
21547: } else {
21548: $output .= '<li>'.&mt('Trusted IP range(s) deleted').'</li>';
21549: }
1.381 raeburn 21550: } elsif ($item eq 'vpnint') {
21551: if ($wafproxy{$item}) {
21552: $output .= '<li>'.&mt('Internal IP Range(s) for VPN sessions set to: [_1]',
21553: $wafproxy{$item}).'</li>';
21554: } else {
21555: $output .= '<li>'.&mt('Internal IP Range(s) for VPN sessions deleted').'</li>';
21556: }
21557: } elsif ($item eq 'vpnext') {
1.373 raeburn 21558: if ($wafproxy{$item}) {
1.381 raeburn 21559: $output .= '<li>'.&mt('IP Range(s) for backend WAF connections set to: [_1]',
1.373 raeburn 21560: $wafproxy{$item}).'</li>';
21561: } else {
1.381 raeburn 21562: $output .= '<li>'.&mt('IP Range(s) for backend WAF connections deleted').'</li>';
1.373 raeburn 21563: }
1.382 raeburn 21564: } elsif ($item eq 'sslopt') {
21565: if ($wafproxy{$item}) {
21566: $output .= '<li>'.&mt('WAF/Reverse Proxy expected to forward requests to https on LON-CAPA node, regardless of original protocol in web browser (http or https).').'</li>';
21567: } else {
21568: $output .= '<li>'.&mt('WAF/Reverse Proxy expected to preserve original protocol in web browser (either http or https) when forwarding to LON-CAPA node.').'</li>';
21569: }
1.373 raeburn 21570: }
21571: }
21572: }
21573: }
1.420 raeburn 21574: $output .= '</ul>';
1.373 raeburn 21575: } else {
21576: $output = '<span class="LC_error">'.
21577: &mt('An error occurred: [_1]',$putresult).'</span>';
21578: }
21579: } elsif (keys(%canset)) {
21580: $output = &mt('No changes made to Web Application Firewall/Reverse Proxy settings');
21581: }
21582: if (@warnings) {
21583: $output .= '<br />'.&mt('Warnings:').'<ul>'.
21584: join("\n",@warnings).'</ul>';
21585: }
21586: return $output;
21587: }
21588:
21589: sub validate_ip_pattern {
21590: my ($pattern) = @_;
21591: if ($pattern =~ /^([^-]+)\-([^-]+)$/) {
21592: my ($start,$end) = ($1,$2);
21593: if ((&Net::CIDR::cidrvalidate($start)) && (&Net::CIDR::cidrvalidate($end))) {
1.393 raeburn 21594: if (($start !~ m{/}) && ($end !~ m{/})) {
21595: return $start.'-'.$end;
21596: }
21597: }
21598: } elsif ($pattern ne '') {
21599: $pattern = &Net::CIDR::cidrvalidate($pattern);
21600: if ($pattern ne '') {
21601: return $pattern;
1.373 raeburn 21602: }
21603: }
1.393 raeburn 21604: return;
1.373 raeburn 21605: }
21606:
1.137 raeburn 21607: sub modify_usersessions {
1.212 raeburn 21608: my ($dom,$lastactref,%domconfig) = @_;
1.145 raeburn 21609: my @hostingtypes = ('version','excludedomain','includedomain');
21610: my @offloadtypes = ('primary','default');
21611: my %types = (
21612: remote => \@hostingtypes,
21613: hosted => \@hostingtypes,
21614: spares => \@offloadtypes,
21615: );
21616: my @prefixes = ('remote','hosted','spares');
1.137 raeburn 21617: my @lcversions = &Apache::lonnet::all_loncaparevs();
1.275 raeburn 21618: my (%by_ip,%by_location,@intdoms,@instdoms);
21619: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
1.138 raeburn 21620: my @locations = sort(keys(%by_location));
1.137 raeburn 21621: my (%defaultshash,%changes);
21622: foreach my $prefix (@prefixes) {
21623: $defaultshash{'usersessions'}{$prefix} = {};
21624: }
1.212 raeburn 21625: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
1.137 raeburn 21626: my $resulttext;
1.138 raeburn 21627: my %iphost = &Apache::lonnet::get_iphost();
1.137 raeburn 21628: foreach my $prefix (@prefixes) {
1.145 raeburn 21629: next if ($prefix eq 'spares');
21630: foreach my $type (@{$types{$prefix}}) {
1.137 raeburn 21631: my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
21632: if ($type eq 'version') {
21633: my $value = $env{'form.'.$prefix.'_'.$type};
21634: my $okvalue;
21635: if ($value ne '') {
21636: if (grep(/^\Q$value\E$/,@lcversions)) {
21637: $okvalue = $value;
21638: }
21639: }
21640: if (ref($domconfig{'usersessions'}) eq 'HASH') {
21641: if (ref($domconfig{'usersessions'}{$prefix}) eq 'HASH') {
21642: if ($domconfig{'usersessions'}{$prefix}{$type} ne '') {
21643: if ($inuse == 0) {
21644: $changes{$prefix}{$type} = 1;
21645: } else {
21646: if ($okvalue ne $domconfig{'usersessions'}{$prefix}{$type}) {
21647: $changes{$prefix}{$type} = 1;
21648: }
21649: if ($okvalue ne '') {
21650: $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
21651: }
21652: }
21653: } else {
21654: if (($inuse == 1) && ($okvalue ne '')) {
21655: $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
21656: $changes{$prefix}{$type} = 1;
21657: }
21658: }
21659: } else {
21660: if (($inuse == 1) && ($okvalue ne '')) {
21661: $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
21662: $changes{$prefix}{$type} = 1;
21663: }
21664: }
21665: } else {
21666: if (($inuse == 1) && ($okvalue ne '')) {
21667: $defaultshash{'usersessions'}{$prefix}{$type} = $okvalue;
21668: $changes{$prefix}{$type} = 1;
21669: }
21670: }
21671: } else {
21672: my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
21673: my @okvals;
21674: foreach my $val (@vals) {
1.138 raeburn 21675: if ($val =~ /:/) {
21676: my @items = split(/:/,$val);
21677: foreach my $item (@items) {
21678: if (ref($by_location{$item}) eq 'ARRAY') {
21679: push(@okvals,$item);
21680: }
21681: }
21682: } else {
21683: if (ref($by_location{$val}) eq 'ARRAY') {
21684: push(@okvals,$val);
21685: }
1.137 raeburn 21686: }
21687: }
21688: @okvals = sort(@okvals);
21689: if (ref($domconfig{'usersessions'}) eq 'HASH') {
21690: if (ref($domconfig{'usersessions'}{$prefix}) eq 'HASH') {
21691: if (ref($domconfig{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
21692: if ($inuse == 0) {
21693: $changes{$prefix}{$type} = 1;
21694: } else {
21695: $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
21696: my @changed = &Apache::loncommon::compare_arrays($domconfig{'usersessions'}{$prefix}{$type},$defaultshash{'usersessions'}{$prefix}{$type});
21697: if (@changed > 0) {
21698: $changes{$prefix}{$type} = 1;
21699: }
21700: }
21701: } else {
21702: if ($inuse == 1) {
21703: $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
21704: $changes{$prefix}{$type} = 1;
21705: }
21706: }
21707: } else {
21708: if ($inuse == 1) {
21709: $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
21710: $changes{$prefix}{$type} = 1;
21711: }
21712: }
21713: } else {
21714: if ($inuse == 1) {
21715: $defaultshash{'usersessions'}{$prefix}{$type} = \@okvals;
21716: $changes{$prefix}{$type} = 1;
21717: }
21718: }
21719: }
21720: }
21721: }
1.145 raeburn 21722:
21723: my @alldoms = &Apache::lonnet::all_domains();
1.149 raeburn 21724: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.145 raeburn 21725: my %spareid = ¤t_offloads_to($dom,$domconfig{'usersessions'},\%servers);
21726: my $savespares;
21727:
21728: foreach my $lonhost (sort(keys(%servers))) {
21729: my $serverhomeID =
21730: &Apache::lonnet::get_server_homeID($servers{$lonhost});
1.152 raeburn 21731: my $serverhostname = &Apache::lonnet::hostname($lonhost);
1.145 raeburn 21732: $defaultshash{'usersessions'}{'spares'}{$lonhost} = {};
21733: my %spareschg;
21734: foreach my $type (@{$types{'spares'}}) {
21735: my @okspares;
21736: my @checked = &Apache::loncommon::get_env_multiple('form.spare_'.$type.'_'.$lonhost);
21737: foreach my $server (@checked) {
1.152 raeburn 21738: if (&Apache::lonnet::hostname($server) ne '') {
21739: unless (&Apache::lonnet::hostname($server) eq $serverhostname) {
21740: unless (grep(/^\Q$server\E$/,@okspares)) {
21741: push(@okspares,$server);
21742: }
1.145 raeburn 21743: }
21744: }
21745: }
21746: my $new = $env{'form.newspare_'.$type.'_'.$lonhost};
21747: my $newspare;
1.152 raeburn 21748: if (($new ne '') && (&Apache::lonnet::hostname($new))) {
21749: unless (&Apache::lonnet::hostname($new) eq $serverhostname) {
1.145 raeburn 21750: $newspare = $new;
21751: }
21752: }
1.152 raeburn 21753: my @spares;
21754: if (($newspare ne '') && (!grep(/^\Q$newspare\E$/,@okspares))) {
21755: @spares = sort(@okspares,$newspare);
21756: } else {
21757: @spares = sort(@okspares);
21758: }
21759: $defaultshash{'usersessions'}{'spares'}{$lonhost}{$type} = \@spares;
1.145 raeburn 21760: if (ref($spareid{$lonhost}) eq 'HASH') {
21761: if (ref($spareid{$lonhost}{$type}) eq 'ARRAY') {
1.152 raeburn 21762: my @diffs = &Apache::loncommon::compare_arrays($spareid{$lonhost}{$type},\@spares);
1.145 raeburn 21763: if (@diffs > 0) {
21764: $spareschg{$type} = 1;
21765: }
21766: }
21767: }
21768: }
21769: if (keys(%spareschg) > 0) {
21770: $changes{'spares'}{$lonhost} = \%spareschg;
21771: }
21772: }
1.261 raeburn 21773: $defaultshash{'usersessions'}{'offloadnow'} = {};
1.371 raeburn 21774: $defaultshash{'usersessions'}{'offloadoth'} = {};
1.261 raeburn 21775: my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');
21776: my @okoffload;
21777: if (@offloadnow) {
21778: foreach my $server (@offloadnow) {
21779: if (&Apache::lonnet::hostname($server) ne '') {
21780: unless (grep(/^\Q$server\E$/,@okoffload)) {
21781: push(@okoffload,$server);
21782: }
21783: }
21784: }
21785: if (@okoffload) {
21786: foreach my $lonhost (@okoffload) {
21787: $defaultshash{'usersessions'}{'offloadnow'}{$lonhost} = 1;
21788: }
21789: }
21790: }
1.371 raeburn 21791: my @offloadoth = &Apache::loncommon::get_env_multiple('form.offloadoth');
21792: my @okoffloadoth;
21793: if (@offloadoth) {
21794: foreach my $server (@offloadoth) {
21795: if (&Apache::lonnet::hostname($server) ne '') {
21796: unless (grep(/^\Q$server\E$/,@okoffloadoth)) {
21797: push(@okoffloadoth,$server);
21798: }
21799: }
21800: }
21801: if (@okoffloadoth) {
21802: foreach my $lonhost (@okoffloadoth) {
21803: $defaultshash{'usersessions'}{'offloadoth'}{$lonhost} = 1;
21804: }
21805: }
21806: }
1.145 raeburn 21807: if (ref($domconfig{'usersessions'}) eq 'HASH') {
21808: if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
21809: if (ref($changes{'spares'}) eq 'HASH') {
21810: if (keys(%{$changes{'spares'}}) > 0) {
21811: $savespares = 1;
21812: }
21813: }
21814: } else {
21815: $savespares = 1;
21816: }
1.371 raeburn 21817: foreach my $offload ('offloadnow','offloadoth') {
21818: if (ref($domconfig{'usersessions'}{$offload}) eq 'HASH') {
21819: foreach my $lonhost (keys(%{$domconfig{'usersessions'}{$offload}})) {
21820: unless ($defaultshash{'usersessions'}{$offload}{$lonhost}) {
21821: $changes{$offload} = 1;
21822: last;
21823: }
1.261 raeburn 21824: }
1.371 raeburn 21825: unless ($changes{$offload}) {
21826: foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{$offload}})) {
21827: unless ($domconfig{'usersessions'}{$offload}{$lonhost}) {
21828: $changes{$offload} = 1;
21829: last;
21830: }
1.261 raeburn 21831: }
21832: }
1.371 raeburn 21833: } else {
21834: if (($offload eq 'offloadnow') && (@okoffload)) {
21835: $changes{'offloadnow'} = 1;
21836: }
21837: if (($offload eq 'offloadoth') && (@okoffloadoth)) {
21838: $changes{'offloadoth'} = 1;
21839: }
1.425 raeburn 21840: }
1.371 raeburn 21841: }
21842: } else {
21843: if (@okoffload) {
1.261 raeburn 21844: $changes{'offloadnow'} = 1;
21845: }
1.371 raeburn 21846: if (@okoffloadoth) {
21847: $changes{'offloadoth'} = 1;
21848: }
1.145 raeburn 21849: }
1.147 raeburn 21850: my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
21851: if ((keys(%changes) > 0) || ($savespares)) {
1.137 raeburn 21852: my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
21853: $dom);
21854: if ($putresult eq 'ok') {
21855: if (ref($defaultshash{'usersessions'}) eq 'HASH') {
21856: if (ref($defaultshash{'usersessions'}{'remote'}) eq 'HASH') {
21857: $domdefaults{'remotesessions'} = $defaultshash{'usersessions'}{'remote'};
21858: }
21859: if (ref($defaultshash{'usersessions'}{'hosted'}) eq 'HASH') {
21860: $domdefaults{'hostedsessions'} = $defaultshash{'usersessions'}{'hosted'};
21861: }
1.261 raeburn 21862: if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
21863: $domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};
21864: }
1.371 raeburn 21865: if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {
21866: $domdefaults{'offloadoth'} = $defaultshash{'usersessions'}{'offloadoth'};
21867: }
1.137 raeburn 21868: }
21869: my $cachetime = 24*60*60;
21870: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
1.295 raeburn 21871: &Apache::lonnet::do_cache_new('usersessions',$dom,$defaultshash{'usersessions'},3600);
1.212 raeburn 21872: if (ref($lastactref) eq 'HASH') {
21873: $lastactref->{'domdefaults'} = 1;
1.295 raeburn 21874: $lastactref->{'usersessions'} = 1;
1.212 raeburn 21875: }
1.147 raeburn 21876: if (keys(%changes) > 0) {
21877: my %lt = &usersession_titles();
21878: $resulttext = &mt('Changes made:').'<ul>';
21879: foreach my $prefix (@prefixes) {
21880: if (ref($changes{$prefix}) eq 'HASH') {
21881: $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
21882: if ($prefix eq 'spares') {
21883: if (ref($changes{$prefix}) eq 'HASH') {
21884: foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) {
21885: $resulttext .= '<li><b>'.$lonhost.'</b> ';
1.148 raeburn 21886: my $lonhostdom = &Apache::lonnet::host_domain($lonhost);
1.211 raeburn 21887: my $cachekey = &escape('spares').':'.&escape($lonhostdom);
21888: &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
1.147 raeburn 21889: if (ref($changes{$prefix}{$lonhost}) eq 'HASH') {
21890: foreach my $type (@{$types{$prefix}}) {
21891: if ($changes{$prefix}{$lonhost}{$type}) {
21892: my $offloadto = &mt('None');
21893: if (ref($defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}) eq 'ARRAY') {
21894: if (@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}} > 0) {
21895: $offloadto = join(', ',@{$defaultshash{'usersessions'}{'spares'}{$lonhost}{$type}});
21896: }
1.145 raeburn 21897: }
1.147 raeburn 21898: $resulttext .= &mt('[_1] set to: [_2].','<i>'.$lt{$type}.'</i>',$offloadto).(' 'x3);
1.145 raeburn 21899: }
1.137 raeburn 21900: }
21901: }
1.147 raeburn 21902: $resulttext .= '</li>';
1.137 raeburn 21903: }
21904: }
1.147 raeburn 21905: } else {
21906: foreach my $type (@{$types{$prefix}}) {
21907: if (defined($changes{$prefix}{$type})) {
1.344 raeburn 21908: my ($newvalue,$notinuse);
1.147 raeburn 21909: if (ref($defaultshash{'usersessions'}) eq 'HASH') {
21910: if (ref($defaultshash{'usersessions'}{$prefix})) {
21911: if ($type eq 'version') {
21912: $newvalue = $defaultshash{'usersessions'}{$prefix}{$type};
1.344 raeburn 21913: } else {
21914: if (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
21915: if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
21916: $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
21917: }
21918: } else {
21919: $notinuse = 1;
1.147 raeburn 21920: }
1.145 raeburn 21921: }
21922: }
21923: }
1.147 raeburn 21924: if ($newvalue eq '') {
21925: if ($type eq 'version') {
21926: $resulttext .= '<li>'.&mt('[_1] set to: off',$lt{$type}).'</li>';
1.344 raeburn 21927: } elsif ($notinuse) {
21928: $resulttext .= '<li>'.&mt('[_1] set to: not in use',$lt{$type}).'</li>';
1.147 raeburn 21929: } else {
21930: $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
21931: }
1.145 raeburn 21932: } else {
1.147 raeburn 21933: if ($type eq 'version') {
1.344 raeburn 21934: $newvalue .= ' '.&mt('(or later)');
1.147 raeburn 21935: }
21936: $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
1.145 raeburn 21937: }
1.137 raeburn 21938: }
21939: }
21940: }
1.147 raeburn 21941: $resulttext .= '</ul>';
1.137 raeburn 21942: }
21943: }
1.261 raeburn 21944: if ($changes{'offloadnow'}) {
21945: if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
21946: if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {
1.371 raeburn 21947: $resulttext .= '<li>'.&mt('Switch any active user on next access, for server(s):').'<ul>';
1.261 raeburn 21948: foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {
21949: $resulttext .= '<li>'.$lonhost.'</li>';
21950: }
21951: $resulttext .= '</ul>';
21952: } else {
1.371 raeburn 21953: $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.');
21954: }
21955: } else {
21956: $resulttext .= '<li>'.&mt('No servers now set to switch any active user on next access.').'</li>';
21957: }
21958: }
21959: if ($changes{'offloadoth'}) {
21960: if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {
21961: if (keys(%{$defaultshash{'usersessions'}{'offloadoth'}}) > 0) {
21962: $resulttext .= '<li>'.&mt('Switch other institutions on next access, for server(s):').'<ul>';
21963: foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadoth'}}))) {
21964: $resulttext .= '<li>'.$lonhost.'</li>';
21965: }
21966: $resulttext .= '</ul>';
21967: } else {
21968: $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.');
1.261 raeburn 21969: }
21970: } else {
1.371 raeburn 21971: $resulttext .= '<li>'.&mt('No servers now set to switch other institutions on next access.').'</li>';
1.261 raeburn 21972: }
21973: }
1.147 raeburn 21974: $resulttext .= '</ul>';
21975: } else {
21976: $resulttext = $nochgmsg;
1.137 raeburn 21977: }
21978: } else {
21979: $resulttext = '<span class="LC_error">'.
21980: &mt('An error occurred: [_1]',$putresult).'</span>';
21981: }
21982: } else {
1.147 raeburn 21983: $resulttext = $nochgmsg;
1.137 raeburn 21984: }
21985: return $resulttext;
21986: }
21987:
1.275 raeburn 21988: sub modify_ssl {
21989: my ($dom,$lastactref,%domconfig) = @_;
21990: my (%by_ip,%by_location,@intdoms,@instdoms);
21991: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
21992: my @locations = sort(keys(%by_location));
21993: my %servers = &Apache::lonnet::internet_dom_servers($dom);
21994: my (%defaultshash,%changes);
21995: my $action = 'ssl';
1.293 raeburn 21996: my @prefixes = ('connto','connfrom','replication');
1.275 raeburn 21997: foreach my $prefix (@prefixes) {
21998: $defaultshash{$action}{$prefix} = {};
21999: }
22000: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
22001: my $resulttext;
22002: my %iphost = &Apache::lonnet::get_iphost();
22003: my @reptypes = ('certreq','nocertreq');
22004: my @connecttypes = ('dom','intdom','other');
22005: my %types = (
1.293 raeburn 22006: connto => \@connecttypes,
22007: connfrom => \@connecttypes,
22008: replication => \@reptypes,
1.275 raeburn 22009: );
22010: foreach my $prefix (sort(keys(%types))) {
22011: foreach my $type (@{$types{$prefix}}) {
1.293 raeburn 22012: if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
1.275 raeburn 22013: my $value = 'yes';
22014: if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
22015: $value = $env{'form.'.$prefix.'_'.$type};
22016: }
1.335 raeburn 22017: if (ref($domconfig{$action}) eq 'HASH') {
22018: if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
22019: if ($domconfig{$action}{$prefix}{$type} ne '') {
22020: if ($value ne $domconfig{$action}{$prefix}{$type}) {
22021: $changes{$prefix}{$type} = 1;
22022: }
22023: $defaultshash{$action}{$prefix}{$type} = $value;
22024: } else {
22025: $defaultshash{$action}{$prefix}{$type} = $value;
1.275 raeburn 22026: $changes{$prefix}{$type} = 1;
22027: }
22028: } else {
22029: $defaultshash{$action}{$prefix}{$type} = $value;
22030: $changes{$prefix}{$type} = 1;
22031: }
22032: } else {
22033: $defaultshash{$action}{$prefix}{$type} = $value;
22034: $changes{$prefix}{$type} = 1;
22035: }
22036: if (($type eq 'dom') && (keys(%servers) == 1)) {
22037: delete($changes{$prefix}{$type});
22038: } elsif (($type eq 'intdom') && (@instdoms == 1)) {
22039: delete($changes{$prefix}{$type});
22040: } elsif (($type eq 'other') && (keys(%by_location) == 0)) {
22041: delete($changes{$prefix}{$type});
22042: }
22043: } elsif ($prefix eq 'replication') {
22044: if (@locations > 0) {
22045: my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
22046: my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
22047: my @okvals;
22048: foreach my $val (@vals) {
22049: if ($val =~ /:/) {
22050: my @items = split(/:/,$val);
22051: foreach my $item (@items) {
22052: if (ref($by_location{$item}) eq 'ARRAY') {
22053: push(@okvals,$item);
22054: }
22055: }
22056: } else {
22057: if (ref($by_location{$val}) eq 'ARRAY') {
22058: push(@okvals,$val);
22059: }
22060: }
22061: }
22062: @okvals = sort(@okvals);
22063: if (ref($domconfig{$action}) eq 'HASH') {
22064: if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
22065: if (ref($domconfig{$action}{$prefix}{$type}) eq 'ARRAY') {
22066: if ($inuse == 0) {
22067: $changes{$prefix}{$type} = 1;
22068: } else {
22069: $defaultshash{$action}{$prefix}{$type} = \@okvals;
22070: my @changed = &Apache::loncommon::compare_arrays($domconfig{$action}{$prefix}{$type},$defaultshash{$action}{$prefix}{$type});
22071: if (@changed > 0) {
22072: $changes{$prefix}{$type} = 1;
22073: }
22074: }
22075: } else {
22076: if ($inuse == 1) {
22077: $defaultshash{$action}{$prefix}{$type} = \@okvals;
22078: $changes{$prefix}{$type} = 1;
22079: }
22080: }
22081: } else {
22082: if ($inuse == 1) {
22083: $defaultshash{$action}{$prefix}{$type} = \@okvals;
22084: $changes{$prefix}{$type} = 1;
22085: }
22086: }
22087: } else {
22088: if ($inuse == 1) {
22089: $defaultshash{$action}{$prefix}{$type} = \@okvals;
22090: $changes{$prefix}{$type} = 1;
22091: }
22092: }
22093: }
22094: }
22095: }
22096: }
1.336 raeburn 22097: if (keys(%changes)) {
22098: foreach my $prefix (keys(%changes)) {
22099: if (ref($changes{$prefix}) eq 'HASH') {
22100: if (scalar(keys(%{$changes{$prefix}})) == 0) {
22101: delete($changes{$prefix});
22102: }
22103: } else {
22104: delete($changes{$prefix});
22105: }
22106: }
22107: }
1.275 raeburn 22108: my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
22109: if (keys(%changes) > 0) {
22110: my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
22111: $dom);
22112: if ($putresult eq 'ok') {
22113: if (ref($defaultshash{$action}) eq 'HASH') {
22114: if (ref($defaultshash{$action}{'replication'}) eq 'HASH') {
22115: $domdefaults{'replication'} = $defaultshash{$action}{'replication'};
22116: }
1.293 raeburn 22117: if (ref($defaultshash{$action}{'connto'}) eq 'HASH') {
1.335 raeburn 22118: $domdefaults{'connto'} = $defaultshash{$action}{'connto'};
1.293 raeburn 22119: }
22120: if (ref($defaultshash{$action}{'connfrom'}) eq 'HASH') {
1.335 raeburn 22121: $domdefaults{'connfrom'} = $defaultshash{$action}{'connfrom'};
1.275 raeburn 22122: }
22123: }
22124: my $cachetime = 24*60*60;
22125: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
22126: if (ref($lastactref) eq 'HASH') {
22127: $lastactref->{'domdefaults'} = 1;
22128: }
22129: if (keys(%changes) > 0) {
22130: my %titles = &ssl_titles();
22131: $resulttext = &mt('Changes made:').'<ul>';
22132: foreach my $prefix (@prefixes) {
22133: if (ref($changes{$prefix}) eq 'HASH') {
22134: $resulttext .= '<li>'.$titles{$prefix}.'<ul>';
22135: foreach my $type (@{$types{$prefix}}) {
22136: if (defined($changes{$prefix}{$type})) {
1.344 raeburn 22137: my ($newvalue,$notinuse);
1.275 raeburn 22138: if (ref($defaultshash{$action}) eq 'HASH') {
22139: if (ref($defaultshash{$action}{$prefix})) {
1.293 raeburn 22140: if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
1.275 raeburn 22141: $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
1.344 raeburn 22142: } else {
22143: if (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
22144: if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
22145: $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
22146: }
22147: } else {
22148: $notinuse = 1;
1.275 raeburn 22149: }
22150: }
22151: }
1.344 raeburn 22152: if ($notinuse) {
22153: $resulttext .= '<li>'.&mt('[_1] set to: not in use',$titles{$type}).'</li>';
22154: } elsif ($newvalue eq '') {
1.275 raeburn 22155: $resulttext .= '<li>'.&mt('[_1] set to: none',$titles{$type}).'</li>';
22156: } else {
22157: $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).'</li>';
22158: }
22159: }
22160: }
22161: }
22162: $resulttext .= '</ul>';
22163: }
22164: }
22165: } else {
22166: $resulttext = $nochgmsg;
22167: }
22168: } else {
22169: $resulttext = '<span class="LC_error">'.
22170: &mt('An error occurred: [_1]',$putresult).'</span>';
22171: }
22172: } else {
22173: $resulttext = $nochgmsg;
22174: }
22175: return $resulttext;
22176: }
22177:
1.279 raeburn 22178: sub modify_trust {
22179: my ($dom,$lastactref,%domconfig) = @_;
22180: my (%by_ip,%by_location,@intdoms,@instdoms);
22181: &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
22182: my @locations = sort(keys(%by_location));
22183: my @prefixes = qw(content shared enroll othcoau coaurem domroles catalog reqcrs msg);
22184: my @types = ('exc','inc');
22185: my (%defaultshash,%changes);
22186: foreach my $prefix (@prefixes) {
22187: $defaultshash{'trust'}{$prefix} = {};
22188: }
22189: my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
22190: my $resulttext;
22191: foreach my $prefix (@prefixes) {
22192: foreach my $type (@types) {
22193: my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
22194: my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
22195: my @okvals;
22196: foreach my $val (@vals) {
22197: if ($val =~ /:/) {
22198: my @items = split(/:/,$val);
22199: foreach my $item (@items) {
22200: if (ref($by_location{$item}) eq 'ARRAY') {
22201: push(@okvals,$item);
22202: }
22203: }
22204: } else {
22205: if (ref($by_location{$val}) eq 'ARRAY') {
22206: push(@okvals,$val);
22207: }
22208: }
22209: }
22210: @okvals = sort(@okvals);
22211: if (ref($domconfig{'trust'}) eq 'HASH') {
22212: if (ref($domconfig{'trust'}{$prefix}) eq 'HASH') {
22213: if (ref($domconfig{'trust'}{$prefix}{$type}) eq 'ARRAY') {
22214: if ($inuse == 0) {
22215: $changes{$prefix}{$type} = 1;
22216: } else {
22217: $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
22218: my @changed = &Apache::loncommon::compare_arrays($domconfig{'trust'}{$prefix}{$type},$defaultshash{'trust'}{$prefix}{$type});
22219: if (@changed > 0) {
22220: $changes{$prefix}{$type} = 1;
22221: }
22222: }
22223: } else {
22224: if ($inuse == 1) {
22225: $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
22226: $changes{$prefix}{$type} = 1;
22227: }
22228: }
22229: } else {
22230: if ($inuse == 1) {
22231: $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
22232: $changes{$prefix}{$type} = 1;
22233: }
22234: }
22235: } else {
22236: if ($inuse == 1) {
22237: $defaultshash{'trust'}{$prefix}{$type} = \@okvals;
22238: $changes{$prefix}{$type} = 1;
22239: }
22240: }
22241: }
22242: }
22243: my $nochgmsg = &mt('No changes made to trust settings.');
22244: if (keys(%changes) > 0) {
22245: my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
22246: $dom);
22247: if ($putresult eq 'ok') {
22248: if (ref($defaultshash{'trust'}) eq 'HASH') {
22249: foreach my $prefix (@prefixes) {
22250: if (ref($defaultshash{'trust'}{$prefix}) eq 'HASH') {
22251: $domdefaults{'trust'.$prefix} = $defaultshash{'trust'}{$prefix};
22252: }
22253: }
22254: }
22255: my $cachetime = 24*60*60;
22256: &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
1.410 raeburn 22257: &Apache::lonnet::do_cache_new('trust',$dom,$defaultshash{'trust'},3600);
1.279 raeburn 22258: if (ref($lastactref) eq 'HASH') {
22259: $lastactref->{'domdefaults'} = 1;
1.410 raeburn 22260: $lastactref->{'trust'} = 1;
1.279 raeburn 22261: }
22262: if (keys(%changes) > 0) {
22263: my %lt = &trust_titles();
22264: $resulttext = &mt('Changes made:').'<ul>';
22265: foreach my $prefix (@prefixes) {
22266: if (ref($changes{$prefix}) eq 'HASH') {
22267: $resulttext .= '<li>'.$lt{$prefix}.'<ul>';
22268: foreach my $type (@types) {
22269: if (defined($changes{$prefix}{$type})) {
1.344 raeburn 22270: my ($newvalue,$notinuse);
1.279 raeburn 22271: if (ref($defaultshash{'trust'}) eq 'HASH') {
22272: if (ref($defaultshash{'trust'}{$prefix})) {
22273: if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
22274: if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
22275: $newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
22276: }
1.344 raeburn 22277: } else {
22278: $notinuse = 1;
1.279 raeburn 22279: }
22280: }
22281: }
1.344 raeburn 22282: if ($notinuse) {
22283: $resulttext .= '<li>'.&mt('[_1] set to: not in use',$lt{$type}).'</li>';
22284: } elsif ($newvalue eq '') {
1.279 raeburn 22285: $resulttext .= '<li>'.&mt('[_1] set to: none',$lt{$type}).'</li>';
22286: } else {
22287: $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).'</li>';
22288: }
22289: }
22290: }
22291: $resulttext .= '</ul>';
22292: }
22293: }
22294: $resulttext .= '</ul>';
22295: } else {
22296: $resulttext = $nochgmsg;
22297: }
22298: } else {
22299: $resulttext = '<span class="LC_error">'.
22300: &mt('An error occurred: [_1]',$putresult).'</span>';
22301: }
22302: } else {
22303: $resulttext = $nochgmsg;
22304: }
22305: return $resulttext;
22306: }
22307:
1.150 raeburn 22308: sub modify_loadbalancing {
22309: my ($dom,%domconfig) = @_;
22310: my $primary_id = &Apache::lonnet::domain($dom,'primary');
22311: my $intdom = &Apache::lonnet::internet_dom($primary_id);
22312: my ($othertitle,$usertypes,$types) =
22313: &Apache::loncommon::sorted_inst_types($dom);
22314: my %servers = &Apache::lonnet::internet_dom_servers($dom);
1.253 raeburn 22315: my %libraryservers = &Apache::lonnet::get_servers($dom,'library');
1.150 raeburn 22316: my @sparestypes = ('primary','default');
22317: my %typetitles = &sparestype_titles();
22318: my $resulttext;
1.342 raeburn 22319: my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
1.171 raeburn 22320: if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
22321: %existing = %{$domconfig{'loadbalancing'}};
22322: }
22323: &get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
1.342 raeburn 22324: \%currtargets,\%currrules,\%currcookies);
1.171 raeburn 22325: my ($saveloadbalancing,%defaultshash,%changes);
22326: my ($alltypes,$othertypes,$titles) =
22327: &loadbalancing_titles($dom,$intdom,$usertypes,$types);
22328: my %ruletitles = &offloadtype_text();
22329: my @deletions = &Apache::loncommon::get_env_multiple('form.loadbalancing_delete');
22330: for (my $i=0; $i<$env{'form.loadbalancing_total'}; $i++) {
22331: my $balancer = $env{'form.loadbalancing_lonhost_'.$i};
22332: if ($balancer eq '') {
22333: next;
22334: }
1.210 raeburn 22335: if (!exists($servers{$balancer})) {
1.171 raeburn 22336: if (exists($currbalancer{$balancer})) {
22337: push(@{$changes{'delete'}},$balancer);
1.150 raeburn 22338: }
1.171 raeburn 22339: next;
22340: }
22341: if ((@deletions > 0) && (grep(/^\Q$i\E$/,@deletions))) {
22342: push(@{$changes{'delete'}},$balancer);
22343: next;
22344: }
22345: if (!exists($currbalancer{$balancer})) {
22346: push(@{$changes{'add'}},$balancer);
22347: }
22348: $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'} = [];
22349: $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'default'} = [];
22350: $defaultshash{'loadbalancing'}{$balancer}{'rules'} = {};
22351: unless (ref($domconfig{'loadbalancing'}) eq 'HASH') {
22352: $saveloadbalancing = 1;
22353: }
22354: foreach my $sparetype (@sparestypes) {
22355: my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$i.'_'.$sparetype);
22356: my @offloadto;
22357: foreach my $target (@targets) {
22358: if (($servers{$target}) && ($target ne $balancer)) {
22359: if ($sparetype eq 'default') {
22360: if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}) eq 'ARRAY') {
22361: next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}}));
1.150 raeburn 22362: }
22363: }
1.171 raeburn 22364: unless(grep(/^\Q$target\E$/,@offloadto)) {
22365: push(@offloadto,$target);
22366: }
1.150 raeburn 22367: }
22368: }
1.284 raeburn 22369: if ($env{'form.loadbalancing_target_'.$i.'_hosthere'} eq $sparetype) {
22370: unless(grep(/^\Q$balancer\E$/,@offloadto)) {
22371: push(@offloadto,$balancer);
22372: }
22373: }
22374: $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
1.150 raeburn 22375: }
1.342 raeburn 22376: if ($env{'form.loadbalancing_cookie_'.$i}) {
22377: $defaultshash{'loadbalancing'}{$balancer}{'cookie'} = 1;
1.425 raeburn 22378: if (exists($currbalancer{$balancer})) {
1.342 raeburn 22379: unless ($currcookies{$balancer}) {
22380: $changes{'curr'}{$balancer}{'cookie'} = 1;
22381: }
22382: }
22383: } elsif (exists($currbalancer{$balancer})) {
22384: if ($currcookies{$balancer}) {
22385: $changes{'curr'}{$balancer}{'cookie'} = 1;
22386: }
22387: }
1.171 raeburn 22388: if (ref($currtargets{$balancer}) eq 'HASH') {
1.150 raeburn 22389: foreach my $sparetype (@sparestypes) {
1.171 raeburn 22390: if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
22391: my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets{$balancer}{$sparetype},$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype});
1.150 raeburn 22392: if (@targetdiffs > 0) {
1.171 raeburn 22393: $changes{'curr'}{$balancer}{'targets'} = 1;
1.150 raeburn 22394: }
1.171 raeburn 22395: } elsif (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
22396: if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
22397: $changes{'curr'}{$balancer}{'targets'} = 1;
1.150 raeburn 22398: }
22399: }
22400: }
22401: } else {
1.171 raeburn 22402: if (ref($defaultshash{'loadbalancing'}{$balancer}) eq 'HASH') {
1.210 raeburn 22403: foreach my $sparetype (@sparestypes) {
1.171 raeburn 22404: if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
22405: if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
22406: $changes{'curr'}{$balancer}{'targets'} = 1;
22407: }
1.150 raeburn 22408: }
22409: }
1.210 raeburn 22410: }
1.150 raeburn 22411: }
22412: my $ishomedom;
1.171 raeburn 22413: if (&Apache::lonnet::host_domain($balancer) eq $dom) {
22414: $ishomedom = 1;
1.150 raeburn 22415: }
22416: if (ref($alltypes) eq 'ARRAY') {
22417: foreach my $type (@{$alltypes}) {
22418: my $rule;
1.210 raeburn 22419: unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) &&
1.150 raeburn 22420: (!$ishomedom)) {
1.171 raeburn 22421: $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type};
22422: }
22423: if ($rule eq 'specific') {
1.255 raeburn 22424: my $specifiedhost = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type};
1.289 raeburn 22425: if (exists($servers{$specifiedhost})) {
1.255 raeburn 22426: $rule = $specifiedhost;
22427: }
1.150 raeburn 22428: }
1.171 raeburn 22429: $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule;
22430: if (ref($currrules{$balancer}) eq 'HASH') {
22431: if ($rule ne $currrules{$balancer}{$type}) {
22432: $changes{'curr'}{$balancer}{'rules'}{$type} = 1;
1.150 raeburn 22433: }
22434: } elsif ($rule ne '') {
1.171 raeburn 22435: $changes{'curr'}{$balancer}{'rules'}{$type} = 1;
1.150 raeburn 22436: }
22437: }
22438: }
1.171 raeburn 22439: }
22440: my $nochgmsg = &mt('No changes made to Load Balancer settings.');
22441: if ((keys(%changes) > 0) || ($saveloadbalancing)) {
22442: unless (ref($defaultshash{'loadbalancing'}) eq 'HASH') {
22443: $defaultshash{'loadbalancing'} = {};
22444: }
22445: my $putresult = &Apache::lonnet::put_dom('configuration',
22446: \%defaultshash,$dom);
22447: if ($putresult eq 'ok') {
22448: if (keys(%changes) > 0) {
1.252 raeburn 22449: my %toupdate;
1.171 raeburn 22450: if (ref($changes{'delete'}) eq 'ARRAY') {
22451: foreach my $balancer (sort(@{$changes{'delete'}})) {
22452: $resulttext .= '<li>'.&mt('Load Balancing discontinued for: [_1]',$balancer).'</li>';
1.252 raeburn 22453: $toupdate{$balancer} = 1;
1.150 raeburn 22454: }
1.171 raeburn 22455: }
22456: if (ref($changes{'add'}) eq 'ARRAY') {
1.210 raeburn 22457: foreach my $balancer (sort(@{$changes{'add'}})) {
1.171 raeburn 22458: $resulttext .= '<li>'.&mt('Load Balancing enabled for: [_1]',$balancer);
1.252 raeburn 22459: $toupdate{$balancer} = 1;
1.171 raeburn 22460: }
22461: }
22462: if (ref($changes{'curr'}) eq 'HASH') {
22463: foreach my $balancer (sort(keys(%{$changes{'curr'}}))) {
1.253 raeburn 22464: $toupdate{$balancer} = 1;
1.171 raeburn 22465: if (ref($changes{'curr'}{$balancer}) eq 'HASH') {
22466: if ($changes{'curr'}{$balancer}{'targets'}) {
22467: my %offloadstr;
22468: foreach my $sparetype (@sparestypes) {
22469: if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
22470: if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) {
22471: $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
22472: }
22473: }
1.150 raeburn 22474: }
1.171 raeburn 22475: if (keys(%offloadstr) == 0) {
22476: $resulttext .= '<li>'.&mt("Servers to which Load Balance server offloads set to 'None', by default").'</li>';
1.150 raeburn 22477: } else {
1.171 raeburn 22478: my $showoffload;
22479: foreach my $sparetype (@sparestypes) {
22480: $showoffload .= '<i>'.$typetitles{$sparetype}.'</i>: ';
22481: if (defined($offloadstr{$sparetype})) {
22482: $showoffload .= $offloadstr{$sparetype};
22483: } else {
22484: $showoffload .= &mt('None');
22485: }
22486: $showoffload .= (' 'x3);
22487: }
22488: $resulttext .= '<li>'.&mt('By default, Load Balancer: [_1] set to offload to - [_2]',$balancer,$showoffload).'</li>';
1.150 raeburn 22489: }
22490: }
22491: }
1.171 raeburn 22492: if (ref($changes{'curr'}{$balancer}{'rules'}) eq 'HASH') {
22493: if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) {
22494: foreach my $type (@{$alltypes}) {
22495: if ($changes{'curr'}{$balancer}{'rules'}{$type}) {
22496: my $rule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};
22497: my $balancetext;
22498: if ($rule eq '') {
22499: $balancetext = $ruletitles{'default'};
1.209 raeburn 22500: } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') ||
1.289 raeburn 22501: ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {
1.254 raeburn 22502: if (($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) {
1.252 raeburn 22503: foreach my $sparetype (@sparestypes) {
22504: if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') {
22505: map { $toupdate{$_} = 1; } (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}});
22506: }
22507: }
1.253 raeburn 22508: foreach my $item (@{$alltypes}) {
22509: next if ($item =~ /^_LC_ipchange/);
22510: my $hasrule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$item};
22511: if ($hasrule eq 'homeserver') {
22512: map { $toupdate{$_} = 1; } (keys(%libraryservers));
22513: } else {
22514: unless (($hasrule eq 'default') || ($hasrule eq 'none') || ($hasrule eq 'externalbalancer')) {
22515: if ($servers{$hasrule}) {
22516: $toupdate{$hasrule} = 1;
22517: }
22518: }
22519: }
22520: }
1.254 raeburn 22521: if (($rule eq 'balancer') || ($rule eq 'offloadedto')) {
22522: $balancetext = $ruletitles{$rule};
22523: } else {
22524: my $receiver = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type};
22525: $balancetext = $ruletitles{'particular'}.' '.$receiver;
22526: if ($receiver) {
22527: $toupdate{$receiver};
22528: }
22529: }
22530: } else {
22531: $balancetext = $ruletitles{$rule};
1.252 raeburn 22532: }
1.171 raeburn 22533: } else {
22534: $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type});
22535: }
1.210 raeburn 22536: $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'</li>';
1.150 raeburn 22537: }
22538: }
22539: }
22540: }
1.342 raeburn 22541: if ($changes{'curr'}{$balancer}{'cookie'}) {
1.389 raeburn 22542: if ($currcookies{$balancer}) {
22543: $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use disabled',
22544: $balancer).'</li>';
22545: } else {
22546: $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use enabled',
22547: $balancer).'</li>';
22548: }
1.342 raeburn 22549: }
1.375 raeburn 22550: }
22551: }
22552: if (keys(%toupdate)) {
22553: my %thismachine;
22554: my $updatedhere;
22555: my $cachetime = 60*60*24;
22556: map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
22557: foreach my $lonhost (keys(%toupdate)) {
22558: if ($thismachine{$lonhost}) {
22559: unless ($updatedhere) {
22560: &Apache::lonnet::do_cache_new('loadbalancing',$dom,
22561: $defaultshash{'loadbalancing'},
22562: $cachetime);
22563: $updatedhere = 1;
1.252 raeburn 22564: }
1.375 raeburn 22565: } else {
22566: my $cachekey = &escape('loadbalancing').':'.&escape($dom);
22567: &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
1.252 raeburn 22568: }
1.150 raeburn 22569: }
1.171 raeburn 22570: }
22571: if ($resulttext ne '') {
22572: $resulttext = &mt('Changes made:').'<ul>'.$resulttext.'</ul>';
1.150 raeburn 22573: } else {
22574: $resulttext = $nochgmsg;
22575: }
22576: } else {
1.171 raeburn 22577: $resulttext = $nochgmsg;
1.150 raeburn 22578: }
22579: } else {
1.171 raeburn 22580: $resulttext = '<span class="LC_error">'.
22581: &mt('An error occurred: [_1]',$putresult).'</span>';
1.150 raeburn 22582: }
22583: } else {
1.171 raeburn 22584: $resulttext = $nochgmsg;
1.150 raeburn 22585: }
22586: return $resulttext;
22587: }
22588:
1.48 raeburn 22589: sub recurse_check {
22590: my ($chkcats,$categories,$depth,$name) = @_;
22591: if (ref($chkcats->[$depth]{$name}) eq 'ARRAY') {
22592: my $chg = 0;
22593: for (my $j=0; $j<@{$chkcats->[$depth]{$name}}; $j++) {
22594: my $category = $chkcats->[$depth]{$name}[$j];
22595: my $item;
22596: if ($category eq '') {
22597: $chg ++;
22598: } else {
22599: my $deeper = $depth + 1;
22600: $item = &escape($category).':'.&escape($name).':'.$depth;
22601: if ($chg) {
22602: $categories->{$item} -= $chg;
22603: }
22604: &recurse_check($chkcats,$categories,$deeper,$category);
22605: $deeper --;
22606: }
22607: }
22608: }
22609: return;
22610: }
22611:
22612: sub recurse_cat_deletes {
22613: my ($item,$coursecategories,$deletions) = @_;
22614: my ($deleted,$container,$depth) = map { &unescape($_); } split(/:/,$item);
22615: my $subdepth = $depth + 1;
22616: if (ref($coursecategories) eq 'HASH') {
22617: foreach my $subitem (keys(%{$coursecategories})) {
22618: my ($child,$parent,$itemdepth) = map { &unescape($_); } split(/:/,$subitem);
22619: if (($parent eq $deleted) && ($itemdepth == $subdepth)) {
22620: delete($coursecategories->{$subitem});
22621: $deletions->{$subitem} = 1;
22622: &recurse_cat_deletes($subitem,$coursecategories,$deletions);
1.168 raeburn 22623: }
1.48 raeburn 22624: }
22625: }
22626: return;
22627: }
22628:
1.125 raeburn 22629: sub active_dc_picker {
1.191 raeburn 22630: my ($dom,$numinrow,$inputtype,$name,%currhash) = @_;
1.287 raeburn 22631: my %domcoords = &Apache::lonnet::get_active_domroles($dom,['dc']);
1.191 raeburn 22632: my @domcoord = keys(%domcoords);
22633: if (keys(%currhash)) {
22634: foreach my $dc (keys(%currhash)) {
22635: unless (exists($domcoords{$dc})) {
22636: push(@domcoord,$dc);
22637: }
22638: }
22639: }
22640: @domcoord = sort(@domcoord);
1.210 raeburn 22641: my $numdcs = scalar(@domcoord);
1.191 raeburn 22642: my $rows = 0;
22643: my $table;
1.125 raeburn 22644: if ($numdcs > 1) {
1.191 raeburn 22645: $table = '<table>';
22646: for (my $i=0; $i<@domcoord; $i++) {
1.125 raeburn 22647: my $rem = $i%($numinrow);
22648: if ($rem == 0) {
22649: if ($i > 0) {
1.191 raeburn 22650: $table .= '</tr>';
1.125 raeburn 22651: }
1.191 raeburn 22652: $table .= '<tr>';
22653: $rows ++;
1.125 raeburn 22654: }
1.191 raeburn 22655: my $check = '';
22656: if ($inputtype eq 'radio') {
22657: if (keys(%currhash) == 0) {
22658: if (!$i) {
22659: $check = ' checked="checked"';
22660: }
22661: } elsif (exists($currhash{$domcoord[$i]})) {
22662: $check = ' checked="checked"';
22663: }
22664: } else {
22665: if (exists($currhash{$domcoord[$i]})) {
22666: $check = ' checked="checked"';
1.125 raeburn 22667: }
22668: }
1.191 raeburn 22669: if ($i == @domcoord - 1) {
1.125 raeburn 22670: my $colsleft = $numinrow - $rem;
22671: if ($colsleft > 1) {
1.191 raeburn 22672: $table .= '<td class="LC_left_item" colspan="'.$colsleft.'">';
1.125 raeburn 22673: } else {
1.191 raeburn 22674: $table .= '<td class="LC_left_item">';
1.125 raeburn 22675: }
22676: } else {
1.191 raeburn 22677: $table .= '<td class="LC_left_item">';
22678: }
22679: my ($dcname,$dcdom) = split(':',$domcoord[$i]);
22680: my $user = &Apache::loncommon::plainname($dcname,$dcdom);
22681: $table .= '<span class="LC_nobreak"><label>'.
22682: '<input type="'.$inputtype.'" name="'.$name.'"'.
22683: ' value="'.$domcoord[$i].'"'.$check.' />'.$user;
22684: if ($user ne $dcname.':'.$dcdom) {
1.219 raeburn 22685: $table .= ' ('.$dcname.':'.$dcdom.')';
1.191 raeburn 22686: }
1.219 raeburn 22687: $table .= '</label></span></td>';
1.191 raeburn 22688: }
22689: $table .= '</tr></table>';
22690: } elsif ($numdcs == 1) {
1.219 raeburn 22691: my ($dcname,$dcdom) = split(':',$domcoord[0]);
22692: my $user = &Apache::loncommon::plainname($dcname,$dcdom);
1.191 raeburn 22693: if ($inputtype eq 'radio') {
1.247 raeburn 22694: $table = '<input type="hidden" name="'.$name.'" value="'.$domcoord[0].'" />'.$user;
1.219 raeburn 22695: if ($user ne $dcname.':'.$dcdom) {
22696: $table .= ' ('.$dcname.':'.$dcdom.')';
22697: }
1.191 raeburn 22698: } else {
22699: my $check;
22700: if (exists($currhash{$domcoord[0]})) {
22701: $check = ' checked="checked"';
1.125 raeburn 22702: }
1.247 raeburn 22703: $table = '<span class="LC_nobreak"><label>'.
22704: '<input type="checkbox" name="'.$name.'" '.
22705: 'value="'.$domcoord[0].'"'.$check.' />'.$user;
1.219 raeburn 22706: if ($user ne $dcname.':'.$dcdom) {
1.220 raeburn 22707: $table .= ' ('.$dcname.':'.$dcdom.')';
1.219 raeburn 22708: }
1.220 raeburn 22709: $table .= '</label></span>';
1.191 raeburn 22710: $rows ++;
1.125 raeburn 22711: }
22712: }
1.191 raeburn 22713: return ($numdcs,$table,$rows);
1.125 raeburn 22714: }
22715:
1.137 raeburn 22716: sub usersession_titles {
22717: return &Apache::lonlocal::texthash(
22718: hosted => 'Hosting of sessions for users from other domains on servers in this domain',
22719: remote => 'Hosting of sessions for users in this domain on servers in other domains',
1.145 raeburn 22720: spares => 'Servers offloaded to, when busy',
1.137 raeburn 22721: version => 'LON-CAPA version requirement',
1.138 raeburn 22722: excludedomain => 'Allow all, but exclude specific domains',
22723: includedomain => 'Deny all, but include specific domains',
1.145 raeburn 22724: primary => 'Primary (checked first)',
1.154 raeburn 22725: default => 'Default',
1.137 raeburn 22726: );
22727: }
22728:
1.152 raeburn 22729: sub id_for_thisdom {
22730: my (%servers) = @_;
22731: my %altids;
22732: foreach my $server (keys(%servers)) {
22733: my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
22734: if ($serverhome ne $server) {
22735: $altids{$serverhome} = $server;
22736: }
22737: }
22738: return %altids;
22739: }
22740:
1.150 raeburn 22741: sub count_servers {
22742: my ($currbalancer,%servers) = @_;
22743: my (@spares,$numspares);
22744: foreach my $lonhost (sort(keys(%servers))) {
22745: next if ($currbalancer eq $lonhost);
22746: push(@spares,$lonhost);
22747: }
22748: if ($currbalancer) {
22749: $numspares = scalar(@spares);
22750: } else {
22751: $numspares = scalar(@spares) - 1;
22752: }
22753: return ($numspares,@spares);
22754: }
22755:
22756: sub lonbalance_targets_js {
1.171 raeburn 22757: my ($dom,$types,$servers,$settings) = @_;
1.150 raeburn 22758: my $select = &mt('Select');
22759: my ($alltargets,$allishome,$allinsttypes,@alltypes);
22760: if (ref($servers) eq 'HASH') {
22761: $alltargets = join("','",sort(keys(%{$servers})));
22762: my @homedoms;
22763: foreach my $server (sort(keys(%{$servers}))) {
22764: if (&Apache::lonnet::host_domain($server) eq $dom) {
22765: push(@homedoms,'1');
22766: } else {
22767: push(@homedoms,'0');
22768: }
22769: }
22770: $allishome = join("','",@homedoms);
22771: }
22772: if (ref($types) eq 'ARRAY') {
22773: if (@{$types} > 0) {
22774: @alltypes = @{$types};
22775: }
22776: }
22777: push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
22778: $allinsttypes = join("','",@alltypes);
1.342 raeburn 22779: my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
1.171 raeburn 22780: if (ref($settings) eq 'HASH') {
22781: %existing = %{$settings};
22782: }
22783: &get_loadbalancers_config($servers,\%existing,\%currbalancer,
1.342 raeburn 22784: \%currtargets,\%currrules,\%currcookies);
1.210 raeburn 22785: my $balancers = join("','",sort(keys(%currbalancer)));
1.150 raeburn 22786: return <<"END";
22787:
22788: <script type="text/javascript">
22789: // <![CDATA[
22790:
1.171 raeburn 22791: currBalancers = new Array('$balancers');
22792:
22793: function toggleTargets(balnum) {
22794: var lonhostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
22795: var prevhostitem = document.getElementById('loadbalancing_prevlonhost_'+balnum);
22796: var balancer = lonhostitem.options[lonhostitem.selectedIndex].value;
22797: var prevbalancer = prevhostitem.value;
22798: var baltotal = document.getElementById('loadbalancing_total').value;
22799: prevhostitem.value = balancer;
22800: if (prevbalancer != '') {
22801: var prevIdx = currBalancers.indexOf(prevbalancer);
22802: if (prevIdx != -1) {
22803: currBalancers.splice(prevIdx,1);
22804: }
22805: }
1.150 raeburn 22806: if (balancer == '') {
1.171 raeburn 22807: hideSpares(balnum);
1.150 raeburn 22808: } else {
1.171 raeburn 22809: var currIdx = currBalancers.indexOf(balancer);
22810: if (currIdx == -1) {
22811: currBalancers.push(balancer);
22812: }
1.150 raeburn 22813: var homedoms = new Array('$allishome');
1.171 raeburn 22814: var ishomedom = homedoms[lonhostitem.selectedIndex];
22815: showSpares(balancer,ishomedom,balnum);
1.150 raeburn 22816: }
1.171 raeburn 22817: balancerChange(balnum,baltotal,'change',prevbalancer,balancer);
1.150 raeburn 22818: return;
22819: }
22820:
1.171 raeburn 22821: function showSpares(balancer,ishomedom,balnum) {
1.150 raeburn 22822: var alltargets = new Array('$alltargets');
22823: var insttypes = new Array('$allinsttypes');
1.151 raeburn 22824: var offloadtypes = new Array('primary','default');
22825:
1.171 raeburn 22826: document.getElementById('loadbalancing_targets_'+balnum).style.display='block';
22827: document.getElementById('loadbalancing_disabled_'+balnum).style.display='none';
1.152 raeburn 22828:
1.151 raeburn 22829: for (var i=0; i<offloadtypes.length; i++) {
22830: var count = 0;
22831: for (var j=0; j<alltargets.length; j++) {
22832: if (alltargets[j] != balancer) {
1.171 raeburn 22833: var item = document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+count);
22834: item.value = alltargets[j];
22835: item.style.textAlign='left';
22836: item.style.textFace='normal';
22837: document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+count).innerHTML = alltargets[j];
22838: if (currBalancers.indexOf(alltargets[j]) == -1) {
22839: item.disabled = '';
22840: } else {
22841: item.disabled = 'disabled';
22842: item.checked = false;
22843: }
1.151 raeburn 22844: count ++;
22845: }
1.150 raeburn 22846: }
22847: }
1.151 raeburn 22848: for (var k=0; k<insttypes.length; k++) {
22849: if ((insttypes[k] == '_LC_external') || (insttypes[k] == '_LC_internetdom')) {
1.150 raeburn 22850: if (ishomedom == 1) {
1.171 raeburn 22851: document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
22852: document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
1.150 raeburn 22853: } else {
1.171 raeburn 22854: document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
22855: document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
1.150 raeburn 22856: }
22857: } else {
1.171 raeburn 22858: document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='block';
22859: document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='block';
1.150 raeburn 22860: }
1.151 raeburn 22861: if ((insttypes[k] != '_LC_external') &&
22862: ((insttypes[k] != '_LC_internetdom') ||
22863: ((insttypes[k] == '_LC_internetdom') && (ishomedom == 1)))) {
1.171 raeburn 22864: var item = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]);
22865: item.options.length = 0;
22866: item.options[0] = new Option("","",true,true);
1.210 raeburn 22867: var idx = 0;
1.151 raeburn 22868: for (var m=0; m<alltargets.length; m++) {
1.171 raeburn 22869: if ((currBalancers.indexOf(alltargets[m]) == -1) && (alltargets[m] != balancer)) {
22870: idx ++;
22871: item.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
1.150 raeburn 22872: }
22873: }
22874: }
22875: }
22876: return;
22877: }
22878:
1.171 raeburn 22879: function hideSpares(balnum) {
1.150 raeburn 22880: var alltargets = new Array('$alltargets');
22881: var insttypes = new Array('$allinsttypes');
22882: var offloadtypes = new Array('primary','default');
22883:
1.171 raeburn 22884: document.getElementById('loadbalancing_targets_'+balnum).style.display='none';
22885: document.getElementById('loadbalancing_disabled_'+balnum).style.display='block';
1.150 raeburn 22886:
22887: var total = alltargets.length - 1;
22888: for (var i=0; i<offloadtypes; i++) {
22889: for (var j=0; j<total; j++) {
1.171 raeburn 22890: document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).checked = false;
22891: document.getElementById('loadbalancing_target_'+balnum+'_'+offloadtypes[i]+'_'+j).value = '';
22892: document.getElementById('loadbalancing_targettxt_'+balnum+'_'+offloadtypes[i]+'_'+j).innerHTML = '';
1.151 raeburn 22893: }
1.150 raeburn 22894: }
22895: for (var k=0; k<insttypes.length; k++) {
1.171 raeburn 22896: document.getElementById('balanceruletitle_'+balnum+'_'+insttypes[k]).style.display='none';
22897: document.getElementById('balancerule_'+balnum+'_'+insttypes[k]).style.display='none';
1.151 raeburn 22898: if (insttypes[k] != '_LC_external') {
1.171 raeburn 22899: document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).length = 0;
22900: document.getElementById('loadbalancing_singleserver_'+balnum+'_'+insttypes[k]).options[0] = new Option("","",true,true);
1.150 raeburn 22901: }
22902: }
22903: return;
22904: }
22905:
1.171 raeburn 22906: function checkOffloads(item,balnum,type) {
1.150 raeburn 22907: var alltargets = new Array('$alltargets');
22908: var offloadtypes = new Array('primary','default');
22909: if (item.checked) {
22910: var total = alltargets.length - 1;
22911: var other;
22912: if (type == offloadtypes[0]) {
1.151 raeburn 22913: other = offloadtypes[1];
1.150 raeburn 22914: } else {
1.151 raeburn 22915: other = offloadtypes[0];
1.150 raeburn 22916: }
22917: for (var i=0; i<total; i++) {
1.171 raeburn 22918: var server = document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).value;
1.150 raeburn 22919: if (server == item.value) {
1.171 raeburn 22920: if (document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked) {
22921: document.getElementById('loadbalancing_target_'+balnum+'_'+other+'_'+i).checked = false;
1.150 raeburn 22922: }
22923: }
22924: }
22925: }
22926: return;
22927: }
22928:
1.171 raeburn 22929: function singleServerToggle(balnum,type) {
22930: var offloadtoSelIdx = document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex;
1.150 raeburn 22931: if (offloadtoSelIdx == 0) {
1.171 raeburn 22932: document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_0').checked = true;
22933: document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
1.150 raeburn 22934:
22935: } else {
1.171 raeburn 22936: document.getElementById('loadbalancing_rules_'+balnum+'_'+type+'_2').checked = true;
22937: document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
1.150 raeburn 22938: }
22939: return;
22940: }
22941:
1.171 raeburn 22942: function balanceruleChange(formname,balnum,type) {
1.150 raeburn 22943: if (type == '_LC_external') {
1.171 raeburn 22944: return;
1.150 raeburn 22945: }
1.171 raeburn 22946: var typesRules = getIndicesByName(formname,'loadbalancing_rules_'+balnum+'_'+type);
1.150 raeburn 22947: for (var i=0; i<typesRules.length; i++) {
22948: if (formname.elements[typesRules[i]].checked) {
22949: if (formname.elements[typesRules[i]].value != 'specific') {
1.171 raeburn 22950: document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).selectedIndex = 0;
22951: document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '';
1.150 raeburn 22952: } else {
1.171 raeburn 22953: document.getElementById('loadbalancing_singleserver_'+balnum+'_'+type).options[0].text = '$select';
22954: }
22955: }
22956: }
22957: return;
22958: }
22959:
22960: function balancerDeleteChange(balnum) {
22961: var hostitem = document.getElementById('loadbalancing_lonhost_'+balnum);
22962: var baltotal = document.getElementById('loadbalancing_total').value;
22963: var addtarget;
22964: var removetarget;
22965: var action = 'delete';
22966: if (document.getElementById('loadbalancing_delete_'+balnum)) {
22967: var lonhost = hostitem.value;
22968: var currIdx = currBalancers.indexOf(lonhost);
22969: if (document.getElementById('loadbalancing_delete_'+balnum).checked) {
22970: if (currIdx != -1) {
22971: currBalancers.splice(currIdx,1);
22972: }
22973: addtarget = lonhost;
22974: } else {
22975: if (currIdx == -1) {
22976: currBalancers.push(lonhost);
22977: }
22978: removetarget = lonhost;
22979: action = 'undelete';
22980: }
22981: balancerChange(balnum,baltotal,action,addtarget,removetarget);
22982: }
22983: return;
22984: }
22985:
22986: function balancerChange(balnum,baltotal,action,addtarget,removetarget) {
22987: if (baltotal > 1) {
22988: var offloadtypes = new Array('primary','default');
22989: var alltargets = new Array('$alltargets');
22990: var insttypes = new Array('$allinsttypes');
22991: for (var i=0; i<baltotal; i++) {
22992: if (i != balnum) {
22993: for (var j=0; j<offloadtypes.length; j++) {
22994: var total = alltargets.length - 1;
22995: for (var k=0; k<total; k++) {
22996: var serveritem = document.getElementById('loadbalancing_target_'+i+'_'+offloadtypes[j]+'_'+k);
22997: var server = serveritem.value;
22998: if ((action == 'delete') || (action == 'change' && addtarget != '')) {
22999: if (server == addtarget) {
23000: serveritem.disabled = '';
23001: }
23002: }
23003: if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
23004: if (server == removetarget) {
23005: serveritem.disabled = 'disabled';
23006: serveritem.checked = false;
23007: }
23008: }
23009: }
23010: }
23011: for (var j=0; j<insttypes.length; j++) {
23012: if (insttypes[j] != '_LC_external') {
23013: if (document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j])) {
23014: var singleserver = document.getElementById('loadbalancing_singleserver_'+i+'_'+insttypes[j]);
23015: var currSel = singleserver.selectedIndex;
23016: var currVal = singleserver.options[currSel].value;
23017: if ((action == 'delete') || (action == 'change' && addtarget != '')) {
23018: var numoptions = singleserver.options.length;
23019: var needsnew = 1;
23020: for (var k=0; k<numoptions; k++) {
23021: if (singleserver.options[k] == addtarget) {
23022: needsnew = 0;
23023: break;
23024: }
23025: }
23026: if (needsnew == 1) {
23027: singleserver.options[numoptions] = new Option(addtarget,addtarget,false,false);
23028: }
23029: }
23030: if ((action == 'undelete') || (action == 'change' && removetarget != '')) {
23031: singleserver.options.length = 0;
23032: if ((currVal) && (currVal != removetarget)) {
23033: singleserver.options[0] = new Option("","",false,false);
23034: } else {
23035: singleserver.options[0] = new Option("","",true,true);
23036: }
23037: var idx = 0;
23038: for (var m=0; m<alltargets.length; m++) {
23039: if (currBalancers.indexOf(alltargets[m]) == -1) {
23040: idx ++;
23041: if (currVal == alltargets[m]) {
23042: singleserver.options[idx] = new Option(alltargets[m],alltargets[m],true,true);
23043: } else {
23044: singleserver.options[idx] = new Option(alltargets[m],alltargets[m],false,false);
23045: }
23046: }
23047: }
23048: }
23049: }
23050: }
23051: }
1.150 raeburn 23052: }
23053: }
23054: }
23055: return;
23056: }
23057:
1.152 raeburn 23058: // ]]>
23059: </script>
23060:
23061: END
23062: }
23063:
23064: sub new_spares_js {
23065: my @sparestypes = ('primary','default');
23066: my $types = join("','",@sparestypes);
23067: my $select = &mt('Select');
23068: return <<"END";
23069:
23070: <script type="text/javascript">
23071: // <![CDATA[
23072:
23073: function updateNewSpares(formname,lonhost) {
23074: var types = new Array('$types');
23075: var include = new Array();
23076: var exclude = new Array();
23077: for (var i=0; i<types.length; i++) {
23078: var spareboxes = getIndicesByName(formname,'spare_'+types[i]+'_'+lonhost);
23079: for (var j=0; j<spareboxes.length; j++) {
23080: if (formname.elements[spareboxes[j]].checked) {
23081: exclude.push(formname.elements[spareboxes[j]].value);
23082: } else {
23083: include.push(formname.elements[spareboxes[j]].value);
23084: }
23085: }
23086: }
23087: for (var i=0; i<types.length; i++) {
23088: var newSpare = document.getElementById('newspare_'+types[i]+'_'+lonhost);
23089: var selIdx = newSpare.selectedIndex;
23090: var currnew = newSpare.options[selIdx].value;
23091: var okSpares = new Array();
23092: for (var j=0; j<newSpare.options.length; j++) {
23093: var possible = newSpare.options[j].value;
23094: if (possible != '') {
23095: if (exclude.indexOf(possible) == -1) {
23096: okSpares.push(possible);
23097: } else {
23098: if (currnew == possible) {
23099: selIdx = 0;
23100: }
23101: }
23102: }
23103: }
23104: for (var k=0; k<include.length; k++) {
23105: if (okSpares.indexOf(include[k]) == -1) {
23106: okSpares.push(include[k]);
23107: }
23108: }
23109: okSpares.sort();
23110: newSpare.options.length = 0;
23111: if (selIdx == 0) {
23112: newSpare.options[0] = new Option("$select","",true,true);
23113: } else {
23114: newSpare.options[0] = new Option("$select","",false,false);
23115: }
23116: for (var m=0; m<okSpares.length; m++) {
23117: var idx = m+1;
23118: var selThis = 0;
23119: if (selIdx != 0) {
23120: if (okSpares[m] == currnew) {
23121: selThis = 1;
23122: }
23123: }
23124: if (selThis == 1) {
23125: newSpare.options[idx] = new Option(okSpares[m],okSpares[m],true,true);
23126: } else {
23127: newSpare.options[idx] = new Option(okSpares[m],okSpares[m],false,false);
23128: }
23129: }
23130: }
23131: return;
23132: }
23133:
23134: function checkNewSpares(lonhost,type) {
23135: var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);
23136: var chosen = newSpare.options[newSpare.selectedIndex].value;
1.372 raeburn 23137: if (chosen != '') {
1.152 raeburn 23138: var othertype;
23139: var othernewSpare;
23140: if (type == 'primary') {
23141: othernewSpare = document.getElementById('newspare_default_'+lonhost);
23142: }
23143: if (type == 'default') {
23144: othernewSpare = document.getElementById('newspare_primary_'+lonhost);
23145: }
23146: if (othernewSpare.options[othernewSpare.selectedIndex].value == chosen) {
23147: othernewSpare.selectedIndex = 0;
23148: }
23149: }
23150: return;
23151: }
23152:
23153: // ]]>
23154: </script>
23155:
23156: END
23157:
23158: }
23159:
23160: sub common_domprefs_js {
23161: return <<"END";
23162:
23163: <script type="text/javascript">
23164: // <![CDATA[
23165:
1.150 raeburn 23166: function getIndicesByName(formname,item) {
1.152 raeburn 23167: var group = new Array();
1.150 raeburn 23168: for (var i=0;i<formname.elements.length;i++) {
23169: if (formname.elements[i].name == item) {
1.152 raeburn 23170: group.push(formname.elements[i].id);
1.150 raeburn 23171: }
23172: }
1.152 raeburn 23173: return group;
1.150 raeburn 23174: }
23175:
23176: // ]]>
23177: </script>
23178:
23179: END
1.152 raeburn 23180:
1.150 raeburn 23181: }
23182:
1.165 raeburn 23183: sub recaptcha_js {
23184: my %lt = &captcha_phrases();
23185: return <<"END";
23186:
23187: <script type="text/javascript">
23188: // <![CDATA[
23189:
23190: function updateCaptcha(caller,context) {
23191: var privitem;
23192: var pubitem;
23193: var privtext;
23194: var pubtext;
1.269 raeburn 23195: var versionitem;
23196: var versiontext;
1.165 raeburn 23197: if (document.getElementById(context+'_recaptchapub')) {
23198: pubitem = document.getElementById(context+'_recaptchapub');
23199: } else {
23200: return;
23201: }
23202: if (document.getElementById(context+'_recaptchapriv')) {
23203: privitem = document.getElementById(context+'_recaptchapriv');
23204: } else {
23205: return;
23206: }
23207: if (document.getElementById(context+'_recaptchapubtxt')) {
23208: pubtext = document.getElementById(context+'_recaptchapubtxt');
23209: } else {
23210: return;
23211: }
23212: if (document.getElementById(context+'_recaptchaprivtxt')) {
23213: privtext = document.getElementById(context+'_recaptchaprivtxt');
23214: } else {
23215: return;
23216: }
1.269 raeburn 23217: if (document.getElementById(context+'_recaptchaversion')) {
23218: versionitem = document.getElementById(context+'_recaptchaversion');
23219: } else {
23220: return;
23221: }
23222: if (document.getElementById(context+'_recaptchavertxt')) {
23223: versiontext = document.getElementById(context+'_recaptchavertxt');
23224: } else {
23225: return;
23226: }
1.165 raeburn 23227: if (caller.checked) {
23228: if (caller.value == 'recaptcha') {
23229: pubitem.type = 'text';
23230: privitem.type = 'text';
23231: pubitem.size = '40';
23232: privitem.size = '40';
23233: pubtext.innerHTML = "$lt{'pub'}";
23234: privtext.innerHTML = "$lt{'priv'}";
1.269 raeburn 23235: versionitem.type = 'text';
23236: versionitem.size = '3';
1.289 raeburn 23237: versiontext.innerHTML = "$lt{'ver'}";
1.165 raeburn 23238: } else {
23239: pubitem.type = 'hidden';
23240: privitem.type = 'hidden';
1.269 raeburn 23241: versionitem.type = 'hidden';
1.165 raeburn 23242: pubtext.innerHTML = '';
23243: privtext.innerHTML = '';
1.269 raeburn 23244: versiontext.innerHTML = '';
1.165 raeburn 23245: }
23246: }
23247: return;
23248: }
23249:
23250: // ]]>
23251: </script>
23252:
23253: END
23254:
23255: }
23256:
1.236 raeburn 23257: sub toggle_display_js {
1.192 raeburn 23258: return <<"END";
23259:
23260: <script type="text/javascript">
23261: // <![CDATA[
23262:
1.236 raeburn 23263: function toggleDisplay(domForm,caller) {
23264: if (document.getElementById(caller)) {
23265: var divitem = document.getElementById(caller);
23266: var optionsElement = domForm.coursecredits;
1.264 raeburn 23267: var checkval = 1;
23268: var dispval = 'block';
1.303 raeburn 23269: var selfcreateRegExp = /^cancreate_emailverified/;
1.236 raeburn 23270: if (caller == 'emailoptions') {
1.372 raeburn 23271: optionsElement = domForm.cancreate_email;
1.236 raeburn 23272: }
1.257 raeburn 23273: if (caller == 'studentsubmission') {
23274: optionsElement = domForm.postsubmit;
23275: }
1.264 raeburn 23276: if (caller == 'cloneinstcode') {
23277: optionsElement = domForm.canclone;
23278: checkval = 'instcode';
23279: }
1.303 raeburn 23280: if (selfcreateRegExp.test(caller)) {
23281: optionsElement = domForm.elements[caller];
23282: checkval = 'other';
23283: dispval = 'inline'
23284: }
1.236 raeburn 23285: if (optionsElement.length) {
1.192 raeburn 23286: var currval;
1.236 raeburn 23287: for (var i=0; i<optionsElement.length; i++) {
23288: if (optionsElement[i].checked) {
23289: currval = optionsElement[i].value;
1.192 raeburn 23290: }
23291: }
1.264 raeburn 23292: if (currval == checkval) {
23293: divitem.style.display = dispval;
1.192 raeburn 23294: } else {
1.236 raeburn 23295: divitem.style.display = 'none';
1.192 raeburn 23296: }
23297: }
23298: }
23299: return;
23300: }
23301:
23302: // ]]>
23303: </script>
23304:
23305: END
23306:
23307: }
23308:
1.165 raeburn 23309: sub captcha_phrases {
23310: return &Apache::lonlocal::texthash (
23311: priv => 'Private key',
23312: pub => 'Public key',
23313: original => 'original (CAPTCHA)',
23314: recaptcha => 'successor (ReCAPTCHA)',
23315: notused => 'unused',
1.289 raeburn 23316: ver => 'ReCAPTCHA version (1 or 2)',
1.165 raeburn 23317: );
23318: }
23319:
1.205 raeburn 23320: sub devalidate_remote_domconfs {
1.212 raeburn 23321: my ($dom,$cachekeys) = @_;
23322: return unless (ref($cachekeys) eq 'HASH');
1.205 raeburn 23323: my %servers = &Apache::lonnet::internet_dom_servers($dom);
23324: my %thismachine;
23325: map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
1.355 raeburn 23326: my @posscached = ('domainconfig','domdefaults','ltitools','usersessions',
1.394 raeburn 23327: 'directorysrch','passwdconf','cats','proxyalias','proxysaml',
1.410 raeburn 23328: 'ipaccess','trust');
1.386 raeburn 23329: my %cache_by_lonhost;
23330: if (exists($cachekeys->{'samllanding'})) {
23331: if (ref($cachekeys->{'samllanding'}) eq 'HASH') {
23332: my %landing = %{$cachekeys->{'samllanding'}};
23333: my %domservers = &Apache::lonnet::get_servers($dom);
23334: if (keys(%domservers)) {
23335: foreach my $server (keys(%domservers)) {
23336: my @cached;
23337: next if ($thismachine{$server});
23338: if ($landing{$server}) {
23339: push(@cached,&escape('samllanding').':'.&escape($server));
23340: }
23341: if (@cached) {
23342: $cache_by_lonhost{$server} = \@cached;
23343: }
23344: }
23345: }
23346: }
23347: }
1.260 raeburn 23348: if (keys(%servers)) {
1.205 raeburn 23349: foreach my $server (keys(%servers)) {
23350: next if ($thismachine{$server});
1.212 raeburn 23351: my @cached;
23352: foreach my $name (@posscached) {
23353: if ($cachekeys->{$name}) {
1.388 raeburn 23354: if (($name eq 'proxyalias') || ($name eq 'proxysaml')) {
1.386 raeburn 23355: if (ref($cachekeys->{$name}) eq 'HASH') {
1.373 raeburn 23356: foreach my $key (keys(%{$cachekeys->{$name}})) {
23357: push(@cached,&escape($name).':'.&escape($key));
23358: }
23359: }
23360: } else {
23361: push(@cached,&escape($name).':'.&escape($dom));
23362: }
1.212 raeburn 23363: }
23364: }
1.386 raeburn 23365: if ((exists($cache_by_lonhost{$server})) &&
23366: (ref($cache_by_lonhost{$server}) eq 'ARRAY')) {
23367: push(@cached,@{$cache_by_lonhost{$server}});
23368: }
1.212 raeburn 23369: if (@cached) {
23370: &Apache::lonnet::remote_devalidate_cache($server,\@cached);
23371: }
1.205 raeburn 23372: }
23373: }
23374: return;
23375: }
23376:
1.3 raeburn 23377: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>