--- loncom/interface/loncommon.pm 2007/08/02 01:07:00 1.558 +++ loncom/interface/loncommon.pm 2007/10/30 01:04:21 1.601 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.558 2007/08/02 01:07:00 albertel Exp $ +# $Id: loncommon.pm,v 1.601 2007/10/30 01:04:21 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -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 .= - "". - "
$text"; + "". + "'. + &end_data_table_row().&end_data_table(); } } else { - $prevattempts='No data.'; + $prevattempts= + &start_data_table().&start_data_table_row(). + ''. + &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); @@ -2769,9 +3169,9 @@ sub pprmlink { if (!$symb) { $symb=&Apache::lonnet::symbread(); } $symb=&escape($symb); if ($target) { $target="target=\"$target\""; } - return ''.$text.''; + return ''.$text.''; } ############################################## @@ -3397,6 +3797,9 @@ Inputs: =item * $args, optional argument valid values are no_auto_mt_title -> prevents &mt()ing the title arg + inherit_jsmath -> when creating popup window in a page, + should it have jsmath forced on by the + current page =back @@ -3445,15 +3848,12 @@ 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); # construct main body tag my $bodytag = "". - &Apache::lontexconvert::init_math_support(); + &Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'}); if ($bodyonly) { return $bodytag; @@ -3565,7 +3965,7 @@ ENDROLE my $imgsrc = $img; if ($img =~ /^\/adm/) { - $imgsrc = 'http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.$img; + $imgsrc = &lonhttpdurl($img); } my $upperleft=''.$function.''; @@ -3738,7 +4138,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; @@ -3984,13 +4384,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%; } @@ -4042,7 +4442,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 { @@ -4273,9 +4674,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; @@ -4288,6 +4687,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; @@ -4296,7 +4703,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; @@ -4364,12 +4812,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 { @@ -4441,6 +4896,10 @@ span.LC_nobreak { white-space: nowrap; } +span.LC_cusr_emph { + font-style: italic; +} + table.LC_docs_documents { background: #BBBBBB; border-width: 0px; @@ -4508,6 +4967,139 @@ 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 { + border: 1px solid black; + float: left; +} +div.LC_grade_select_mode div div { + margin: 5px; +} + +div.LC_grade_select_mode_header { + font: bold larger $sans; + background: $tabbg; +} + +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; +} +div.LC_edit_problem_header, +div.LC_edit_problem_header div { + margin-top: 5px; +} +div.LC_edit_problem_header_title { + font: larger medium $sans; + background: $tabbg; +} +hr.LC_edit_problem_divide { + color: $tabbg; + background-color: $tabbg; + height: 3px; + border: 0px; +} END } @@ -4624,7 +5216,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='' @@ -4711,6 +5305,10 @@ Inputs: $title - optional title for the no_auto_mt_title -> prevent &mt()ing the title arg + inherit_jsmath -> when creating popup window in a page, + should it have jsmath forced on by the + current page + =cut sub start_page { @@ -5535,11 +6133,11 @@ sub get_secgrprole_info { } sub user_picker { - my ($dom,$srch,$forcenewuser) = @_; + my ($dom,$srch,$forcenewuser,$caller) = @_; my $currdom = $dom; my %curr_selected = ( srchin => 'dom', - srchby => 'uname', + srchby => 'lastname', ); my $srchterm; if (ref($srch) eq 'HASH') { @@ -5557,25 +6155,30 @@ sub user_picker { } $srchterm = $srch->{'srchterm'}; } - use Data::Dumper; - &Apache::lonnet::logthis(&Dumper($srch)); my %lt=&Apache::lonlocal::texthash( - 'usr' => 'Search for', - 'or' => 'or', - 'doma' => 'domain', + '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', + 'youm' => "You must include some text to search for.", + 'thte' => "The text you are searching for must contain at least two characters when using a 'begins' type search.", + 'thet' => "The text you are searching for must contain at least three characters when using a 'contains' type search.", + 'yomc' => "You must choose a domain when using an institutional directory search.", + 'ymcd' => "You must choose a domain when using a domain search.", + 'whus' => "When using searching by last,first you must include a comma as separator between last name and first name.", + 'whse' => "When searching by last,first you must include at least one character in the first name.", + 'thfo' => "The following need to be corrected before the search can be run:", ); - my $domform = &select_dom_form($currdom,'srchdomain',1); - - my $srchin; + my $domform = &select_dom_form($currdom,'srchdomain',1,1); + my $srchinsel = ' - -ROW + if ($curr_selected{'srchin'} eq $option) { + $srchinsel .= ' + '; + } else { + $srchinsel .= ' + '; + } } + $srchinsel .= "\n \n"; my $srchbysel = ' \n"; my $srchtypesel = ' &"').'" onclick="javascript:setSearch(\'1\');" />

'; + 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 = '

&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" />

'; + } + } + $newuserscript = <<"ENDSCRIPT"; -function setSearch(createnew) { +function setSearch(createnew,callingForm) { if (createnew == 1) { - for (var i=0; i -function validateEntry() { +function validateEntry(callingForm) { var checkok = 1; var srchin; - for (var i=0; i - + + + + + + -$srchin
$text"; } # 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,138 @@ 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 + +creates a function resize_textrea that takes two IDs first should be +the id of the element to resize, second should be the id of a div that +surrounds everything that comes after the textarea, this routine needs +to be attached to the for the onload and onresize events. + + +=cut + +sub resize_textarea_js { + my $geometry = &viewport_geometry_js(); + return <<"RESIZE"; + +RESIZE + +} + +=pod + =back =head1 Excel and CSV file utility routines @@ -1285,8 +1407,6 @@ sub domain_select { =over 4 -=cut - =item * multiple_select_form($name,$value,$size,$hash,$order) Returns a string containing a form to allow a user to select the domain to preform an operation in. @@ -1433,18 +1553,28 @@ See loncreateuser.pm for an example invo If the $includeempty flag is set, it also includes an empty choice ("no domain selected"); +If the $showdomdesc flag is set, the domain name is followed by the domain description. + =cut #------------------------------------------- sub select_dom_form { - my ($defdom,$name,$includeempty) = @_; + my ($defdom,$name,$includeempty,$showdomdesc) = @_; my @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains()); if ($includeempty) { @domains=('',@domains); } my $selectdomain = ""; return $selectdomain; @@ -1454,24 +1584,68 @@ sub select_dom_form { =pod -=item * home_server_option_list($domain) +=item * home_server_form_item($domain,$name,$defaultflag) -returns a string which contains an + + + form item if there are multiple library servers in $domain, or + (ii) an form item + if there is only one library server in $domain. + +(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.= - '\n"; + my $result; + my $numlib = keys(%servers); + if ($numlib > 1) { + $result .= ''."\n"; + } elsif ($numlib == 1) { + my $hostid; + foreach my $item (keys(%servers)) { + $hostid = $item; + } + $result .= ''; + if (!$hide) { + $result .= $hostid.' '.$servers{$hostid}; + } + $result .= "\n"; + } elsif ($default) { + $result .= ''; + if (!$hide) { + $result .= &mt('default'); + } + $result .= "\n"; } - return $result; + return ($result,$numlib); } =pod @@ -1624,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'}'"; } } @@ -1719,79 +1890,170 @@ sub authform_nochange{ kerb_def_dom => 'MSU.EDU', @_, ); - my $result = ''; + } 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 = ''; } } - - 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 = ''; + } + } + } + } + $jscall = "javascript:changed_radio('krb',$in{'formname'});"; + if ($authtype eq '') { + $authtype = ''; + } + 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]', - ''.&mt('Nothing submitted - no attempts.').''.&mt('No data.').' - $extra -
$srchbysel - $srchtypesel - + $lt{'doma'}:$domform
$lt{'usr'}:$srchbysel + $srchtypesel + + $srchinsel

