--- loncom/interface/loncommon.pm 2007/08/28 15:55:49 1.571 +++ loncom/interface/loncommon.pm 2007/11/06 02:23:49 1.608 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.571 2007/08/28 15:55:49 raeburn Exp $ +# $Id: loncommon.pm,v 1.608 2007/11/06 02:23:49 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -367,7 +367,7 @@ sub selectstudent_link { return ''; } return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele. - '","'.$udomele.'","","1");'."'>".&mt('Select User')."</a>"; + '","'.$udomele.'");'."'>".&mt('Select User')."</a>"; } if ($env{'request.role'}=~/^(au|dc|su)/) { return "<a href='".'javascript:openstdbrowser("'.$form.'","'.$unameele. @@ -407,7 +407,7 @@ sub coursebrowser_javascript { '&cdomelement='+udom+ '&cnameelement='+desc; if (extra_element !=null && extra_element != '') { - if (formname == 'rolechoice') { + if (formname == 'rolechoice' || formname == 'studentform') { url += '&roleelement='+extra_element; if (domainfilter == null || domainfilter == '') { url += '&domainfilter='+extra_element; @@ -721,24 +721,20 @@ sub help_open_topic { my $template = ""; my $link; - + $topic=~s/\W/\_/g; - if (!$stayOnPage) - { + if (!$stayOnPage) { $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))"; - } - else - { + } else { $link = "/adm/help/${filename}.hlp"; } # Add the text - if ($text ne "") - { + if ($text ne "") { $template .= - "<table bgcolor='#3333AA' cellspacing='1' cellpadding='1' border='0'><tr>". - "<td bgcolor='#5555FF'><a target=\"_top\" href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>"; + "<table bgcolor='#3333AA' cellspacing='1' cellpadding='1' border='0'><tr>". + "<td bgcolor='#5555FF'><a target=\"_top\" href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>"; } # Add the graphic @@ -805,14 +801,10 @@ sub help_open_menu { my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text) = @_; $stayOnPage = 0 if (not defined $stayOnPage); - # formerly only used pop-up help (stayOnPage = 0) + # only use pop-up help (stayOnPage == 0) # if environment.remote is on (using remote control UI) - # if ($env{'browser.interface'} eq 'textual' || - # $env{'environment.remote'} eq 'off' ) { - # $stayOnPage=1; - #} - # Now making pop-up help the default even with remote control - if ($env{'browser.interface'} eq 'textual') { + if ($env{'browser.interface'} eq 'textual' || + $env{'environment.remote'} eq 'off' ) { $stayOnPage=1; } my $output; @@ -834,15 +826,13 @@ sub help_open_menu { sub top_nav_help { my ($text) = @_; - $text = &mt($text); - - my $stayOnPage = + my $stay_on_page = ($env{'browser.interface'} eq 'textual' || $env{'environment.remote'} eq 'off' ); - my $link= ($stayOnPage) ? "javascript:helpMenu('display')" + my $link = ($stay_on_page) ? "javascript:helpMenu('display')" : "javascript:helpMenu('open')"; - my $banner_link = &update_help_link(undef,undef,undef,undef,$stayOnPage); + my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page); my $title = &mt('Get help'); @@ -870,7 +860,7 @@ sub help_menu_js { 'js_ready' => 1, 'add_entries' => { 'border' => '0', - 'rows' => "105,*",},}); + 'rows' => "110,*",},}); my $end_page = &Apache::loncommon::end_page({'frameset' => 1, 'js_ready' => 1,}); @@ -1084,6 +1074,77 @@ sub changable_area { =pod +=item * viewport_geometry_js { + +Provides javascript object (Geometry) which can provide information about the viewport geometry for the client browser. + +=cut + + +sub viewport_geometry_js { + return <<"GEOMETRY"; +var Geometry = {}; +function init_geometry() { + if (Geometry.init) { return }; + Geometry.init=1; + if (window.innerHeight) { + Geometry.getViewportHeight = function() { return window.innerHeight; }; + Geometry.getViewportWidth = function() { return window.innerWidth; }; + Geometry.getHorizontalScroll = function() { return window.pageXOffset; }; + Geometry.getVerticalScroll = function() { return window.pageYOffset; }; + } + else if (document.documentElement && document.documentElement.clientHeight) { + Geometry.getViewportHeight = + function() { return document.documentElement.clientHeight; }; + Geometry.getViewportWidth = + function() { return document.documentElement.clientWidth; }; + + Geometry.getHorizontalScroll = + function() { return document.documentElement.scrollLeft; }; + Geometry.getVerticalScroll = + function() { return document.documentElement.scrollTop; }; + } + else if (document.body.clientHeight) { + Geometry.getViewportHeight = + function() { return document.body.clientHeight; }; + Geometry.getViewportWidth = + function() { return document.body.clientWidth; }; + Geometry.getHorizontalScroll = + function() { return document.body.scrollLeft; }; + Geometry.getVerticalScroll = + function() { return document.body.scrollTop; }; + } +} + +GEOMETRY +} + +=pod + +=item * viewport_size_js { + +Provides a javascript function to set values of two form elements - width and height (elements are passed in as arguments to the javascript function) to the dimensions of the user's browser window. + +=cut + +sub viewport_size_js { + my $geometry = &viewport_geometry_js(); + return <<"DIMS"; + +$geometry + +function getViewportDims(width,height) { + init_geometry(); + width.value = Geometry.getViewportWidth(); + height.value = Geometry.getViewportHeight(); + return; +} + +DIMS +} + +=pod + =item * resize_textarea_js emits the needed javascript to resize a textarea to be as big as possible @@ -1097,37 +1158,41 @@ to be attached to the <body> for the onl =cut sub resize_textarea_js { + my $geometry = &viewport_geometry_js(); return <<"RESIZE"; <script type="text/javascript"> -var Geometry = {}; -function init_geometry() { - if (Geometry.init) { return }; - Geometry.init=1; - if (window.innerHeight) { - Geometry.getViewportHeight = function() { return window.innerHeight; }; - } - else if (document.documentElement && document.documentElement.clientHeight) { - Geometry.getViewportHeight = - function() { return document.documentElement.clientHeight; }; - } - else if (document.body.clientHeight) { - Geometry.getViewportHeight = - function() { return document.body.clientHeight; }; +$geometry + +function getX(element) { + var x = 0; + while (element) { + x += element.offsetLeft; + element = element.offsetParent; + } + return x; +} +function getY(element) { + var y = 0; + while (element) { + y += element.offsetTop; + element = element.offsetParent; } + return y; } + function resize_textarea(textarea_id,bottom_id) { init_geometry(); var textarea = document.getElementById(textarea_id); //alert(textarea); - var textarea_top = textarea.offsetTop; + var textarea_top = getY(textarea); var textarea_height = textarea.offsetHeight; var bottom = document.getElementById(bottom_id); - var bottom_top = bottom.offsetTop; + var bottom_top = getY(bottom); var bottom_height = bottom.offsetHeight; var window_height = Geometry.getViewportHeight(); - var fudge = 23; + var fudge = 23; var new_height = window_height-fudge-textarea_top-bottom_height; if (new_height < 300) { new_height = 300; @@ -1342,8 +1407,6 @@ sub domain_select { =over 4 -=cut - =item * multiple_select_form($name,$value,$size,$hash,$order) Returns a string containing a <select> element int multiple mode @@ -1521,24 +1584,68 @@ sub select_dom_form { =pod -=item * home_server_option_list($domain) +=item * home_server_form_item($domain,$name,$defaultflag) + +input: 4 arguments (two required, two optional) - + $domain - domain of new user + $name - name of form element + $default - Value of 'default' causes a default item to be first + option, and selected by default. + $hide - Value of 'hide' causes hiding of the name of the server, + if 1 server found, or default, if 0 found. +output: returns 2 items: +(a) form element which contains either: + (i) <select name="$name"> + <option value="$hostid1">$hostid $servers{$hostid}</option> + <option value="$hostid2">$hostid $servers{$hostid}</option> + </select> + form item if there are multiple library servers in $domain, or + (ii) an <input type="hidden" name="$name" value="$hostid" /> form item + if there is only one library server in $domain. -returns a string which contains an <option> list to be used in a -<select> form input. See loncreateuser.pm for an example. +(b) number of library servers found. + +See loncreateuser.pm for example of use. =cut #------------------------------------------- -sub home_server_option_list { - my $domain = shift; +sub home_server_form_item { + my ($domain,$name,$default,$hide) = @_; my %servers = &Apache::lonnet::get_servers($domain,'library'); - my $result = ''; - foreach my $hostid (sort(keys(%servers))) { - $result.= - '<option value="'.$hostid.'">'. - $hostid.' '.$servers{$hostid}."</option>\n"; + my $result; + my $numlib = keys(%servers); + if ($numlib > 1) { + $result .= '<select name="'.$name.'" />'."\n"; + if ($default) { + $result .= '<option value="default" selected>'.&mt('default'). + '</option>'."\n"; + } + foreach my $hostid (sort(keys(%servers))) { + $result.= '<option value="'.$hostid.'">'. + $hostid.' '.$servers{$hostid}."</option>\n"; + } + $result .= '</select>'."\n"; + } elsif ($numlib == 1) { + my $hostid; + foreach my $item (keys(%servers)) { + $hostid = $item; + } + $result .= '<input type="hidden" name="'.$name.'" value="'. + $hostid.'" />'; + if (!$hide) { + $result .= $hostid.' '.$servers{$hostid}; + } + $result .= "\n"; + } elsif ($default) { + $result .= '<input type="hidden" name="'.$name. + '" value="default" />'; + if (!$hide) { + $result .= &mt('default'); + } + $result .= "\n"; } - return $result; + return ($result,$numlib); } =pod @@ -1691,19 +1798,16 @@ END } my $radioval = "'nochange'"; - if (exists($in{'curr_authtype'}) && - defined($in{'curr_authtype'}) && - $in{'curr_authtype'} ne '') { - $radioval = "'$in{'curr_authtype'}arg'"; + if (defined($in{'curr_authtype'})) { + if ($in{'curr_authtype'} ne '') { + $radioval = "'".$in{'curr_authtype'}."arg'"; + } } my $argfield = 'null'; - if ( grep/^mode$/,(keys %in) ) { + if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { - if ( grep/^curr_authtype$/,(keys %in) ) { - $radioval = "'$in{'curr_authtype'}'"; - } - if ( grep/^curr_autharg$/,(keys %in) ) { - unless ($in{'curr_autharg'} eq '') { + if (defined($in{'curr_autharg'})) { + if ($in{'curr_autharg'} ne '') { $argfield = "'$in{'curr_autharg'}'"; } } @@ -1786,79 +1890,170 @@ sub authform_nochange{ kerb_def_dom => 'MSU.EDU', @_, ); - my $result = '<label>'.&mt('[_1] Do not change login data', - '<input type="radio" name="login" value="nochange" '. - 'checked="checked" onclick="'. + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + my $result; + if (keys(%can_assign) == 0) { + $result = &mt('Under you current role you are not permitted to change login settings for this user'); + } else { + $result = '<label>'.&mt('[_1] Do not change login data', + '<input type="radio" name="login" value="nochange" '. + 'checked="checked" onclick="'. "javascript:changed_radio('nochange',$in{'formname'});".'" />'). '</label>'; + } return $result; } -sub authform_kerberos{ +sub authform_kerberos { my %in = ( formname => 'document.cu', kerb_def_dom => 'MSU.EDU', kerb_def_auth => 'krb4', @_, ); - my ($check4,$check5,$krbarg); + my ($check4,$check5,$krbcheck,$krbarg,$krbver,$result,$authtype, + $autharg,$jscall); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); if ($in{'kerb_def_auth'} eq 'krb5') { - $check5 = " checked=\"on\""; + $check5 = ' checked="on"'; } else { - $check4 = " checked=\"on\""; + $check4 = ' checked="on"'; } $krbarg = $in{'kerb_def_dom'}; - - my $krbcheck = ""; - if ( grep/^curr_authtype$/,(keys %in) ) { - if ($in{'curr_authtype'} =~ m/^krb/) { - $krbcheck = " checked=\"on\""; - if ( grep/^curr_autharg$/,(keys %in) ) { + if (defined($in{'curr_authtype'})) { + if ($in{'curr_authtype'} eq 'krb') { + $krbcheck = ' checked="on"'; + if (defined($in{'curr_kerb_ver'})) { + if ($in{'curr_krb_ver'} eq '5') { + $check5 = ' checked="on"'; + $check4 = ''; + } else { + $check4 = ' checked="on"'; + $check5 = ''; + } + } + if (defined($in{'curr_autharg'})) { $krbarg = $in{'curr_autharg'}; } + if (!$can_assign{'krb4'} && !$can_assign{'krb5'}) { + if (defined($in{'curr_autharg'})) { + $result = + &mt('Currently Kerberos authenticated with domain [_1] Version [_2].', + $in{'curr_autharg'},$krbver); + } else { + $result = + &mt('Currently Kerberos authenticated, Version [_1].',$krbver); + } + return $result; + } + } + } else { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="krb">'; } } - - my $jscall = "javascript:changed_radio('krb',$in{'formname'});"; - my $result .= &mt + if (!$can_assign{'krb4'} && !$can_assign{'krb5'}) { + return; + } elsif ($authtype eq '') { + if (defined($in{'mode'})) { + if ($in{'mode'} eq 'modifycourse') { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="krb">'; + } + } + } + } + $jscall = "javascript:changed_radio('krb',$in{'formname'});"; + if ($authtype eq '') { + $authtype = '<input type="radio" name="login" value="krb" '. + 'onclick="'.$jscall.'" onchange="'.$jscall.'"'. + $krbcheck.' />'; + } + if (($can_assign{'krb4'} && $can_assign{'krb5'}) || + ($can_assign{'krb4'} && !$can_assign{'krb5'} && + $in{'curr_authtype'} eq 'krb5') || + (!$can_assign{'krb4'} && $can_assign{'krb5'} && + $in{'curr_authtype'} eq 'krb4')) { + $result .= &mt ('[_1] Kerberos authenticated with domain [_2] '. '[_3] Version 4 [_4] Version 5 [_5]', - '<label><input type="radio" name="login" value="krb" '. - 'onclick="'.$jscall.'" onchange="'.$jscall.'"'.$krbcheck.' />', + '<label>'.$authtype, '</label><input type="text" size="10" name="krbarg" '. 'value="'.$krbarg.'" '. 'onchange="'.$jscall.'" />', '<label><input type="radio" name="krbver" value="4" '.$check4.' />', '</label><label><input type="radio" name="krbver" value="5" '.$check5.' />', '</label>'); + } elsif ($can_assign{'krb4'}) { + $result .= &mt + ('[_1] Kerberos authenticated with domain [_2] '. + '[_3] Version 4 [_4]', + '<label>'.$authtype, + '</label><input type="text" size="10" name="krbarg" '. + 'value="'.$krbarg.'" '. + 'onchange="'.$jscall.'" />', + '<label><input type="hidden" name="krbver" value="4" />', + '</label>'); + } elsif ($can_assign{'krb5'}) { + $result .= &mt + ('[_1] Kerberos authenticated with domain [_2] '. + '[_3] Version 5 [_4]', + '<label>'.$authtype, + '</label><input type="text" size="10" name="krbarg" '. + 'value="'.$krbarg.'" '. + 'onchange="'.$jscall.'" />', + '<label><input type="hidden" name="krbver" value="5" />', + '</label>'); + } return $result; } sub authform_internal{ - my %args = ( + my %in = ( formname => 'document.cu', kerb_def_dom => 'MSU.EDU', @_, ); - - my $intcheck = ""; - my $intarg = 'value=""'; - if ( grep/^curr_authtype$/,(keys %args) ) { - if ($args{'curr_authtype'} eq 'int') { - $intcheck = " checked=\"on\""; - if ( grep/^curr_autharg$/,(keys %args) ) { - $intarg = "value=\"$args{'curr_autharg'}\""; + my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + if (defined($in{'curr_authtype'})) { + if ($in{'curr_authtype'} eq 'int') { + if ($can_assign{'int'}) { + $intcheck = 'checked="on" '; + if (defined($in{'curr_autharg'})) { + $intarg = $in{'curr_autharg'}; + } + } else { + $result = &mt('Currently internally authenticated.'); + return $result; } } + } else { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="int">'; + } } - - my $jscall = "javascript:changed_radio('int',$args{'formname'});"; - my $result.=&mt + if (!$can_assign{'int'}) { + return; + } elsif ($authtype eq '') { + if (defined($in{'mode'})) { + if ($in{'mode'} eq 'modifycourse') { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="int">'; + } + } + } + } + $jscall = "javascript:changed_radio('int',$in{'formname'});"; + if ($authtype eq '') { + $authtype = '<input type="radio" name="login" value="int" '.$intcheck. + ' onchange="'.$jscall.'" onclick="'.$jscall.'" />'; + } + $autharg = '<input type="password" size="10" name="intarg" value="'. + $intarg.'" onchange="'.$jscall.'" />'; + $result = &mt ('[_1] Internally authenticated (with initial password [_2])', - '<label><input type="radio" name="login" value="int" '.$intcheck. - ' onchange="'.$jscall.'" onclick="'.$jscall.'" />', - '</label><input type="text" size="10" name="intarg" '.$intarg. - ' onchange="'.$jscall.'" />'); + '<label>'.$authtype,'</label>'.$autharg); return $result; } @@ -1868,24 +2063,46 @@ sub authform_local{ kerb_def_dom => 'MSU.EDU', @_, ); - - my $loccheck = ""; - my $locarg = 'value=""'; - if ( grep/^curr_authtype$/,(keys %in) ) { + my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'loc') { - $loccheck = " checked=\"on\""; - if ( grep/^curr_autharg$/,(keys %in) ) { - $locarg = "value=\"$in{'curr_autharg'}\""; + if ($can_assign{'loc'}) { + $loccheck = 'checked="on" '; + if (defined($in{'curr_autharg'})) { + $locarg = $in{'curr_autharg'}; + } + } else { + $result = &mt('Currently using local (institutional) authentication.'); + return $result; } } + } else { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="loc">'; + } } - - my $jscall = "javascript:changed_radio('loc',$in{'formname'});"; - my $result.=&mt('[_1] Local Authentication with argument [_2]', - '<label><input type="radio" name="login" value="loc" '.$loccheck. - ' onchange="'.$jscall.'" onclick="'.$jscall.'" />', - '</label><input type="text" size="10" name="locarg" '.$locarg. - ' onchange="'.$jscall.'" />'); + if (!$can_assign{'loc'}) { + return; + } elsif ($authtype eq '') { + if (defined($in{'mode'})) { + if ($in{'mode'} eq 'modifycourse') { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="loc">'; + } + } + } + } + $jscall = "javascript:changed_radio('loc',$in{'formname'});"; + if ($authtype eq '') { + $authtype = '<input type="radio" name="login" value="loc" '. + $loccheck.' onchange="'.$jscall.'" onclick="'. + $jscall.'" />'; + } + $autharg = '<input type="text" size="10" name="locarg" value="'. + $locarg.'" onchange="'.$jscall.'" />'; + $result = &mt('[_1] Local Authentication with argument [_2]', + '<label>'.$authtype,'</label>'.$autharg); return $result; } @@ -1895,16 +2112,92 @@ sub authform_filesystem{ kerb_def_dom => 'MSU.EDU', @_, ); - my $jscall = "javascript:changed_radio('fsys',$in{'formname'});"; - my $result.= &mt + my ($fsyscheck,$result,$authtype,$autharg,$jscall); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + if (defined($in{'curr_authtype'})) { + if ($in{'curr_authtype'} eq 'fsys') { + if ($can_assign{'fsys'}) { + $fsyscheck = 'checked="on" '; + } else { + $result = &mt('Currently Filesystem Authenticated.'); + return $result; + } + } + } else { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="fsys">'; + } + } + if (!$can_assign{'fsys'}) { + return; + } elsif ($authtype eq '') { + if (defined($in{'mode'})) { + if ($in{'mode'} eq 'modifycourse') { + if ($authnum == 1) { + $authtype = '<input type="hidden" name="login" value="fsys">'; + } + } + } + } + $jscall = "javascript:changed_radio('fsys',$in{'formname'});"; + if ($authtype eq '') { + $authtype = '<input type="radio" name="login" value="fsys" '. + $fsyscheck.' onchange="'.$jscall.'" onclick="'. + $jscall.'" />'; + } + $autharg = '<input type="text" size="10" name="fsysarg" value=""'. + ' onchange="'.$jscall.'" />'; + $result = &mt ('[_1] Filesystem Authenticated (with initial password [_2])', '<label><input type="radio" name="login" value="fsys" '. - 'onchange="'.$jscall.'" onclick="'.$jscall.'" />', - '</label><input type="text" size="10" name="fsysarg" value="" '. + $fsyscheck.'onchange="'.$jscall.'" onclick="'.$jscall.'" />', + '</label><input type="password" size="10" name="fsysarg" value="" '. 'onchange="'.$jscall.'" />'); return $result; } +sub get_assignable_auth { + my ($dom) = @_; + if ($dom eq '') { + $dom = $env{'request.role.domain'}; + } + my %can_assign = ( + krb4 => 1, + krb5 => 1, + int => 1, + loc => 1, + ); + my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom); + if (ref($domconfig{'usercreation'}) eq 'HASH') { + if (ref($domconfig{'usercreation'}{'authtypes'}) eq 'HASH') { + my $authhash = $domconfig{'usercreation'}{'authtypes'}; + my $context; + if ($env{'request.role'} =~ /^au/) { + $context = 'author'; + } elsif ($env{'request.role'} =~ /^dc/) { + $context = 'domain'; + } elsif ($env{'request.course.id'}) { + $context = 'course'; + } + if ($context) { + if (ref($authhash->{$context}) eq 'HASH') { + %can_assign = %{$authhash->{$context}}; + } + } + } + } + my $authnum = 0; + foreach my $key (keys(%can_assign)) { + if ($can_assign{$key}) { + $authnum ++; + } + } + if ($can_assign{'krb4'} && $can_assign{'krb5'}) { + $authnum --; + } + return ($authnum,%can_assign); +} + ############################################################### ## Get Authentication Defaults for Domain ## ############################################################### @@ -2030,7 +2323,7 @@ sub initialize_keywords { # Remove special values from %Keywords. foreach my $value ('total.count','average.count') { delete($Keywords{$value}) if (exists($Keywords{$value})); - } + } return 1; } @@ -2541,9 +2834,11 @@ sub preferred_languages { @languages=(@languages, split(/\s*(\,|\;|\:)\s*/,$env{'environment.languages'})); } - my $browser=(split(/\;/,$ENV{'HTTP_ACCEPT_LANGUAGE'}))[0]; + my $browser=$ENV{'HTTP_ACCEPT_LANGUAGE'}; if ($browser) { - @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$browser)); + my @browser = + map { (split(/\s*;\s*/,$_))[0] } (split(/\s*,\s*/,$browser)); + push(@languages,@browser); } if (&Apache::lonnet::domain($env{'user.domain'},'lang_def')) { @languages=(@languages, @@ -2565,14 +2860,40 @@ sub preferred_languages { my @genlanguages; foreach my $lang (@languages) { unless ($lang=~/\w/) { next; } - push (@genlanguages,$lang); + push(@genlanguages,$lang); if ($lang=~/(\-|\_)/) { push(@genlanguages,(split(/(\-|\_)/,$lang))[0]); } } + #uniqueify the languages list + my %count; + @genlanguages = map { $count{$_}++ == 0 ? $_ : () } @genlanguages; return @genlanguages; } +sub languages { + my ($possible_langs) = @_; + my @preferred_langs = &preferred_languages(); + if (!ref($possible_langs)) { + if( wantarray ) { + return @preferred_langs; + } else { + return $preferred_langs[0]; + } + } + my %possibilities = map { $_ => 1 } (@$possible_langs); + my @preferred_possibilities; + foreach my $preferred_lang (@preferred_langs) { + if (exists($possibilities{$preferred_lang})) { + push(@preferred_possibilities, $preferred_lang); + } + } + if( wantarray ) { + return @preferred_possibilities; + } + return $preferred_possibilities[0]; +} + ############################################################### ## Student Answer Attempts ## ############################################################### @@ -2627,14 +2948,14 @@ sub get_previous_attempt { $lasthash{$key}=$returnhash{$version.':'.$key}; } } - $prevattempts='<table border="0" width="100%"><tr><td bgcolor="#777777">'; - $prevattempts.='<table border="0" width="100%"><tr bgcolor="#e6ffff"><td>History</td>'; + $prevattempts=&start_data_table().&start_data_table_header_row(); + $prevattempts.='<th>'.&mt('History').'</th>'; foreach my $key (sort(keys(%lasthash))) { my ($ign,@parts) = split(/\./,$key); if ($#parts > 0) { my $data=$parts[-1]; pop(@parts); - $prevattempts.='<td>Part '.join('.',@parts).'<br />'.$data.' </td>'; + $prevattempts.='<th>'.&mt('Part ').join('.',@parts).'<br />'.$data.' </th>'; } else { if ($#parts == 0) { $prevattempts.='<th>'.$parts[0].'</th>'; @@ -2643,41 +2964,53 @@ sub get_previous_attempt { } } } + $prevattempts.=&end_data_table_header_row(); if ($getattempt eq '') { for ($version=1;$version<=$returnhash{'version'};$version++) { - $prevattempts.='</tr><tr bgcolor="#ffffe6"><td>Transaction '.$version.'</td>'; + $prevattempts.=&start_data_table_row(). + '<td>'.&mt('Transaction [_1]',$version).'</td>'; foreach my $key (sort(keys(%lasthash))) { - my $value; - if ($key =~ /timestamp/) { - $value=scalar(localtime($returnhash{$version.':'.$key})); - } else { - $value=$returnhash{$version.':'.$key}; - } - $prevattempts.='<td>'.&unescape($value).' </td>'; + my $value = &format_previous_attempt_value($key, + $returnhash{$version.':'.$key}); + $prevattempts.='<td>'.$value.' </td>'; } + $prevattempts.=&end_data_table_row(); } } - $prevattempts.='</tr><tr bgcolor="#ffffe6"><td>Current</td>'; + $prevattempts.=&start_data_table_row().'<td>'.&mt('Current').'</td>'; foreach my $key (sort(keys(%lasthash))) { - my $value; - if ($key =~ /timestamp/) { - $value=scalar(localtime($lasthash{$key})); - } else { - $value=$lasthash{$key}; - } - $value=&unescape($value); + my $value = &format_previous_attempt_value($key,$lasthash{$key}); if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)} $prevattempts.='<td>'.$value.' </td>'; } - $prevattempts.='</tr></table></td></tr></table>'; + $prevattempts.= &end_data_table_row().&end_data_table(); } else { - $prevattempts='Nothing submitted - no attempts.'; + $prevattempts= + &start_data_table().&start_data_table_row(). + '<td>'.&mt('Nothing submitted - no attempts.').'</td>'. + &end_data_table_row().&end_data_table(); } } else { - $prevattempts='No data.'; + $prevattempts= + &start_data_table().&start_data_table_row(). + '<td>'.&mt('No data.').'</td>'. + &end_data_table_row().&end_data_table(); } } +sub format_previous_attempt_value { + my ($key,$value) = @_; + if ($key =~ /timestamp/) { + $value = &Apache::lonlocal::locallocaltime($value); + } elsif (ref($value) eq 'ARRAY') { + $value = '('.join(', ', @{ $value }).')'; + } else { + $value = &unescape($value); + } + return $value; +} + + sub relative_to_absolute { my ($url,$output)=@_; my $parser=HTML::TokeParser->new(\$output); @@ -2836,9 +3169,9 @@ sub pprmlink { if (!$symb) { $symb=&Apache::lonnet::symbread(); } $symb=&escape($symb); if ($target) { $target="target=\"$target\""; } - return '<a href="/adm/parmset?&command=set&'. - 'symb='.$symb.'&uname='.$uname. - '&udom='.$udom.'" '.$target.'>'.$text.'</a>'; + return '<a href="/adm/parmset?command=set&'. + 'symb='.$symb.'&uname='.$uname. + '&udom='.$udom.'" '.$target.'>'.$text.'</a>'; } ############################################## @@ -3515,9 +3848,6 @@ sub bodytag { if (!$realm) { $realm=' '; } # Set messages my $messages=&domainlogo($domain); -# Port for miniserver - my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'}; - if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; } my $extra_body_attr = &make_attr_string($forcereg,\%design); @@ -3635,7 +3965,7 @@ ENDROLE my $imgsrc = $img; if ($img =~ /^\/adm/) { - $imgsrc = 'http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.$img; + $imgsrc = &lonhttpdurl($img); } my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />'; @@ -3769,7 +4099,7 @@ sub standard_css { my $vlink = &designparm($function.'.vlink', $domain); my $link = &designparm($function.'.link', $domain); - my $sans = 'Arial,Helvetica,sans-serif'; + my $sans = 'Verdana,Arial,Helvetica,sans-serif'; my $mono = 'monospace'; my $data_table_head = $tabbg; my $data_table_light = '#EEEEEE'; @@ -3787,8 +4117,9 @@ sub standard_css { my $table_header = '#DDDDDD'; my $feedback_link_bg = '#BBBBBB'; - my $border = ($env{'browser.type'} eq 'explorer') ? '0px 2px 0px 2px' - : '0px 3px 0px 4px'; + my $border = ($env{'browser.type'} eq 'explorer' || + $env{'browser.type'} eq 'safari' ) ? '0px 2px 0px 2px' + : '0px 3px 0px 4px'; return <<END; @@ -3808,7 +4139,7 @@ table.thinborder tr td { form, .inline { display: inline; } .center { text-align: center; } -.LC_filename {font-family: $mono;} +.LC_filename {font-family: $mono; white-space:pre;} .LC_error { color: red; font-size: larger; @@ -3849,7 +4180,7 @@ table.LC_pastsubmission { margin: 2px; } -table#LC_top_nav, table#LC_menubuttons { +table#LC_top_nav, table#LC_menubuttons,table#LC_nav_location { width: 100%; background: $pgbg; border: 2px; @@ -3857,7 +4188,7 @@ table#LC_top_nav, table#LC_menubuttons { padding: 0px; } -table#LC_title_bar, table.LC_breadcrumbs, table#LC_nav_location, +table#LC_title_bar, table.LC_breadcrumbs, table#LC_title_bar.LC_with_remote { width: 100%; border-color: $pgbg; @@ -4054,13 +4385,13 @@ table.LC_data_table, table.LC_mail_list } table.LC_nested_outer { border: 1px solid #000000; - border-collapse: separate; + border-collapse: collapse; border-spacing: 0px; width: 100%; } table.LC_nested { border: 0px; - border-collapse: separate; + border-collapse: collapse; border-spacing: 0px; width: 100%; } @@ -4112,7 +4443,8 @@ table.LC_nested tr.LC_info_row td { font-size: small; text-align: center; } -table.LC_nested tr.LC_info_row td.LC_left_item { +table.LC_nested tr.LC_info_row td.LC_left_item, +table.LC_nested_outer tr th.LC_left_item { text-align: left; } table.LC_nested td { @@ -4343,9 +4675,7 @@ table#LC_helpmenu_links a:hover { border: 1px solid #8888FF; background: #CCCCFF; } - table.LC_pick_box { - width: 100%; border-collapse: separate; background: white; border: 1px solid black; @@ -4358,6 +4688,14 @@ table.LC_pick_box td.LC_pick_box_title { width: 184px; padding: 8px; } +table.LC_pick_box td.LC_pick_box_value { + text-align: left; + padding: 8px; +} +table.LC_pick_box td.LC_pick_box_select { + text-align: left; + padding: 8px; +} table.LC_pick_box td.LC_pick_box_separator { padding: 0px; height: 1px; @@ -4366,7 +4704,48 @@ table.LC_pick_box td.LC_pick_box_separat table.LC_pick_box td.LC_pick_box_submit { text-align: right; } - +table.LC_pick_box td.LC_evenrow_value { + text-align: left; + padding: 8px; + background-color: $data_table_light; +} +table.LC_pick_box td.LC_oddrow_value { + text-align: left; + padding: 8px; + background-color: $data_table_light; +} +table.LC_helpform_receipt { + width: 620px; + border-collapse: separate; + background: white; + border: 1px solid black; + border-spacing: 1px; +} +table.LC_helpform_receipt td.LC_pick_box_title { + background: $tabbg; + font-weight: bold; + text-align: right; + width: 184px; + padding: 8px; +} +table.LC_helpform_receipt td.LC_evenrow_value { + text-align: left; + padding: 8px; + background-color: $data_table_light; +} +table.LC_helpform_receipt td.LC_oddrow_value { + text-align: left; + padding: 8px; + background-color: $data_table_light; +} +table.LC_helpform_receipt td.LC_pick_box_separator { + padding: 0px; + height: 1px; + background: black; +} +span.LC_helpform_receipt_cat { + font-weight: bold; +} table.LC_group_priv_box { background: white; border: 1px solid black; @@ -4434,12 +4813,19 @@ table.LC_descriptive_input td.LC_descrip text-align: right; font-weight: bold; } -table.LC_feedback_link { - background: $feedback_link_bg; +div.LC_feedback_link { + background: white; + width: 100%; } span.LC_feedback_link { - background: $feedback_link_bg; - font-size: larger; + background: $feedback_link_bg; + font-size: larger; +} +span.LC_message_link { + background: $feedback_link_bg; + font-size: larger; + position: absolute; + right: 1em; } table.LC_prior_tries { @@ -4511,6 +4897,10 @@ span.LC_nobreak { white-space: nowrap; } +span.LC_cusr_emph { + font-style: italic; +} + table.LC_docs_documents { background: #BBBBBB; border-width: 0px; @@ -4578,6 +4968,163 @@ table.LC_docs_adddocs th { background: #DDDDDD; } +table.LC_sty_begin { + background: #BBFFBB; +} +table.LC_sty_end { + background: #FFBBBB; +} + +table.LC_double_column { + border-width: 0px; + border-collapse: collapse; + width: 100%; + padding: 2px; +} + +table.LC_double_column tr td.LC_left_col { + top: 2px; + left: 2px; + width: 47%; + vertical-align: top; +} + +table.LC_double_column tr td.LC_right_col { + top: 2px; + right: 2px; + width: 47%; + vertical-align: top; +} + +span.LC_role_level { + font-weight: bold; +} + +div.LC_left_float { + float: left; + padding-right: 5%; + padding-bottom: 4px; +} + +div.LC_clear_float_header { + padding-bottom: 2px; +} + +div.LC_clear_float_footer { + padding-top: 10px; + clear: both; +} + + +div.LC_grade_select_mode { + float: left; + font-family: $sans; +} +div.LC_grade_select_mode div div { + margin: 5px; +} +div.LC_grade_select_mode_selector { + margin: 5px; + float: left; +} +div.LC_grade_select_mode_selector_header { + font: bold medium $sans; +} +div.LC_grade_select_mode_type { + clear: left; +} + +div.LC_grade_show_user { + margin-top: 20px; + border: 1px solid black; +} +div.LC_grade_user_name { + background: #DDDDEE; + border-bottom: 1px solid black; + font: bold large $sans; +} +div.LC_grade_show_user_odd_row div.LC_grade_user_name { + background: #DDEEDD; +} + +div.LC_grade_show_problem, +div.LC_grade_submissions, +div.LC_grade_message_center, +div.LC_grade_info_links, +div.LC_grade_assign { + margin: 5px; + width: 99%; + background: #FFFFFF; +} +div.LC_grade_show_problem_header, +div.LC_grade_submissions_header, +div.LC_grade_message_center_header, +div.LC_grade_assign_header { + font: bold large $sans; +} +div.LC_grade_show_problem_problem, +div.LC_grade_submissions_body, +div.LC_grade_message_center_body, +div.LC_grade_assign_body { + border: 1px solid black; + width: 99%; + background: #FFFFFF; +} +span.LC_grade_check_note { + font: normal medium $sans; + display: inline; + position: absolute; + right: 1em; +} + + +div.LC_edit_problem_header { + font: normal medium $sans; + margin: 2px; +} +div.LC_edit_problem_header, +div.LC_edit_problem_header div, +div.LC_edit_problem_editxml_header, +div.LC_edit_problem_editxml_header div { + margin-top: 5px; +} +div.LC_edit_problem_header_edit_row { + background: $tabbg; + padding: 3px; + margin-bottom: 5px; +} +div.LC_edit_problem_header_title { + font: larger bold $sans; + background: $tabbg; + padding: 3px; +} +table.LC_edit_problem_header_title { + font: larger bold $sans; + width: 100%; + border-color: $pgbg; + border-style: solid; + border-width: $border; + + background: $tabbg; + border-collapse: collapse; + padding: 0px +} + +div.LC_edit_problem_discards { + float: left; + padding-bottom: 5px; +} +div.LC_edit_problem_saves { + float: right; + padding-bottom: 5px; +} +hr.LC_edit_problem_divide { + clear: both; + color: $tabbg; + background-color: $tabbg; + height: 3px; + border: 0px; +} END } @@ -4694,7 +5241,9 @@ Inputs: none sub xml_begin { my $output=''; - &Apache::lonhtmlcommon::init_htmlareafields(); + if ($env{'internal.start_page'}==1) { + &Apache::lonhtmlcommon::init_htmlareafields(); + } if ($env{'browser.mathml'}) { $output='<?xml version="1.0"?>' @@ -5613,7 +6162,7 @@ sub user_picker { my $currdom = $dom; my %curr_selected = ( srchin => 'dom', - srchby => 'uname', + srchby => 'lastname', ); my $srchterm; if (ref($srch) eq 'HASH') { @@ -5632,14 +6181,15 @@ sub user_picker { $srchterm = $srch->{'srchterm'}; } my %lt=&Apache::lonlocal::texthash( + 'usr' => 'Search criteria', 'doma' => 'Domain/institution to search', 'uname' => 'username', 'lastname' => 'last name', 'lastfirst' => 'last name, first name', 'crs' => 'in this course', - 'dom' => 'in this domain', + 'dom' => 'in selected LON-CAPA domain', 'alc' => 'all LON-CAPA', - 'instd' => 'in institutional directory', + 'instd' => 'in institutional directory for selected domain', 'exact' => 'is', 'contains' => 'contains', 'begins' => 'begins with', @@ -5674,7 +6224,7 @@ sub user_picker { $srchinsel .= "\n </select>\n"; my $srchbysel = ' <select name="srchby">'; - foreach my $option ('uname','lastname','lastfirst') { + foreach my $option ('lastname','lastfirst','uname') { if ($curr_selected{'srchby'} eq $option) { $srchbysel .= ' <option value="'.$option.'" selected="selected">'.$lt{$option}.'</option>'; @@ -5686,7 +6236,7 @@ sub user_picker { $srchbysel .= "\n </select>\n"; my $srchtypesel = ' <select name="srchtype">'; - foreach my $option ('exact','begins','contains') { + foreach my $option ('begins','contains','exact') { if ($curr_selected{'srchtype'} eq $option) { $srchtypesel .= ' <option value="'.$option.'" selected="selected">'.$lt{$option}.'</option>'; @@ -5700,7 +6250,12 @@ sub user_picker { my ($newuserscript,$new_user_create); if ($forcenewuser) { - $new_user_create = '<p> <input type="submit" name="forcenew" value="'.&HTML::Entities::encode(&mt('Make new user "[_1]"',$srchterm),'<>&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" /> </p>'; + if (ref($srch) eq 'HASH') { + if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $env{'request.role.domain'}) { + $new_user_create = '<p> <input type="submit" name="forcenew" value="'.&HTML::Entities::encode(&mt('Make new user "[_1]"',$srchterm),'<>&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" /> </p>'; + } + } + $newuserscript = <<"ENDSCRIPT"; function setSearch(createnew,callingForm) { @@ -5807,16 +6362,18 @@ $new_user_create <table> <tr> + <td>$lt{'doma'}:</td> + <td>$domform</td> + </td> + </tr> + <tr> + <td>$lt{'usr'}:</td> <td>$srchbysel $srchtypesel <input type="text" size="15" name="srchterm" value="$srchterm" /> $srchinsel </td> </tr> - <tr> - <td>$lt{'doma'}: $domform</td> - </td> - </tr> </table> <br /> END_BLOCK @@ -5824,7 +6381,58 @@ END_BLOCK return $output; } - +sub username_rule_check { + my ($srch,$caller) = @_; + my ($response,@curr_rules,%inst_results,$rulematch); + my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($srch->{'srchdomain'}); + if (ref($srch) eq 'HASH') { + (my $inst_response,%inst_results) = + &Apache::lonnet::get_instuser($srch->{'srchdomain'}, + $srch->{'srchterm'}); + my %domconfig = &Apache::lonnet::get_dom('configuration', + ['usercreation'],$srch->{'srchdomain'}); + if (ref($domconfig{'usercreation'}) eq 'HASH') { + if (ref($domconfig{'usercreation'}{'username_rule'}) eq 'ARRAY') { + @curr_rules = @{$domconfig{'usercreation'}{'username_rule'}}; + } + } + if (@curr_rules > 0) { + my $domdesc = &Apache::lonnet::domain($srch->{'srchdomain'},'description'); + my $instuser_reqd; + my %rule_check = &Apache::lonnet::inst_rulecheck($srch->{'srchdomain'},$srch->{'srchterm'},\@curr_rules); + foreach my $rule (@curr_rules) { + if ($rule_check{$rule}) { + $rulematch = $rule; + if ($inst_response eq 'ok') { + if (keys(%inst_results) == 0) { + if ($caller eq 'new') { + $response = &mt('The username you chose matches the format of usernames defined for <span class="LC_cusr_emph">[_1]</span>, but the user does not exist in the institutional directory.',$domdesc).'<br />'.&mt("You must choose a username with a different format -- one that will not conflict with 'official' institutional usernames."); + } + } + } + last; + } + } + if ($response) { + if ((ref($rules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) { + if (@{$ruleorder} > 0) { + $response .= '<br />'.&mt('Usernames with the following format(s) may <span class="LC_cusr_emph">only</span> be used for verified users at [_1]:',$domdesc).' <ul>'; + foreach my $rule (@{$ruleorder}) { + if (grep(/^\Q$rule\E$/,@curr_rules)) { + if (ref($rules->{$rule}) eq 'HASH') { + $response .= '<li>'.$rules->{$rule}{'name'}.': '. + $rules->{$rule}{'desc'}.'</li>'; + } + } + } + } + $response .= '</ul>'; + } + } + } + } + return ($response,$rulematch,$rules,%inst_results); +} =pod @@ -6197,20 +6805,21 @@ sub csv_print_samples { my ($r,$records) = @_; my $samples = &get_samples($records,3); - $r->print(&mt('Samples').'<br /><table border="2"><tr>'); + $r->print(&mt('Samples').'<br />'.&start_data_table(). + &start_data_table_header_row()); foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { $r->print('<th>'.&mt('Column [_1]',($sample+1)).'</th>'); } - $r->print('</tr>'); + $r->print(&end_data_table_header_row()); foreach my $hash (@$samples) { - $r->print('<tr>'); + $r->print(&start_data_table_row()); foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { $r->print('<td>'); if (defined($$hash{$sample})) { $r->print($$hash{$sample}); } $r->print('</td>'); } - $r->print('</tr>'); + $r->print(&end_data_table_row()); } - $r->print('</tr></table><br />'."\n"); + $r->print(&end_data_table().'<br />'."\n"); } ###################################################### @@ -6235,12 +6844,13 @@ sub csv_print_select_table { my $i=0; my $samples = &get_samples($records,1); $r->print(&mt('Associate columns with student attributes.')."\n". - '<table border="2"><tr>'. + &start_data_table().&start_data_table_header_row(). '<th>'.&mt('Attribute').'</th>'. - '<th>'.&mt('Column').'</th></tr>'."\n"); + '<th>'.&mt('Column').'</th>'. + &end_data_table_header_row()."\n"); foreach my $array_ref (@$d) { my ($value,$display,$defaultcol)=@{ $array_ref }; - $r->print('<tr><td>'.$display.'</td>'); + $r->print(&start_data_table_row().'<tr><td>'.$display.'</td>'); $r->print('<td><select name=f'.$i. ' onchange="javascript:flip(this.form,'.$i.');">'); @@ -6250,9 +6860,10 @@ sub csv_print_select_table { ($sample eq $defaultcol ? ' selected="selected" ' : ''). '>Column '.($sample+1).'</option>'); } - $r->print('</select></td></tr>'."\n"); + $r->print('</select></td>'.&end_data_table_row()."\n"); $i++; } + $r->print(&end_data_table()); $i--; return $i; } @@ -6279,11 +6890,13 @@ sub csv_samples_select_table { my $i=0; # my $samples = &get_samples($records,3); - $r->print('<table border=2><tr><th>'. - &mt('Field').'</th><th>'.&mt('Samples').'</th></tr>'); + $r->print(&start_data_table(). + &start_data_table_header_row().'<th>'. + &mt('Field').'</th><th>'.&mt('Samples').'</th>'. + &end_data_table_header_row()); foreach my $key (sort(keys(%{ $samples->[0] }))) { - $r->print('<tr><td><select name="f'.$i.'"'. + $r->print(&start_data_table_row().'<td><select name="f'.$i.'"'. ' onchange="javascript:flip(this.form,'.$i.');">'); foreach my $option (@$d) { my ($value,$display,$defaultcol)=@{ $option }; @@ -6297,9 +6910,10 @@ sub csv_samples_select_table { $r->print($samples->[$line]{$key}."<br />\n"); } } - $r->print('</td></tr>'); + $r->print('</td>'.&end_data_table_row()); $i++; } + $r->print(&end_data_table()); $i--; return($i); } @@ -6986,7 +7600,7 @@ sub commit_studentrole { ############################################################ sub check_clone { - my ($args) = @_; + my ($args,$linefeed) = @_; my $cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'}; my ($clonecrsudom,$clonecrsunum)= &LONCAPA::split_courseid($cloneid); my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom); @@ -6994,8 +7608,7 @@ sub check_clone { my $can_clone = 0; if ($clonehome eq 'no_host') { - $clonemsg = &mt('Attempting to clone non-existing [_1]', - $args->{'crstype'}); + $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'}); } else { my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1}); if ($env{'request.role.domain'} eq $args->{'clonedomain'}) { @@ -7004,18 +7617,24 @@ sub check_clone { my %clonehash = &Apache::lonnet::get('environment',['cloners'], $args->{'clonedomain'},$args->{'clonecourse'}); my @cloners = split(/,/,$clonehash{'cloners'}); - my %roleshash = - &Apache::lonnet::get_my_roles($args->{'ccuname'}, - $args->{'ccdomain'},'userroles',['active'],['cc'], - [$args->{'clonedomain'}]); - if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) { - $can_clone = 1; - } else { - $clonemsg = &mt('The new course was not cloned from an existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'}); + if (grep(/^\*$/,@cloners)) { + $can_clone = 1; + } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) { + $can_clone = 1; + } else { + my %roleshash = + &Apache::lonnet::get_my_roles($args->{'ccuname'}, + $args->{'ccdomain'}, + 'userroles',['active'],['cc'], + [$args->{'clonedomain'}]); + if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) { + $can_clone = 1; + } else { + $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'}); + } } - } + } } - return ($can_clone, $clonemsg, $cloneid, $clonehome); } @@ -7032,9 +7651,11 @@ sub construct_course { # my ($can_clone, $clonemsg, $cloneid, $clonehome); if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) { - ($can_clone, $clonemsg, $cloneid, $clonehome) = &check_clone($args); + ($can_clone, $clonemsg, $cloneid, $clonehome) = &check_clone($args,$linefeed); if ($context ne 'auto') { - $clonemsg = '<span class="LC_error">'.$clonemsg.'</span>'; + if ($clonemsg ne '') { + $clonemsg = '<span class="LC_error">'.$clonemsg.'</span>'; + } } $outcome .= $clonemsg.$linefeed; @@ -7378,10 +7999,27 @@ sub icon { return &lonhttpdurl($iconname); } -sub lonhttpdurl { - my ($url)=@_; +sub lonhttpd_port { my $lonhttpd_port=$Apache::lonnet::perlvar{'lonhttpdPort'}; if (!defined($lonhttpd_port)) { $lonhttpd_port='8080'; } + # IE doesn't like a secure page getting images from a non-secure + # port (when logging we haven't parsed the browser type so default + # back to secure + if ((!exists($env{'browser.type'}) || $env{'browser.type'} eq 'explorer') + && $ENV{'SERVER_PORT'} == 443) { + return 443; + } + return $lonhttpd_port; + +} + +sub lonhttpdurl { + my ($url)=@_; + + my $lonhttpd_port = &lonhttpd_port(); + if ($lonhttpd_port == 443) { + return 'https://'.$ENV{'SERVER_NAME'}.$url; + } return 'http://'.$ENV{'SERVER_NAME'}.':'.$lonhttpd_port.$url; }