--- loncom/interface/loncommon.pm 2008/07/08 00:49:18 1.666 +++ loncom/interface/loncommon.pm 2009/08/14 03:48:49 1.692.4.4 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.666 2008/07/08 00:49:18 raeburn Exp $ +# $Id: loncommon.pm,v 1.692.4.4 2009/08/14 03:48:49 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -61,6 +61,7 @@ use POSIX qw(strftime mktime); use Apache::lonmenu(); use Apache::lonenc(); use Apache::lonlocal; +use Apache::lonnet(); use HTML::Entities; use Apache::lonhtmlcommon(); use Apache::loncoursedata(); @@ -68,6 +69,7 @@ use Apache::lontexconvert(); use Apache::lonclonecourse(); use LONCAPA qw(:DEFAULT :match); use DateTime::TimeZone; +use DateTime::Locale::Catalog; # ---------------------------------------------- Designs use vars qw(%defaultdesign); @@ -404,9 +406,10 @@ sub studentbrowser_javascript { || ($env{'request.role'}=~/^(au|dc|su)/) ) { return ''; } return (<<'ENDSTDBRW'); - ENDSTDBRW } sub selectstudent_link { - my ($form,$unameele,$udomele)=@_; + my ($form,$unameele,$udomele,$courseadvonly)=@_; + my $callargs = "'".$form."','".$unameele."','".$udomele."'"; if ($env{'request.course.id'}) { if (!&Apache::lonnet::allowed('srm',$env{'request.course.id'}) && !&Apache::lonnet::allowed('srm',$env{'request.course.id'}. '/'.$env{'request.course.sec'})) { return ''; } - return "".&mt('Select User').""; + if ($courseadvonly) { + $callargs .= ",'',1,1"; + } + return ''. + ''. + &mt('Select User').''; } if ($env{'request.role'}=~/^(au|dc|su)/) { - return "".&mt('Select User').""; + $callargs .= ",1"; + return ''. + ''. + &mt('Select User').''; } return ''; } @@ -451,6 +463,7 @@ sub selectstudent_link { sub authorbrowser_javascript { return <<"ENDAUTHORBRW"; ENDAUTHORBRW } @@ -471,7 +484,8 @@ sub coursebrowser_javascript { my ($domainfilter,$sec_element,$formname)=@_; my $crs_or_grp_alert = &mt('Please select the type of LON-CAPA entity - Course or Group - for which you wish to add/modify a user role'); my $output = ' -'; return $output; } @@ -600,8 +615,13 @@ function setSect(sectionlist) { sub selectcourse_link { my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype)=@_; - return "".&mt('Select Course').""; + return '' + ."".&mt('Select Course').'' + .''; } sub selectauthor_link { @@ -657,6 +677,72 @@ sub select_timezone { return $output; } +sub select_datelocale { + my ($name,$selected,$onchange,$includeempty)=@_; + my $output='"; + $output.="\n".''; + ''; } sub gradeleveldescription { @@ -1682,7 +1787,7 @@ sub select_level_form { =pod -=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc) +=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$autosubmit) Returns a string containing a \n"; + my $selectdomain = "'."\n"; if ($default) { - $result .= ''."\n"; } foreach my $hostid (sort(keys(%servers))) { @@ -2051,14 +2162,14 @@ sub authform_kerberos { $autharg,$jscall); my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); if ($in{'kerb_def_auth'} eq 'krb5') { - $check5 = ' checked="on"'; + $check5 = ' checked="checked"'; } else { - $check4 = ' checked="on"'; + $check4 = ' checked="checked"'; } $krbarg = $in{'kerb_def_dom'}; if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'krb') { - $krbcheck = ' checked="on"'; + $krbcheck = ' checked="checked"'; if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifyuser') { $krbcheck = ''; @@ -2066,10 +2177,10 @@ sub authform_kerberos { } if (defined($in{'curr_kerb_ver'})) { if ($in{'curr_krb_ver'} eq '5') { - $check5 = ' checked="on"'; + $check5 = ' checked="checked"'; $check4 = ''; } else { - $check4 = ' checked="on"'; + $check4 = ' checked="checked"'; $check5 = ''; } } @@ -2090,7 +2201,7 @@ sub authform_kerberos { } } else { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } if (!$can_assign{'krb4'} && !$can_assign{'krb5'}) { @@ -2099,7 +2210,7 @@ sub authform_kerberos { if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } } @@ -2160,7 +2271,7 @@ sub authform_internal{ if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'int') { if ($can_assign{'int'}) { - $intcheck = 'checked="on" '; + $intcheck = 'checked="checked" '; if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifyuser') { $intcheck = ''; @@ -2176,7 +2287,7 @@ sub authform_internal{ } } else { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } if (!$can_assign{'int'}) { @@ -2185,7 +2296,7 @@ sub authform_internal{ if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } } @@ -2200,7 +2311,7 @@ sub authform_internal{ $result = &mt ('[_1] Internally authenticated (with initial password [_2])', ''.$autharg); - $result.="'; + $result.="'; return $result; } @@ -2215,7 +2326,7 @@ sub authform_local{ if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'loc') { if ($can_assign{'loc'}) { - $loccheck = 'checked="on" '; + $loccheck = 'checked="checked" '; if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifyuser') { $loccheck = ''; @@ -2231,7 +2342,7 @@ sub authform_local{ } } else { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } if (!$can_assign{'loc'}) { @@ -2240,7 +2351,7 @@ sub authform_local{ if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } } @@ -2269,7 +2380,7 @@ sub authform_filesystem{ if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'fsys') { if ($can_assign{'fsys'}) { - $fsyscheck = 'checked="on" '; + $fsyscheck = 'checked="checked" '; if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifyuser') { $fsyscheck = ''; @@ -2282,7 +2393,7 @@ sub authform_filesystem{ } } else { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } if (!$can_assign{'fsys'}) { @@ -2291,7 +2402,7 @@ sub authform_filesystem{ if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = ''; + $authtype = ''; } } } @@ -2659,6 +2770,43 @@ sub flush_email_cache { &Apache::lonnet::devalidate_cache_new('emailscache',$id); } +# -------------------------------------------------------------------- getlangs + +=pod + +=item * &getlangs($uname,$udom) + +Gets a user's language preference and returns it as a hash with key: +language. + +=cut + + +sub getlangs { + my ($uname,$udom) = @_; + if (!$udom) { $udom =$env{'user.domain'}; } + if (!$uname) { $uname=$env{'user.name'}; } + my $id=$uname.':'.$udom; + my ($langs,$cached)=&Apache::lonnet::is_cached_new('userlangs',$id); + if ($cached) { + return %{$langs}; + } else { + my %loadlangs=&Apache::lonnet::get('environment',['languages'], + $udom,$uname); + &Apache::lonnet::do_cache_new('userlangs',$id,\%loadlangs); + return %loadlangs; + } +} + +sub flush_langs_cache { + my ($uname,$udom)=@_; + if (!$udom) { $udom =$env{'user.domain'}; } + if (!$uname) { $uname=$env{'user.name'}; } + return if ($udom eq 'public' && $uname eq 'public'); + my $id=$uname.':'.$udom; + &Apache::lonnet::devalidate_cache_new('userlangs',$id); +} + # ------------------------------------------------------------------ Screenname =pod @@ -2677,6 +2825,25 @@ sub screenname { return $names{'screenname'}; } +# ------------------------------------------------------------- Confirm Wrapper +=pod + +=item confirmwrapper + +Wrap messages about completion of operation in box + +=cut + +sub confirmwrapper { + my ($message)=@_; + if ($message) { + return "\n".'
'."\n" + .$message."\n" + .'
'."\n"; + } else { + return $message; + } +} # ------------------------------------------------------------- Message Wrapper @@ -2703,7 +2870,7 @@ sub aboutmewrapper { return; } return ''.$link.''; + ($target?' target="$target"':'').' title="'.&mt("View this user's personal information page").'">'.$link.''; } # ------------------------------------------------------------ Syllabus Wrapper @@ -2738,6 +2905,27 @@ sub track_student_link { &help_open_topic('View_recent_activity'); } +sub slot_reservations_link { + my ($linktext,$sname,$sdom,$target) = @_; + my $link ="/adm/slotrequest?command=showresv&origin=aboutme"; + my $title = 'View slot reservation history'; + if (defined($sname) && $sname !~ /^\s*$/ && + defined($sdom) && $sdom !~ /^\s*$/) { + $link .= "&uname=$sname&udom=$sdom"; + $title .= ' of this student'; + } + if (defined($target) && $target !~ /^\s*$/) { + $target = qq{target="$target"}; + } else { + $target = ''; + } + $title = &mt($title); + $linktext = &mt($linktext); + return qq{$linktext}; +# FIXME uncomment when help item created: &help_open_topic('Slot_Reservation_History'); + +} + # ===================================================== Display a student photo @@ -2940,7 +3128,7 @@ sub fileextensions { sub display_languages { my %languages=(); - foreach my $lang (&preferred_languages()) { + foreach my $lang (&Apache::lonlocal::preferred_languages()) { $languages{$lang}=1; } &get_unprocessed_cgi($ENV{'QUERY_STRING'},['displaylanguage']); @@ -2952,54 +3140,9 @@ sub display_languages { return %languages; } -sub preferred_languages { - my @languages=(); - if (($env{'request.role.adv'}) && ($env{'form.languages'})) { - @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$env{'form.languages'})); - } - if ($env{'course.'.$env{'request.course.id'}.'.languages'}) { - @languages=(@languages,split(/\s*(\,|\;|\:)\s*/, - $env{'course.'.$env{'request.course.id'}.'.languages'})); - } - - if ($env{'environment.languages'}) { - @languages=(@languages, - split(/\s*(\,|\;|\:)\s*/,$env{'environment.languages'})); - } - my $browser=$ENV{'HTTP_ACCEPT_LANGUAGE'}; - if ($browser) { - my @browser = - map { (split(/\s*;\s*/,$_))[0] } (split(/\s*,\s*/,$browser)); - push(@languages,@browser); - } - - foreach my $domtype ($env{'user.domain'},$env{'request.role.domain'}, - $Apache::lonnet::perlvar{'lonDefDomain'}) { - if ($domtype ne '') { - my %domdefs = &Apache::lonnet::get_domain_defaults($domtype); - if ($domdefs{'lang_def'} ne '') { - push(@languages,$domdefs{'lang_def'}); - } - } - } -# turn "en-ca" into "en-ca,en" - my @genlanguages; - foreach my $lang (@languages) { - unless ($lang=~/\w/) { next; } - 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(); + my @preferred_langs = &Apache::lonlocal::preferred_languages(); if (!ref($possible_langs)) { if( wantarray ) { return @preferred_langs; @@ -3020,6 +3163,28 @@ sub languages { return $preferred_possibilities[0]; } +sub user_lang { + my ($touname,$toudom,$fromcid) = @_; + my @userlangs; + if (($fromcid ne '') && ($env{'course.'.$fromcid.'.languages'} ne '')) { + @userlangs=(@userlangs,split(/\s*(\,|\;|\:)\s*/, + $env{'course.'.$fromcid.'.languages'})); + } else { + my %langhash = &getlangs($touname,$toudom); + if ($langhash{'languages'} ne '') { + @userlangs = split(/\s*(\,|\;|\:)\s*/,$langhash{'languages'}); + } else { + my %domdefs = &Apache::lonnet::get_domain_defaults($toudom); + if ($domdefs{'lang_def'} ne '') { + @userlangs = ($domdefs{'lang_def'}); + } + } + } + my @languages=&Apache::lonlocal::get_genlanguages(@userlangs); + my $user_lh = Apache::localize->get_handle(@languages); + return $user_lh; +} + ############################################################### ## Student Answer Attempts ## ############################################################### @@ -3158,7 +3323,7 @@ sub relative_to_absolute { } $thisdir=~s-/[^/]*$--; foreach my $link (@rlinks) { - unless (($link=~/^http:\/\//i) || + unless (($link=~/^https?\:\/\//i) || ($link=~/^\//) || ($link=~/^javascript:/i) || ($link=~/^mailto:/i) || @@ -3343,16 +3508,21 @@ sub pprmlink { sub timehash { - my @ltime=localtime(shift); - return ( 'seconds' => $ltime[0], - 'minutes' => $ltime[1], - 'hours' => $ltime[2], - 'day' => $ltime[3], - 'month' => $ltime[4]+1, - 'year' => $ltime[5]+1900, - 'weekday' => $ltime[6], - 'dayyear' => $ltime[7]+1, - 'dlsav' => $ltime[8] ); + my ($thistime) = @_; + my $timezone = &Apache::lonlocal::gettimezone(); + my $dt = DateTime->from_epoch(epoch => $thistime) + ->set_time_zone($timezone); + my $wday = $dt->day_of_week(); + if ($wday == 7) { $wday = 0; } + return ( 'second' => $dt->second(), + 'minute' => $dt->minute(), + 'hour' => $dt->hour(), + 'day' => $dt->day_of_month(), + 'month' => $dt->month(), + 'year' => $dt->year(), + 'weekday' => $wday, + 'dayyear' => $dt->day_of_year(), + 'dlsav' => $dt->is_dst() ); } sub utc_string { @@ -3362,6 +3532,24 @@ sub utc_string { sub maketime { my %th=@_; + my ($epoch_time,$timezone,$dt); + $timezone = &Apache::lonlocal::gettimezone(); + eval { + $dt = DateTime->new( year => $th{'year'}, + month => $th{'month'}, + day => $th{'day'}, + hour => $th{'hour'}, + minute => $th{'minute'}, + second => $th{'second'}, + time_zone => $timezone, + ); + }; + if (!$@) { + $epoch_time = $dt->epoch; + if ($epoch_time) { + return $epoch_time; + } + } return POSIX::mktime( ($th{'seconds'},$th{'minutes'},$th{'hours'}, $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,-1)); @@ -3712,7 +3900,7 @@ sub blocking_status { &Apache::lonnet::coursedescription($course); $coursedesc = $courseinfo{'description'}; } - $category = "Group files in the course '$coursedesc'"; + $category = "Group portfolio files in the course '$coursedesc'"; } else { $category = 'Portfolio files belonging to '; if ($env{'user.name'} eq 'public' && @@ -3742,6 +3930,60 @@ sub blocking_status { ############################################### +sub check_ip_acc { + my ($acc)=@_; + &Apache::lonxml::debug("acc is $acc"); + if (!defined($acc) || $acc =~ /^\s*$/ || $acc =~/^\s*no\s*$/i) { + return 1; + } + my $allowed=0; + my $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'}; + + my $name; + foreach my $pattern (split(',',$acc)) { + $pattern =~ s/^\s*//; + $pattern =~ s/\s*$//; + if ($pattern =~ /\*$/) { + #35.8.* + $pattern=~s/\*//; + if ($ip =~ /^\Q$pattern\E/) { $allowed=1; } + } elsif ($pattern =~ /(\d+\.\d+\.\d+)\.\[(\d+)-(\d+)\]$/) { + #35.8.3.[34-56] + my $low=$2; + my $high=$3; + $pattern=$1; + if ($ip =~ /^\Q$pattern\E/) { + my $last=(split(/\./,$ip))[3]; + if ($last <=$high && $last >=$low) { $allowed=1; } + } + } elsif ($pattern =~ /^\*/) { + #*.msu.edu + $pattern=~s/\*//; + if (!defined($name)) { + use Socket; + my $netaddr=inet_aton($ip); + ($name)=gethostbyaddr($netaddr,AF_INET); + } + if ($name =~ /\Q$pattern\E$/i) { $allowed=1; } + } elsif ($pattern =~ /\d+\.\d+\.\d+\.\d+/) { + #127.0.0.1 + if ($ip =~ /^\Q$pattern\E/) { $allowed=1; } + } else { + #some.name.com + if (!defined($name)) { + use Socket; + my $netaddr=inet_aton($ip); + ($name)=gethostbyaddr($netaddr,AF_INET); + } + if ($name =~ /\Q$pattern\E$/i) { $allowed=1; } + } + if ($allowed) { last; } + } + return $allowed; +} + +############################################### + =pod =head1 Domain Template Functions @@ -3790,7 +4032,14 @@ sub get_domainconf { if (ref($domconfig{'login'}) eq 'HASH') { if (keys(%{$domconfig{'login'}})) { foreach my $key (keys(%{$domconfig{'login'}})) { - $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key}; + if (ref($domconfig{'login'}{$key}) eq 'HASH') { + foreach my $img (keys(%{$domconfig{'login'}{$key}})) { + $designhash{$udom.'.login.'.$key.'_'.$img} = + $domconfig{'login'}{$key}{$img}; + } + } else { + $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key}; + } } } else { $legacy{'login'} = 1; @@ -4012,7 +4261,7 @@ sub bodytag { my $font = &designparm($function.'.font',$domain); my $pgbg = $bgcolor || &designparm($function.'.pgbg',$domain); - my %design = ( 'style' => 'margin-top: 0px', + my %design = ( 'style' => 'margin-top: 0', 'bgcolor' => $pgbg, 'text' => $font, 'alink' => &designparm($function.'.alink',$domain), @@ -4314,10 +4563,11 @@ sub standard_css { my $mail_other_hover = '#669999'; my $table_header = '#DDDDDD'; my $feedback_link_bg = '#BBBBBB'; + my $lg_border_color = '#C8C8C8'; my $border = ($env{'browser.type'} eq 'explorer' || - $env{'browser.type'} eq 'safari' ) ? '0px 2px 0px 2px' - : '0px 3px 0px 4px'; + $env{'browser.type'} eq 'safari' ) ? '0 2px 0 2px' + : '0 3px 0 4px'; return < td { + background-color: #CCCCCC; + font-weight: bold; + text-align: left; +} table.LC_data_table tr.LC_odd_row > td, +table.LC_pick_box tr > td.LC_odd_row, table.LC_aboutme_port tr td { background-color: $data_table_light; padding: 2px; } table.LC_data_table tr.LC_even_row > td, +table.LC_pick_box tr > td.LC_even_row, table.LC_aboutme_port tr.LC_even_row td { background-color: $data_table_dark; + padding: 2px; } table.LC_data_table tr.LC_data_table_highlight td { background-color: $data_table_darker; @@ -4646,7 +4887,7 @@ table.LC_nested_outer tr td.LC_subheader text-align: right; } table.LC_nested tr.LC_info_row td { - background-color: #CCC; + background-color: #CCCCCC; font-weight: bold; font-size: small; text-align: center; @@ -4656,7 +4897,7 @@ table.LC_nested_outer tr th.LC_left_item text-align: left; } table.LC_nested td { - background-color: #FFF; + background-color: #FFFFFF; font-size: small; } table.LC_nested_outer tr th.LC_right_item, @@ -4667,7 +4908,7 @@ table.LC_nested tr td.LC_right_item { } table.LC_nested tr.LC_odd_row td { - background-color: #EEE; + background-color: #EEEEEE; } table.LC_createuser { @@ -4678,7 +4919,7 @@ table.LC_createuser tr.LC_section_row td } table.LC_createuser tr.LC_info_row td { - background-color: #CCC; + background-color: #CCCCCC; font-weight: bold; text-align: center; } @@ -4734,10 +4975,10 @@ table.LC_mail_list tr.LC_mail_odd { table#LC_portfolio_actions { width: auto; background: $pgbg; - border: 0px; + border: none; border-spacing: 2px 2px; - padding: 0px; - margin: 0px; + padding: 0; + margin: 0; border-collapse: separate; } table#LC_portfolio_actions td.LC_label { @@ -4793,6 +5034,26 @@ table#LC_browser tr.LC_browser_file_meta table#LC_browser tr.LC_browser_folder { background: #CCCCFF; } + +table.LC_data_table tr > td.LC_roles_is { +/* background: #77FF77; */ +} +table.LC_data_table tr > td.LC_roles_future { + background: #FFFF77; +} +table.LC_data_table tr > td.LC_roles_will { + background: #FFAA77; +} +table.LC_data_table tr > td.LC_roles_expired { + background: #FF7777; +} +table.LC_data_table tr > td.LC_roles_will_not { + background: #AAFF77; +} +table.LC_data_table tr > td.LC_roles_selected { + background: #11CC55; +} + span.LC_current_location { font-size: x-large; background: $pgbg; @@ -4838,9 +5099,9 @@ table.LC_parm_overview_restrictions th { border-color: $pgbg; } table#LC_helpmenu { - border: 0px; + border: none; height: 55px; - border-spacing: 0px; + border-spacing: 0; } table#LC_helpmenu fieldset legend { @@ -4851,7 +5112,7 @@ table#LC_helpmenu_links { width: 100%; border: 1px solid black; background: $pgbg; - padding: 0px; + padding: 0; border-spacing: 1px; } table#LC_helpmenu_links tr td { @@ -4893,6 +5154,7 @@ table.LC_pick_box td.LC_pick_box_title { background: $tabbg; font-weight: bold; text-align: right; + vertical-align: top; width: 184px; padding: 8px; } @@ -4913,7 +5175,7 @@ table.LC_pick_box td.LC_pick_box_select padding: 8px; } table.LC_pick_box td.LC_pick_box_separator { - padding: 0px; + padding: 0; height: 1px; background: black; } @@ -4955,7 +5217,7 @@ table.LC_helpform_receipt td.LC_oddrow_v background-color: $data_table_light; } table.LC_helpform_receipt td.LC_pick_box_separator { - padding: 0px; + padding: 0; height: 1px; background: black; } @@ -4988,7 +5250,7 @@ table.LC_group_priv_box td.LC_groups_fun } table.LC_group_priv td { text-align: left; - padding: 0px; + padding: 0; } table.LC_notify_front_page { @@ -5009,6 +5271,7 @@ table.LC_notify_front_page td { background: $tabbg; vertical-align: middle; margin: 2ex 0ex 2ex 0ex; + padding: 3px; } .LC_topic_bar span { vertical-align: middle; @@ -5125,7 +5388,7 @@ span.LC_cusr_subheading { table.LC_docs_documents { background: #BBBBBB; - border-width: 0px; + border-width: 0; border-collapse: collapse; } @@ -5142,7 +5405,7 @@ table.LC_docs_documents td.LC_docs_docum } .LC_docs_entry_move { - border: 0px; + border: none; border-collapse: collapse; } @@ -5198,7 +5461,7 @@ table.LC_sty_end { } table.LC_double_column { - border-width: 0px; + border-width: 0; border-collapse: collapse; width: 100%; padding: 2px; @@ -5337,7 +5600,7 @@ table.LC_edit_problem_header_title { background: $tabbg; border-collapse: collapse; - padding: 0px + padding: 0; } div.LC_edit_problem_discards { @@ -5353,8 +5616,39 @@ hr.LC_edit_problem_divide { color: $tabbg; background-color: $tabbg; height: 3px; - border: 0px; + border: none; +} +img.stift{ + border-width:0; + vertical-align:middle; +} + +table#LC_mainmenu{ + margin-top:10px; + width:80%; + +} + +table#LC_mainmenu td.LC_mainmenu_col_fieldset{ + vertical-align: top; + width: 45%; +} +.LC_mainmenu_fieldset_category { + color: $font; + background: $pgbg; + font-family: $sans; + font-size: small; + font-weight: bold; } +fieldset#LC_mainmenu_fieldset { + margin:0 10px 10px 0; + +} + +div.LC_createcourse { + margin: 10px 10px 10px 10px; +} + END } @@ -5623,10 +5917,26 @@ sub start_page { if ($args->{'html_encode'}) { $result = &html_encode($result); } + #Breadcrumbs + if (exists($args->{'bread_crumbs'}) or exists($args->{'bread_crumbs_component'})) { + &Apache::lonhtmlcommon::clear_breadcrumbs(); + #if any br links exists, add them to the breadcrumbs + if (exists($args->{'bread_crumbs'}) and ref($args->{'bread_crumbs'}) eq 'ARRAY') { + foreach my $crumb (@{$args->{'bread_crumbs'}}){ + &Apache::lonhtmlcommon::add_breadcrumb($crumb); + } + } + + #if bread_crumbs_component exists show it as headline else show only the breadcrumbs + if (exists($args->{'bread_crumbs_component'})){ + $result .= &Apache::lonhtmlcommon::breadcrumbs($args->{'bread_crumbs_component'}); + } else { + $result .= &Apache::lonhtmlcommon::breadcrumbs(); + } + } return $result; } - =pod =item * &head() @@ -5868,6 +6178,37 @@ sub get_users_function { =pod +=item * &show_course() + +Used by lonmenu.pm and lonroles.pm to determine whether to use the word +'Courses' or 'Roles' in inline navigation and on screen displaying user's roles. +Inputs: +None + +Outputs: +Scalar: 1 if 'Course' to be used, 0 otherwise. + +=cut + +############################################### +sub show_course { + my $course = !$env{'user.adv'}; + if (!$env{'user.adv'}) { + foreach my $env (keys(%env)) { + next if ($env !~ m/^user\.priv\./); + if ($env !~ m/^user\.priv\.(?:st|cm)/) { + $course = 0; + last; + } + } + } + return $course; +} + +############################################### + +=pod + =item * &check_user_status() Determines current status of supplied role for a @@ -6383,21 +6724,37 @@ sub default_quota { ['quotas'],$udom); if (ref($quotahash{'quotas'}) eq 'HASH') { if ($inststatus ne '') { - my @statuses = split(/:/,$inststatus); + my @statuses = map { &unescape($_); } split(/:/,$inststatus); foreach my $item (@statuses) { - if ($quotahash{'quotas'}{$item} ne '') { - if ($defquota eq '') { - $defquota = $quotahash{'quotas'}{$item}; - $settingstatus = $item; - } elsif ($quotahash{'quotas'}{$item} > $defquota) { - $defquota = $quotahash{'quotas'}{$item}; - $settingstatus = $item; + if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') { + if ($quotahash{'quotas'}{'defaultquota'}{$item} ne '') { + if ($defquota eq '') { + $defquota = $quotahash{'quotas'}{'defaultquota'}{$item}; + $settingstatus = $item; + } elsif ($quotahash{'quotas'}{'defaultquota'}{$item} > $defquota) { + $defquota = $quotahash{'quotas'}{'defaultquota'}{$item}; + $settingstatus = $item; + } + } + } else { + if ($quotahash{'quotas'}{$item} ne '') { + if ($defquota eq '') { + $defquota = $quotahash{'quotas'}{$item}; + $settingstatus = $item; + } elsif ($quotahash{'quotas'}{$item} > $defquota) { + $defquota = $quotahash{'quotas'}{$item}; + $settingstatus = $item; + } } } } } if ($defquota eq '') { - $defquota = $quotahash{'quotas'}{'default'}; + if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') { + $defquota = $quotahash{'quotas'}{'defaultquota'}{'default'}; + } else { + $defquota = $quotahash{'quotas'}{'default'}; + } $settingstatus = 'default'; } } else { @@ -6546,12 +6903,14 @@ sub user_picker { if ($cancreate) { $new_user_create = '

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