END_BLOCK @@ -5737,7 +6356,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 [_1], but the user does not exist in the institutional directory.',$domdesc).'
'.&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 .= '
'.&mt('Usernames with the following format(s) may only be used for verified users at [_1]:',$domdesc).'
    '; + foreach my $rule (@{$ruleorder}) { + if (grep(/^\Q$rule\E$/,@curr_rules)) { + if (ref($rules->{$rule}) eq 'HASH') { + $response .= '
  • '.$rules->{$rule}{'name'}.': '. + $rules->{$rule}{'desc'}.'
  • '; + } + } + } + } + $response .= '
'; + } + } + } + } + return ($response,$rulematch,$rules,%inst_results); +} =pod @@ -5996,28 +6666,50 @@ sub record_sep { $i++; } } else { - my @allfields; + my $separator=','; if ($env{'form.upfiletype'} eq 'semisv') { - @allfields=split(/;/,$record,-1); - } else { - @allfields=split(/\,/,$record,-1); + $separator=';'; } my $i=0; - my $j; - for ($j=0;$j<=$#allfields;$j++) { - my $field=$allfields[$j]; - if ($field=~/^\s*(\"|\')/) { - my $delimiter=$1; - while (($field!~/$delimiter$/) && ($j<$#allfields)) { - $j++; - $field.=','.$allfields[$j]; - } - $field=~s/^\s*$delimiter//; - $field=~s/$delimiter\s*$//; - } - $components{&takeleft($i)}=$field; - $i++; +# the character we are looking for to indicate the end of a quote or a record + my $looking_for=$separator; +# do not add the characters to the fields + my $ignore=0; +# we just encountered a separator (or the beginning of the record) + my $just_found_separator=1; +# store the field we are working on here + my $field=''; +# work our way through all characters in record + foreach my $character ($record=~/(.)/g) { + if ($character eq $looking_for) { + if ($character ne $separator) { +# Found the end of a quote, again looking for separator + $looking_for=$separator; + $ignore=1; + } else { +# Found a separator, store away what we got + $components{&takeleft($i)}=$field; + $i++; + $just_found_separator=1; + $ignore=0; + $field=''; + } + next; + } +# single or double quotation marks after a separator indicate beginning of a quote +# we are now looking for the end of the quote and need to ignore separators + if ((($character eq '"') || ($character eq "'")) && ($just_found_separator)) { + $looking_for=$character; + next; + } +# ignore would be true after we reached the end of a quote + if ($ignore) { next; } + if (($just_found_separator) && ($character=~/\s/)) { next; } + $field.=$character; + $just_found_separator=0; } +# catch the very last entry, since we never encountered the separator + $components{&takeleft($i)}=$field; } return %components; } @@ -6088,20 +6780,21 @@ sub csv_print_samples { my ($r,$records) = @_; my $samples = &get_samples($records,3); - $r->print(&mt('Samples').'
'); + $r->print(&mt('Samples').'
'.&start_data_table(). + &start_data_table_header_row()); foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { $r->print(''); } - $r->print(''); + $r->print(&end_data_table_header_row()); foreach my $hash (@$samples) { - $r->print(''); + $r->print(&start_data_table_row()); foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { $r->print(''); } - $r->print(''); + $r->print(&end_data_table_row()); } - $r->print('
'.&mt('Column [_1]',($sample+1)).'
'); if (defined($$hash{$sample})) { $r->print($$hash{$sample}); } $r->print('

'."\n"); + $r->print(&end_data_table().'
'."\n"); } ###################################################### @@ -6126,12 +6819,13 @@ sub csv_print_select_table { my $i=0; my $samples = &get_samples($records,1); $r->print(&mt('Associate columns with student attributes.')."\n". - ''. + &start_data_table().&start_data_table_header_row(). ''. - ''."\n"); + ''. + &end_data_table_header_row()."\n"); foreach my $array_ref (@$d) { my ($value,$display,$defaultcol)=@{ $array_ref }; - $r->print(''); + $r->print(&start_data_table_row().''); $r->print(''."\n"); + $r->print(''.&end_data_table_row()."\n"); $i++; } + $r->print(&end_data_table()); $i--; return $i; } @@ -6170,11 +6865,13 @@ sub csv_samples_select_table { my $i=0; # my $samples = &get_samples($records,3); - $r->print('
'.&mt('Attribute').''.&mt('Column').'
'.&mt('Column').'
'.$display.'
'.$display.'
'); + $r->print(&start_data_table(). + &start_data_table_header_row().''. + &end_data_table_header_row()); foreach my $key (sort(keys(%{ $samples->[0] }))) { - $r->print(''); + $r->print(''.&end_data_table_row()); $i++; } + $r->print(&end_data_table()); $i--; return($i); } @@ -6876,6 +7574,45 @@ sub commit_studentrole { ############################################################ ############################################################ +sub check_clone { + my ($args,$linefeed) = @_; + my $cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'}; + my ($clonecrsudom,$clonecrsunum)= &LONCAPA::split_courseid($cloneid); + my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom); + my $clonemsg; + my $can_clone = 0; + + if ($clonehome eq 'no_host') { + $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'}) { + $can_clone = 1; + } else { + my %clonehash = &Apache::lonnet::get('environment',['cloners'], + $args->{'clonedomain'},$args->{'clonecourse'}); + my @cloners = split(/,/,$clonehash{'cloners'}); + 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); +} + sub construct_course { my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context) = @_; my $outcome; @@ -6883,6 +7620,25 @@ sub construct_course { if ($context eq 'auto') { $linefeed = "\n"; } + +# +# Are we cloning? +# + my ($can_clone, $clonemsg, $cloneid, $clonehome); + if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) { + ($can_clone, $clonemsg, $cloneid, $clonehome) = &check_clone($args,$linefeed); + if ($context ne 'auto') { + if ($clonemsg ne '') { + $clonemsg = ''.$clonemsg.''; + } + } + $outcome .= $clonemsg.$linefeed; + + if (!$can_clone) { + return (0,$outcome); + } + } + # # Open course # @@ -6903,81 +7659,39 @@ sub construct_course { # if anyone ever decides to not show this, and Utils::Course::new # will need to be suitably modified. $outcome .= &mt('New LON-CAPA [_1] ID: [_2]',$crstype,$$courseid).$linefeed; - # # Check if created correctly # ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid); my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom); $outcome .= &mt('Created on').': '.$crsuhome.$linefeed; + # -# Are we cloning? -# - my $cloneid=''; - if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) { - my $can_clone = 0; - $cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'}; - my ($clonecrsudom,$clonecrsunum)= &LONCAPA::split_courseid($cloneid); - my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom); - my $clonemsg; - if ($clonehome eq 'no_host') { - $clonemsg = &mt('Attempting to clone non-existing [_1]',$crstype); - if ($context eq 'auto') { - $outcome .= $clonemsg; - } else { - $outcome .= ''.$clonemsg.''; - } - $outcome .= $linefeed; - } else { - my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1}); - if ($env{'request.role.domain'} eq $args->{'form.clonedomain'}) { - $can_clone = 1; - } else { - 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 course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'}); - if ($context eq 'auto') { - $outcome .= $clonemsg; - } else { - $outcome .= ''.$clonemsg.''; - } - $outcome .= $linefeed; - } - } - } - if ($can_clone) { - $clonemsg = &mt('Cloning [_1] from [_2]',$crstype,$clonehome); - if ($context eq 'auto') { - $outcome = $clonemsg; - } else { - $outcome .= ''.$clonemsg.''; - } - $outcome .= $linefeed; - my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum); +# Do the cloning +# + if ($can_clone && $cloneid) { + $clonemsg = &mt('Cloning [_1] from [_2]',$crstype,$clonehome); + if ($context ne 'auto') { + $clonemsg = ''.$clonemsg.''; + } + $outcome .= $clonemsg.$linefeed; + my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum); # Copy all files - &Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid); + &Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid); # Restore URL - $cenv{'url'}=$oldcenv{'url'}; + $cenv{'url'}=$oldcenv{'url'}; # Restore title - $cenv{'description'}=$oldcenv{'description'}; + $cenv{'description'}=$oldcenv{'description'}; # restore grading mode - if (defined($oldcenv{'grading'})) { - $cenv{'grading'}=$oldcenv{'grading'}; - } -# Mark as cloned - $cenv{'clonedfrom'}=$cloneid; - delete($cenv{'default_enrollment_start_date'}); - delete($cenv{'default_enrollment_end_date'}); + if (defined($oldcenv{'grading'})) { + $cenv{'grading'}=$oldcenv{'grading'}; } +# Mark as cloned + $cenv{'clonedfrom'}=$cloneid; + delete($cenv{'default_enrollment_start_date'}); + delete($cenv{'default_enrollment_end_date'}); } + # # Set environment (will override cloned, if existing) # @@ -7085,7 +7799,7 @@ sub construct_course { ' ('.$lt{'adby'}.')'; if ($context eq 'auto') { $outcome .= $badclass_msg.$linefeed; - $outcome .= ''.$badclass_msg.$linefeed.'
    '."\n"; + $outcome .= '
    '.$badclass_msg.$linefeed.'
      '."\n"; foreach my $item (@badclasses) { if ($context eq 'auto') { $outcome .= " - $item\n"; @@ -7096,7 +7810,7 @@ sub construct_course { if ($context eq 'auto') { $outcome .= $linefeed; } else { - $outcome .= "


    \n"; + $outcome .= "


\n"; } } } @@ -7118,7 +7832,7 @@ sub construct_course { if ($context eq 'auto') { $outcome .= $krb_msg; } else { - $outcome .= ''.$krb_msg.''; + $outcome .= ''.$krb_msg.''; } $outcome .= $linefeed; } @@ -7216,7 +7930,8 @@ sub construct_course { if ($errtext) { $fatal=2; } $outcome .= ($fatal?$errtext:'write ok').$linefeed; } - return $outcome; + + return (1,$outcome); } ############################################################ @@ -7259,10 +7974,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; }
'. - &mt('Field').''.&mt('Samples').'
'. + &mt('Field').''.&mt('Samples').'