'; } else { - my $helplink = ' href="javascript:helpMenu('."'display'".')"'; + my $helplink = 'javascript:helpMenu('."'display'".')'; my %usertypetext = ( official => 'institutional', unofficial => 'non-institutional', ); - $new_user_create = '
'.&mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.").' '.&mt('Contact the helpdesk for assistance.',$helplink).'

'; + $new_user_create = '

'. + &mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.").' '. + &mt('Please contact the [_1]helpdesk[_2] for assistance.','','').'


'; } } } @@ -6588,6 +6947,7 @@ ENDSCRIPT my $output = <<"END_BLOCK"; $new_user_create @@ -6803,12 +7164,16 @@ sub instrule_disallow_msg { $text{'action'} = 'IDs'; } } - $response = &mt("The $text{'item'} you chose $text{'match'} the format of $text{'items'} defined for [_1], but the $text{'item'} $text{'do'} not exist in the institutional directory.",$domdesc).'
'; + $response = &mt("The $text{'item'} you chose $text{'match'} the format of $text{'items'} defined for [_1], but the $text{'item'} $text{'do'} not exist in the institutional directory.",''.$domdesc.'').'
'; if ($mode eq 'upload') { if ($checkitem eq 'username') { $response .= &mt("You will need to modify your upload file so it will include $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}."); } elsif ($checkitem eq 'id') { - $response .= &mt("Either upload a file which includes $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}, or when associating fields with data columns, omit an association for the ID/Student Number field."); + $response .= &mt("Either upload a file which includes $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}, or when associating fields with data columns, omit an association for the Student/Employee ID field."); + } + } elsif ($mode eq 'selfcreate') { + if ($checkitem eq 'id') { + $response .= &mt("You must either choose $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}, or leave the ID field blank."); } } else { if ($checkitem eq 'username') { @@ -6829,6 +7194,7 @@ sub personal_data_fieldtitles { middlename => 'Middle Name', generation => 'Generation', gen => 'Generation', + inststatus => 'Affiliation', ); return %fieldtitles; } @@ -6838,7 +7204,7 @@ sub sorted_inst_types { my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom); my $othertitle = &mt('All users'); if ($env{'request.course.id'}) { - $othertitle = 'any'; + $othertitle = &mt('Any users'); } my @types; if (ref($order) eq 'ARRAY') { @@ -6851,9 +7217,6 @@ sub sorted_inst_types { } if (keys(%{$usertypes}) > 0) { $othertitle = &mt('Other users'); - if ($env{'request.course.id'}) { - $othertitle = 'other'; - } } return ($othertitle,$usertypes,\@types); } @@ -6901,6 +7264,56 @@ sub get_institutional_codes { =pod +=head1 Slot Helpers + +=over 4 + +=item * sorted_slots() + +Sorts an array of slot names in order of slot start time (earliest first). + +Inputs: + +=over 4 + +slotsarr - Reference to array of unsorted slot names. + +slots - Reference to hash of hash, where outer hash keys are slot names. + +=back + +Returns: + +=over 4 + +sorted - An array of slot names sorted by the start time of the slot. + +=back + +=back + +=cut + + +sub sorted_slots { + my ($slotsarr,$slots) = @_; + my @sorted; + if ((ref($slotsarr) eq 'ARRAY') && (ref($slots) eq 'HASH')) { + @sorted = + sort { + if (ref($slots->{$a}) && ref($slots->{$b})) { + return $slots->{$a}{'starttime'} <=> $slots->{$b}{'starttime'} + } + if (ref($slots->{$a})) { return -1;} + if (ref($slots->{$b})) { return 1;} + return 0; + } @{$slotsarr}; + } + return @sorted; +} + +=pod + =back =head1 HTTP Helpers @@ -7242,7 +7655,6 @@ sub check_for_upload { } } } - my $getpropath = 1; if (($current_disk_usage + $filesize) > $disk_quota){ my $msg = ''. &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.',''.$fname.'',$filesize).''. @@ -7454,7 +7866,7 @@ sub upfile_select_html { # xml => &mt('HTML/XML'), ); my $Str = ''. - '
Type: '; foreach my $type (sort(keys(%Types))) { $Str .= '\n"; } @@ -7542,7 +7954,7 @@ sub csv_print_select_table { &end_data_table_header_row()."\n"); foreach my $array_ref (@$d) { my ($value,$display,$defaultcol)=@{ $array_ref }; - $r->print(&start_data_table_row().''.$display.''); + $r->print(&start_data_table_row().''.$display.''); $r->print(''.&escape($parent).''; + $output .= ''. + ''.$parent.''. + ''; my $depth = 1; push(@path,$parent); $output .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories); @@ -8574,7 +8994,9 @@ sub assign_category_rows { } $text .= ''; + $item.'"'.$checked.' />'.$name.''. + ''. + ''; if (ref($path) eq 'ARRAY') { push(@{$path},$name); $text .= &assign_category_rows($itemcount,$cats,$deeper,$name,$path,$currcategories); @@ -8873,7 +9295,9 @@ sub construct_course { 'policy.email', 'comment.email', 'pch.users.denied', - 'plc.users.denied'], + 'plc.users.denied', + 'hidefromcat', + 'categories'], $$crsudom,$$crsunum); } @@ -9101,10 +9525,10 @@ sub construct_course { $outcome .= ($fatal?$errtext:'read ok').' - '; my $title; my $url; if ($args->{'firstres'} eq 'syl') { - $title='Syllabus'; + $title=&mt('Syllabus'); $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus'; } else { - $title='Navigate Contents'; + $title=&mt('Navigate Contents'); $url='/adm/navmaps'; } @@ -9158,28 +9582,14 @@ sub icon { return &lonhttpdurl($iconname); } -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 { +# +# Had been used for "small fry" static images on separate port 8080. +# Modify here if lightweight http functionality desired again. +# Currently eliminated due to increasing firewall issues. +# 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; + return $url; } sub connection_aborted { @@ -9215,6 +9625,22 @@ sub escape_url { return join('/',@urlslices).'/'.$lastitem; } +sub compare_arrays { + my ($arrayref1,$arrayref2) = @_; + my (@difference,%count); + @difference = (); + %count = (); + if ((ref($arrayref1) eq 'ARRAY') && (ref($arrayref2) eq 'ARRAY')) { + foreach my $element (@{$arrayref1}, @{$arrayref2}) { $count{$element}++; } + foreach my $element (keys(%count)) { + if ($count{$element} == 1) { + push(@difference,$element); + } + } + } + return @difference; +} + # -------------------------------------------------------- Initliaze user login sub init_user_environment { my ($r, $username, $domain, $authhost, $form, $args) = @_; @@ -9257,7 +9683,7 @@ sub init_user_environment { } # Give them a new cookie my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'} - : $now); + : $now.$$.int(rand(10000))); $cookie="$username\_$id\_$domain\_$authhost"; # Initialize roles @@ -9345,6 +9771,17 @@ sub init_user_environment { } } + foreach my $tool ('aboutme','blog','portfolio') { + $userenv{'availabletools.'.$tool} = + &Apache::lonnet::usertools_access($username,$domain,$tool,'reload'); + } + + foreach my $crstype ('official','unofficial') { + $userenv{'canrequest.'.$crstype} = + &Apache::lonnet::usertools_access($username,$domain,$crstype, + 'reload','requestcourses'); + } + $env{'user.environment'} = "$lonids/$cookie.id"; if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id", @@ -9372,12 +9809,54 @@ sub init_user_environment { sub _add_to_env { my ($idf,$env_data,$prefix) = @_; - while (my ($key,$value) = each(%$env_data)) { - $idf->{$prefix.$key} = $value; - $env{$prefix.$key} = $value; + if (ref($env_data) eq 'HASH') { + while (my ($key,$value) = each(%$env_data)) { + $idf->{$prefix.$key} = $value; + $env{$prefix.$key} = $value; + } } } +# --- Get the symbolic name of a problem and the url +sub get_symb { + my ($request,$silent) = @_; + (my $url=$env{'form.url'}) =~ s-^https?\://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; + my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url))); + if ($symb eq '') { + if (!$silent) { + $request->print("Unable to handle ambiguous references:$url:."); + return (); + } + } + &Apache::lonenc::check_decrypt(\$symb); + return ($symb); +} + +# --------------------------------------------------------------Get annotation + +sub get_annotation { + my ($symb,$enc) = @_; + + my $key = $symb; + if (!$enc) { + $key = + &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]); + } + my %annotation=&Apache::lonnet::get('nohist_annotations',[$key]); + return $annotation{$key}; +} + +sub clean_symb { + my ($symb,$delete_enc) = @_; + + &Apache::lonenc::check_decrypt(\$symb); + my $enc = $env{'request.enc'}; + if ($delete_enc) { + delete($env{'request.enc'}); + } + + return ($symb,$enc); +} =pod