--- loncom/interface/loncommon.pm 2006/05/01 20:48:55 1.359
+++ loncom/interface/loncommon.pm 2006/12/11 21:56:52 1.492
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.359 2006/05/01 20:48:55 albertel Exp $
+# $Id: loncommon.pm,v 1.492 2006/12/11 21:56:52 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -64,6 +64,8 @@ use HTML::Entities;
use Apache::lonhtmlcommon();
use Apache::loncoursedata();
use Apache::lontexconvert();
+use Apache::lonclonecourse();
+use LONCAPA qw(:DEFAULT :match);
my $readit;
@@ -155,7 +157,7 @@ BEGIN {
opendir(DIR,$designdir);
while ($filename=readdir(DIR)) {
if ($filename!~/\.tab$/) { next; }
- my ($domain)=($filename=~/^(\w+)\./);
+ my ($domain)=($filename=~/^($match_domain)\./);
{
my $designfile = $designdir.'/'.$filename;
if ( open (my $fh,"<$designfile") ) {
@@ -255,7 +257,7 @@ of the element the selection from the se
sub browser_and_searcher_javascript {
my ($mode)=@_;
if (!defined($mode)) { $mode='edit'; }
- my $resurl=&lastresurl();
+ my $resurl=&escape_single(&lastresurl());
return <
- var stdeditbrowser;
- function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag) {
+ var stdeditbrowser;'."\n";
+ $output .= <<"ENDSTDBRW";
+ function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag,crstype) {
var url = '/adm/pickcourse?';
- var filter;
- if (filter != null) {
- if (filter != '') {
- url += 'filter='+filter+'&';
- }
+ var domainfilter = '';
+ var formid = getFormIdByName(formname);
+ if (formid > -1) {
+ var domid = getIndexByName(formid,udom);
+ if (domid > -1) {
+ if (document.forms[formid].elements[domid].type == 'select-one') {
+ domainfilter=document.forms[formid].elements[domid].options[document.forms[formid].elements[domid].selectedIndex].value;
+ }
+ if (document.forms[formid].elements[domid].type == 'hidden') {
+ domainfilter=document.forms[formid].elements[domid].value;
+ }
+ }
}
- var domainfilter='$domainfilter';
if (domainfilter != null) {
if (domainfilter != '') {
url += 'domainfilter='+domainfilter+'&';
@@ -405,29 +415,108 @@ sub coursebrowser_javascript {
url += 'form=' + formname + '&cnumelement='+uname+
'&cdomelement='+udom+
'&cnameelement='+desc;
- if (extra_element !=null && extra_element != '' && formname == 'rolechoice') {
- url += '&roleelement='+extra_element;
- if (domainfilter == null || domainfilter == '') {
- url += '&domainfilter='+extra_element;
+ if (extra_element !=null && extra_element != '') {
+ if (formname == 'rolechoice') {
+ url += '&roleelement='+extra_element;
+ if (domainfilter == null || domainfilter == '') {
+ url += '&domainfilter='+extra_element;
+ }
}
+ else {
+ if (formname == 'portform') {
+ url += '&setroles='+extra_element;
+ }
+ }
}
if (multflag !=null && multflag != '') {
url += '&multiple='+multflag;
}
+ if (crstype == 'Course/Group') {
+ if (formname == 'cu') {
+ crstype = document.cu.crstype.options[document.cu.crstype.selectedIndex].value;
+ if (crstype == "") {
+ alert("$crs_or_grp_alert");
+ return;
+ }
+ }
+ }
+ if (crstype !=null && crstype != '') {
+ url += '&type='+crstype;
+ }
var title = 'Course_Browser';
var options = 'scrollbars=1,resizable=1,menubar=0';
options += ',width=700,height=600';
stdeditbrowser = open(url,title,options,'1');
stdeditbrowser.focus();
}
-
+
+ function getFormIdByName(formname) {
+ for (var i=0;i".&mt('Select Course')."";
+ my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype)=@_;
+ return "".&mt('Select Course')." ";
}
sub check_uncheck_jscript {
@@ -658,14 +747,14 @@ sub help_open_topic {
{
$template .=
"".
- "$text ";
+ "$text ";
}
# Add the graphic
my $title = &mt('Online Help');
my $helpicon=&lonhttpdurl("/adm/help/gif/smallHelp.gif");
$template .= <<"ENDTEMPLATE";
-
+
ENDTEMPLATE
if ($text ne '') { $template.='
' };
return $template;
@@ -692,40 +781,93 @@ sub helpLatexCheatsheet {
.'';
}
-sub help_open_menu {
- my ($color,$topic,$component_help,$function,$faq,$bug,$stayOnPage,$width,$height,$text) = @_;
- $text = "" if (not defined $text);
- $stayOnPage = 0 if (not defined $stayOnPage);
- if ($env{'browser.interface'} eq 'textual' ||
- $env{'environment.remote'} eq 'off' ) {
- $stayOnPage=1;
+sub general_help {
+ my $helptopic='Student_Intro';
+ if ($env{'request.role'}=~/^(ca|au)/) {
+ $helptopic='Authoring_Intro';
+ } elsif ($env{'request.role'}=~/^cc/) {
+ $helptopic='Course_Coordination_Intro';
}
- $width = 620 if (not defined $width);
- $height = 600 if (not defined $height);
- my $link='';
- my $title = &mt('Get help');
+ return $helptopic;
+}
+
+sub update_help_link {
+ my ($topic,$component_help,$faq,$bug,$stayOnPage) = @_;
my $origurl = $ENV{'REQUEST_URI'};
$origurl=~s|^/~|/priv/|;
my $timestamp = time;
- foreach my $datum (\$color,\$function,\$topic,\$component_help,\$faq,
- \$bug,\$origurl) {
- $$datum = &Apache::lonnet::escape($$datum);
+ foreach my $datum (\$topic,\$component_help,\$faq,\$bug,\$origurl) {
+ $$datum = &escape($$datum);
}
- if (!$stayOnPage) {
- $link = "javascript:helpMenu('open')";
- } else {
- $link = "javascript:helpMenu('display')";
+
+ my $banner_link = "/adm/helpmenu?page=banner&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage";
+ my $output .= <<"ENDOUTPUT";
+
+ENDOUTPUT
+ return $output;
+}
+
+# now just updates the help link and generates a blue icon
+sub help_open_menu {
+ my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text)
+ = @_;
+
+ $stayOnPage = 0 if (not defined $stayOnPage);
+ if ($env{'browser.interface'} eq 'textual' ||
+ $env{'environment.remote'} eq 'off' ) {
+ $stayOnPage=1;
}
- my $banner_link = "/adm/helpmenu?page=banner&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage";
- my $details_link = "/adm/helpmenu?page=body&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp";
- my $template;
- if ($text ne "") {
- $template .=
- "".
- "$text ";
+ my $output;
+ if ($component_help) {
+ if (!$text) {
+ $output=&help_open_topic($component_help,undef,$stayOnPage,
+ $width,$height);
+ } else {
+ my $help_text;
+ $help_text=&unescape($topic);
+ $output=''.
+ &help_open_topic($component_help,$help_text,$stayOnPage,
+ $width,$height).'
';
+ }
}
+ my $banner_link = &update_help_link($topic,$component_help,$faq,$bug,$stayOnPage);
+ return $output.$banner_link;
+}
+
+sub top_nav_help {
+ my ($text) = @_;
+
+ $text = &mt($text);
+
+ my $stayOnPage =
+ ($env{'browser.interface'} eq 'textual' ||
+ $env{'environment.remote'} eq 'off' );
+ my $link= ($stayOnPage) ? "javascript:helpMenu('display')"
+ : "javascript:helpMenu('open')";
+ my $banner_link = &update_help_link(undef,undef,undef,undef,$stayOnPage);
+
+ my $title = &mt('Get help');
+
+ return <<"END";
+$banner_link
+ $text
+END
+}
+
+sub help_menu_js {
+ my ($text) = @_;
+
+ my $stayOnPage =
+ ($env{'browser.interface'} eq 'textual' ||
+ $env{'environment.remote'} eq 'off' );
+
+ my $width = 620;
+ my $height = 600;
+ my $helptopic=&general_help();
+ my $details_link = '/adm/help/'.$helptopic.'.hlp';
my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
- my $helpicon=&lonhttpdurl("/adm/lonIcons/helpgateway.gif");
my $start_page =
&Apache::loncommon::start_page('Help Menu', undef,
{'frameset' => 1,
@@ -737,10 +879,11 @@ sub help_open_menu {
&Apache::loncommon::end_page({'frameset' => 1,
'js_ready' => 1,});
- $template .= <<"ENDTEMPLATE";
-
-
+
ENDTEMPLATE
- if ($component_help) {
- if (!$text) {
- $template=&help_open_topic($component_help,undef,$stayOnPage,
- $width,$height).' '.$template;
- } else {
- my $help_text;
- $help_text=&Apache::lonnet::unescape($topic);
- $template=''.
- &help_open_topic($component_help,$help_text,$stayOnPage,
- $width,$height).' '.$template.
- '
';
- }
- }
- if ($text ne '') { $template.='
' };
return $template;
}
@@ -802,8 +930,8 @@ sub help_open_bug {
$topic=~s/\W+/\+/g;
my $link='';
my $template='';
- my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='.
- &Apache::lonnet::escape($ENV{'REQUEST_URI'}).'&component='.$topic;
+ my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='.
+ &escape($ENV{'REQUEST_URI'}).'&component='.$topic;
if (!$stayOnPage)
{
$link = "javascript:void(open('$url', 'Bugzilla', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
@@ -817,14 +945,14 @@ sub help_open_bug {
{
$template .=
"".
- "$text ";
+ "$text ";
}
# Add the graphic
my $title = &mt('Report a Bug');
my $bugicon=&lonhttpdurl("/adm/lonMisc/smallBug.gif");
$template .= <<"ENDTEMPLATE";
-
+
ENDTEMPLATE
if ($text ne '') { $template.='
' };
return $template;
@@ -862,14 +990,14 @@ sub help_open_faq {
{
$template .=
"".
- "$text ";
+ "$text ";
}
# Add the graphic
my $title = &mt('View the FAQ');
my $faqicon=&lonhttpdurl("/adm/lonMisc/smallFAQ.gif");
$template .= <<"ENDTEMPLATE";
-
+
ENDTEMPLATE
if ($text ne '') { $template.='
' };
return $template;
@@ -1249,6 +1377,24 @@ sub select_form {
return $selectform;
}
+# For display filters
+
+sub display_filter {
+ if (!$env{'form.show'}) { $env{'form.show'}=10; }
+ if (!$env{'form.displayfilter'}) { $env{'form.displayfilter'}='currentfolder'; }
+ return ''.&mt('Records [_1]',
+ &Apache::lonmeta::selectbox('show',$env{'form.show'},undef,
+ (&mt('all'),10,20,50,100,1000,10000))).
+ ' '.
+ &mt('Filter [_1]',
+ &select_form($env{'form.displayfilter'},
+ 'displayfilter',
+ ('currentfolder' => 'Current folder/page',
+ 'containing' => 'Containing phrase',
+ 'none' => 'None'))).
+ ' ';
+}
+
sub gradeleveldescription {
my $gradelevel=shift;
my %gradelevels=(0 => 'Not specified',
@@ -1905,12 +2051,20 @@ sub get_related_words {
return ();
}
my @Words=();
+ my $count=0;
if (exists($thesaurus_db{$keyword})) {
# The first element is the number of times
# the word appears. We do not need it now.
- (undef,@Words) = (split(/:/,$thesaurus_db{$keyword}));
- for (my $i=0;$i<=$#Words;$i++) {
- ($Words[$i],undef)= split(/\,/,$Words[$i]);
+ my (undef,@RelatedWords) = (split(/:/,$thesaurus_db{$keyword}));
+ my (undef,$mostfrequentcount)=split(/\,/,$RelatedWords[0]);
+ my $threshold=$mostfrequentcount/10;
+ foreach my $possibleword (@RelatedWords) {
+ my ($word,$wordcount)=split(/\,/,$possibleword);
+ if ($wordcount>$threshold) {
+ push(@Words,$word);
+ $count++;
+ if ($count>10) { last; }
+ }
}
}
untie %thesaurus_db;
@@ -1989,6 +2143,9 @@ sub nickname {
sub getnames {
my ($uname,$udom)=@_;
+ if ($udom eq 'public' && $uname eq 'public') {
+ return ('lastname' => &mt('Public'));
+ }
my $id=$uname.':'.$udom;
my ($names,$cached)=&Apache::lonnet::is_cached_new('namescache',$id);
if ($cached) {
@@ -2002,6 +2159,27 @@ sub getnames {
}
}
+sub getemails {
+ my ($uname,$udom)=@_;
+ if ($udom eq 'public' && $uname eq 'public') {
+ return;
+ }
+ if (!$udom) { $udom=$env{'user.domain'}; }
+ if (!$uname) { $uname=$env{'user.name'}; }
+ my $id=$uname.':'.$udom;
+ my ($names,$cached)=&Apache::lonnet::is_cached_new('emailscache',$id);
+ if ($cached) {
+ return %{$names};
+ } else {
+ my %loadnames=&Apache::lonnet::get('environment',
+ ['notification','critnotification',
+ 'permanentemail'],
+ $udom,$uname);
+ &Apache::lonnet::do_cache_new('emailscache',$id,\%loadnames);
+ return %loadnames;
+ }
+}
+
# ------------------------------------------------------------------ Screenname
=pod
@@ -2024,10 +2202,11 @@ sub screenname {
# ------------------------------------------------------------- Message Wrapper
sub messagewrapper {
- my ($link,$username,$domain)=@_;
+ my ($link,$username,$domain,$subject,$text)=@_;
return
- ''.$link.' ';
}
# --------------------------------------------------------------- Notes Wrapper
@@ -2041,8 +2220,11 @@ sub noteswrapper {
sub aboutmewrapper {
my ($link,$username,$domain,$target)=@_;
+ if (!defined($username) && !defined($domain)) {
+ return;
+ }
return ''.$link.' ';
+ ($target?' target="$target"':'').' title="'.&mt("View this user's personal page").'">'.$link.'';
}
# ------------------------------------------------------------ Syllabus Wrapper
@@ -2071,7 +2253,9 @@ sub track_student_link {
$target = '';
}
if ($start) { $link.='&start='.$start; }
- return qq{$linktext };
+
+ return qq{$linktext }.
+ &help_open_topic('View_recent_activity');
}
=pod
@@ -2282,7 +2466,8 @@ sub preferred_languages {
$env{'course.'.$env{'request.course.id'}.'.languages'}));
}
if ($env{'environment.languages'}) {
- @languages=split(/\s*(\,|\;|\:)\s*/,$env{'environment.languages'});
+ @languages=(@languages,
+ split(/\s*(\,|\;|\:)\s*/,$env{'environment.languages'}));
}
my $browser=(split(/\;/,$ENV{'HTTP_ACCEPT_LANGUAGE'}))[0];
if ($browser) {
@@ -2394,7 +2579,7 @@ sub get_previous_attempt {
} else {
$value=$returnhash{$version.':'.$key};
}
- $prevattempts.=''.&Apache::lonnet::unescape($value).' ';
+ $prevattempts.=''.&unescape($value).' ';
}
}
}
@@ -2406,7 +2591,7 @@ sub get_previous_attempt {
} else {
$value=$lasthash{$key};
}
- $value=&Apache::lonnet::unescape($value);
+ $value=&unescape($value);
if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
$prevattempts.=''.$value.' ';
}
@@ -2524,11 +2709,11 @@ sub submlink {
my ($text,$uname,$udom,$symb,$target)=@_;
if (!($uname && $udom)) {
(my $cursymb, my $courseid,$udom,$uname)=
- &Apache::lonxml::whichuser($symb);
+ &Apache::lonnet::whichuser($symb);
if (!$symb) { $symb=$cursymb; }
}
if (!$symb) { $symb=&Apache::lonnet::symbread(); }
- $symb=&Apache::lonnet::escape($symb);
+ $symb=&escape($symb);
if ($target) { $target="target=\"$target\""; }
return ' 1 } @{$roles}; }
my %courses;
my $now=time;
- foreach my $key (keys(%env)) {
- if ( $key=~m{^user\.role\.(\w+)\./(\w+)/(\w+)} ) {
- my ($role,$domain,$id) = ($1,$2,$3);
- next if ($role eq 'ca' || $role eq 'aa');
- next if (%roles && !exists($roles{$role}));
- my ($starttime,$endtime)=split(/\./,$env{$key});
- my $active=1;
- if ($starttime) {
- if ($now<$starttime) { $active=0; }
+ if (!defined($uname)) {
+ $uname = $env{'user.name'};
+ }
+ if (!defined($udom)) {
+ $udom = $env{'user.domain'};
+ }
+ if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
+ my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname);
+ if (!%roles) {
+ %roles = (
+ cc => 1,
+ in => 1,
+ ep => 1,
+ ta => 1,
+ cr => 1,
+ st => 1,
+ );
+ }
+ foreach my $entry (keys(%roleshash)) {
+ my ($trole,$tend,$tstart) = split(/_/,$roleshash{$entry});
+ if ($trole =~ /^cr/) {
+ next if (!exists($roles{$trole}) && !exists($roles{'cr'}));
+ } else {
+ next if (!exists($roles{$trole}));
}
- if ($endtime) {
- if ($now>$endtime) { $active=0; }
+ if ($tend) {
+ next if ($tend < $now);
+ }
+ if ($tstart) {
+ next if ($tstart > $now);
+ }
+ my ($cdom,$cnum,$sec,$cnumpart,$secpart,$role,$realsec);
+ (undef,$cdom,$cnumpart,$secpart) = split(/\//,$entry);
+ if ($secpart eq '') {
+ ($cnum,$role) = split(/_/,$cnumpart);
+ $sec = 'none';
+ $realsec = '';
+ } else {
+ $cnum = $cnumpart;
+ ($sec,$role) = split(/_/,$secpart);
+ $realsec = $sec;
+ }
+ $courses{$cdom.'_'.$cnum}{$sec} = $trole.'/'.$cdom.'/'.$cnum.'/'.$realsec;
+ }
+ } else {
+ foreach my $key (keys(%env)) {
+ if ( $key=~m{^user\.role\.(\w+)\./($match_domain)/($match_courseid)/?(\w*)$} ||
+ $key=~m{^user\.role\.(cr/$match_domain/$match_username/\w+)\./($match_domain)/($match_courseid)/?(\w*)$}) {
+ my ($role,$cdom,$cnum,$sec) = ($1,$2,$3,$4);
+ next if ($role eq 'ca' || $role eq 'aa');
+ next if (%roles && !exists($roles{$role}));
+ my ($starttime,$endtime)=split(/\./,$env{$key});
+ my $active=1;
+ if ($starttime) {
+ if ($now<$starttime) { $active=0; }
+ }
+ if ($endtime) {
+ if ($now>$endtime) { $active=0; }
+ }
+ if ($active) {
+ if ($sec eq '') {
+ $sec = 'none';
+ }
+ $courses{$cdom.'_'.$cnum}{$sec} =
+ $role.'/'.$cdom.'/'.$cnum.'/'.$sec;
+ }
}
- if ($active) { $courses{$domain.'_'.$id}=1; }
}
}
- return keys(%courses);
+ return %courses;
}
###############################################
+
+sub blockcheck {
+ my ($setters,$activity,$uname,$udom) = @_;
+
+ if (!defined($udom)) {
+ $udom = $env{'user.domain'};
+ }
+ if (!defined($uname)) {
+ $uname = $env{'user.name'};
+ }
+
+ my ($startblock,$endblock);
+
+ # If uname and udom are for a course, check for blocks in the course.
+
+ if (&Apache::lonnet::is_course($udom,$uname)) {
+ my %records = &Apache::lonnet::dump('comm_block',$udom,$uname);
+ ($startblock,$endblock)=&get_blocks($setters,$activity,$udom,$uname);
+ return ($startblock,$endblock);
+ }
+
+ my %live_courses = &findallcourses(undef,$uname,$udom);
+
+ # If uname is for a user, and activity is course-specific, i.e.,
+ # boards, chat or groups, check for blocking in current course only.
+
+ if (($activity eq 'boards' || $activity eq 'chat' ||
+ $activity eq 'groups') && ($env{'request.course.id'})) {
+ foreach my $key (keys(%live_courses)) {
+ if ($key ne $env{'request.course.id'}) {
+ delete($live_courses{$key});
+ }
+ }
+ }
+
+ my $otheruser = 0;
+ my %own_courses;
+ if ((($uname ne $env{'user.name'})) || ($udom ne $env{'user.domain'})) {
+ # Resource belongs to user other than current user.
+ $otheruser = 1;
+ # Gather courses for current user
+ %own_courses =
+ &findallcourses(undef,$env{'user.name'},$env{'user.domain'});
+ }
+
+ # Gather active course roles - course coordinator, instructor,
+ # exam proctor, ta, student, or custom role.
+
+ foreach my $course (keys(%live_courses)) {
+ my ($cdom,$cnum);
+ if ((defined($env{'course.'.$course.'.domain'})) && (defined($env{'course.'.$course.'.num'}))) {
+ $cdom = $env{'course.'.$course.'.domain'};
+ $cnum = $env{'course.'.$course.'.num'};
+ } else {
+ ($cdom,$cnum) = split(/_/,$course);
+ }
+ my $no_ownblock = 0;
+ my $no_userblock = 0;
+ if ($otheruser) {
+ # Check if current user has 'evb' priv for this
+ if (defined($own_courses{$course})) {
+ foreach my $sec (keys(%{$own_courses{$course}})) {
+ my $checkrole = 'cm./'.$cdom.'/'.$cnum;
+ if ($sec ne 'none') {
+ $checkrole .= '/'.$sec;
+ }
+ if (&Apache::lonnet::allowed('evb',undef,undef,$checkrole)) {
+ $no_ownblock = 1;
+ last;
+ }
+ }
+ }
+ # if they have 'evb' priv and are currently not playing student
+ next if (($no_ownblock) &&
+ ($env{'request.role'} !~ m{^st\./$cdom/$cnum}));
+ }
+ foreach my $sec (keys(%{$live_courses{$course}})) {
+ my $checkrole = 'cm./'.$cdom.'/'.$cnum;
+ if ($sec ne 'none') {
+ $checkrole .= '/'.$sec;
+ }
+ # Resource belongs to user other than current user.
+ # Assemble privs for that user, and check for 'evb' priv.
+ if ($otheruser) {
+ # Resource belongs to user other than current user.
+ # Assemble privs for that user, and check for 'evb' priv.
+ my ($trole,$tdom,$tnum,$tsec);
+ my $entry = $live_courses{$course}{$sec};
+ if ($entry =~ /^cr/) {
+ ($trole,$tdom,$tnum,$tsec) =
+ ($entry =~ m|^(cr/$match_domain/$match_username/\w+)\./($match_domain)/($match_username)/?(\w*)$|);
+ } else {
+ ($trole,$tdom,$tnum,$tsec) = split(/\//,$entry);
+ }
+ my ($spec,$area,$trest,%allroles,%userroles);
+ $area = '/'.$tdom.'/'.$tnum;
+ $trest = $tnum;
+ if ($tsec ne '') {
+ $area .= '/'.$tsec;
+ $trest .= '/'.$tsec;
+ }
+ $spec = $trole.'.'.$area;
+ if ($trole =~ /^cr/) {
+ &Apache::lonnet::custom_roleprivs(\%allroles,$trole,
+ $tdom,$spec,$trest,$area);
+ } else {
+ &Apache::lonnet::standard_roleprivs(\%allroles,$trole,
+ $tdom,$spec,$trest,$area);
+ }
+ my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles);
+ if ($userroles{'user.priv.'.$checkrole} =~ /evb\&([^\:]*)/) {
+ if ($1) {
+ $no_userblock = 1;
+ last;
+ }
+ }
+ } else {
+ # Resource belongs to current user
+ # Check for 'evb' priv via lonnet::allowed().
+ if (&Apache::lonnet::allowed('evb',undef,undef,$checkrole)) {
+ $no_ownblock = 1;
+ last;
+ }
+ }
+ }
+ # if they have the evb priv and are currently not playing student
+ next if (($no_ownblock) &&
+ ($env{'request.role'} !~ m{^st\./\Q$cdom\E/\Q$cnum\E}));
+ next if ($no_userblock);
+
+ # Retrieve blocking times and identity of blocker for course
+ # of specified user, unless user has 'evb' privilege.
+
+ ($startblock,$endblock)=&get_blocks($setters,$activity,$cdom,$cnum);
+ }
+ return ($startblock,$endblock);
+}
+
+sub get_blocks {
+ my ($setters,$activity,$cdom,$cnum) = @_;
+ my $startblock = 0;
+ my $endblock = 0;
+ my $course = $cdom.'_'.$cnum;
+ $setters->{$course} = {};
+ $setters->{$course}{'staff'} = [];
+ $setters->{$course}{'times'} = [];
+ my %records = &Apache::lonnet::dump('comm_block',$cdom,$cnum);
+ foreach my $record (keys(%records)) {
+ my ($start,$end) = ($record =~ m/^(\d+)____(\d+)$/);
+ if ($start <= time && $end >= time) {
+ my ($staff_name,$staff_dom,$title,$blocks) =
+ &parse_block_record($records{$record});
+ if ($blocks->{$activity} eq 'on') {
+ push(@{$$setters{$course}{'staff'}},[$staff_name,$staff_dom]);
+ push(@{$$setters{$course}{'times'}}, [$start,$end]);
+ if ( ($startblock == 0) || ($startblock > $start) ) {
+ $startblock = $start;
+ }
+ if ( ($endblock == 0) || ($endblock < $end) ) {
+ $endblock = $end;
+ }
+ }
+ }
+ }
+ return ($startblock,$endblock);
+}
+
+sub parse_block_record {
+ my ($record) = @_;
+ my ($setuname,$setudom,$title,$blocks);
+ if (ref($record) eq 'HASH') {
+ ($setuname,$setudom) = split(/:/,$record->{'setter'});
+ $title = &unescape($record->{'event'});
+ $blocks = $record->{'blocks'};
+ } else {
+ my @data = split(/:/,$record,3);
+ if (scalar(@data) eq 2) {
+ $title = $data[1];
+ ($setuname,$setudom) = split(/@/,$data[0]);
+ } else {
+ ($setuname,$setudom,$title) = @data;
+ }
+ $blocks = { 'com' => 'on' };
+ }
+ return ($setuname,$setudom,$title,$blocks);
+}
+
+sub build_block_table {
+ my ($startblock,$endblock,$setters) = @_;
+ my %lt = &Apache::lonlocal::texthash(
+ 'cacb' => 'Currently active communication blocks',
+ 'cour' => 'Course',
+ 'dura' => 'Duration',
+ 'blse' => 'Block set by'
+ );
+ my $output;
+ $output = ' '.$lt{'cacb'}.': ';
+ $output .= &start_data_table();
+ $output .= '
+
+ '.$lt{'cour'}.'
+ '.$lt{'dura'}.'
+ '.$lt{'blse'}.'
+
+';
+ foreach my $course (keys(%{$setters})) {
+ my %courseinfo=&Apache::lonnet::coursedescription($course);
+ for (my $i=0; $i<@{$$setters{$course}{staff}}; $i++) {
+ my ($uname,$udom) = @{$$setters{$course}{staff}[$i]};
+ my $fullname = &plainname($uname,$udom);
+ if (defined($env{'user.name'}) && defined($env{'user.domain'})
+ && $env{'user.name'} ne 'public'
+ && $env{'user.domain'} ne 'public') {
+ $fullname = &aboutmewrapper($fullname,$uname,$udom);
+ }
+ my ($openblock,$closeblock) = @{$$setters{$course}{times}[$i]};
+ $openblock = &Apache::lonlocal::locallocaltime($openblock);
+ $closeblock= &Apache::lonlocal::locallocaltime($closeblock);
+ $output .= &Apache::loncommon::start_data_table_row().
+ ' '.$courseinfo{'description'}.' '.
+ ''.$openblock.' to '.$closeblock.' '.
+ ''.$fullname.' '.
+ &Apache::loncommon::end_data_table_row();
+ }
+ }
+ $output .= &end_data_table();
+}
+
+sub blocking_status {
+ my ($activity,$uname,$udom) = @_;
+ my %setters;
+ my ($blocked,$output,$ownitem,$is_course);
+ my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);
+ if ($startblock && $endblock) {
+ $blocked = 1;
+ if (wantarray) {
+ my $category;
+ if ($activity eq 'boards') {
+ $category = 'Discussion posts in this course';
+ } elsif ($activity eq 'blogs') {
+ $category = 'Blogs';
+ } elsif ($activity eq 'port') {
+ if (defined($uname) && defined($udom)) {
+ if ($uname eq $env{'user.name'} &&
+ $udom eq $env{'user.domain'}) {
+ $ownitem = 1;
+ }
+ }
+ $is_course = &Apache::lonnet::is_course($udom,$uname);
+ if ($ownitem) {
+ $category = 'Your portfolio files';
+ } elsif ($is_course) {
+ my $coursedesc;
+ foreach my $course (keys(%setters)) {
+ my %courseinfo =
+ &Apache::lonnet::coursedescription($course);
+ $coursedesc = $courseinfo{'description'};
+ }
+ $category = "Group files in the course '$coursedesc'";
+ } else {
+ $category = 'Portfolio files belonging to ';
+ if ($env{'user.name'} eq 'public' &&
+ $env{'user.domain'} eq 'public') {
+ $category .= &plainname($uname,$udom);
+ } else {
+ $category .= &aboutmewrapper(&plainname($uname,$udom),$uname,$udom);
+ }
+ }
+ } elsif ($activity eq 'groups') {
+ $category = 'Groups in this course';
+ }
+ my $showstart = &Apache::lonlocal::locallocaltime($startblock);
+ my $showend = &Apache::lonlocal::locallocaltime($endblock);
+ $output = ' '.&mt('[_1] will be inaccessible between [_2] and [_3] because communication is being blocked.',$category,$showstart,$showend).' ';
+ if (!($activity eq 'port' && !($ownitem) && !($is_course))) {
+ $output .= &build_block_table($startblock,$endblock,\%setters);
+ }
+ }
+ }
+ if (wantarray) {
+ return ($blocked,$output);
+ } else {
+ return $blocked;
+ }
+}
+
###############################################
=pod
@@ -2705,6 +3234,7 @@ Returns: value of designparamter $which
=cut
+
##############################################
sub designparm {
my ($which,$domain)=@_;
@@ -2719,11 +3249,11 @@ sub designparm {
return '#CCCCCC';
}
}
- if ($env{'environment.color.'.$which}) {
+ if (exists($env{'environment.color.'.$which})) {
return $env{'environment.color.'.$which};
}
$domain=&determinedomain($domain);
- if ($designhash{$domain.'.'.$which}) {
+ if (exists($designhash{$domain.'.'.$which})) {
return $designhash{$domain.'.'.$which};
} else {
return $designhash{'default.'.$which};
@@ -2773,6 +3303,11 @@ Inputs:
=item * $notitle, if true keep the nav controls, but remove the title bar
+=item * $no_inline_link, if true and in remote mode, don't show the
+ 'Switch To Inline Menu' link
+
+=item * $args, optional argument valid values are
+ no_auto_mt_title -> prevents &mt()ing the title arg
=back
@@ -2785,15 +3320,13 @@ other decorations will be returned.
sub bodytag {
my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,$customtitle,
- $notopbar,$bgcolor,$notitle)=@_;
+ $notopbar,$bgcolor,$notitle,$no_inline_link,$args)=@_;
- $title=&mt($title);
+ if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
$function = &get_users_function() if (!$function);
my $img = &designparm($function.'.img',$domain);
- my $tabbg = &designparm($function.'.tabbg',$domain);
my $font = &designparm($function.'.font',$domain);
- my $sidebg = &designparm($function.'.sidebg',$domain);
my $pgbg = $bgcolor || &designparm($function.'.pgbg',$domain);
my %design = ( 'style' => 'margin-top: 0px',
@@ -2802,15 +3335,24 @@ sub bodytag {
'alink' => &designparm($function.'.alink',$domain),
'vlink' => &designparm($function.'.vlink',$domain),
'link' => &designparm($function.'.link',$domain),);
- @$addentries{keys(%design)} = @design{keys(%design)};
+ @design{keys(%$addentries)} = @$addentries{keys(%$addentries)};
# role and realm
- my ($role,$realm) =
- &Apache::lonnet::plaintext((split(/\./,$env{'request.role'}))[0]);
+ my ($role,$realm) = split(/\./,$env{'request.role'},2);
+ if ($role eq 'ca') {
+ my ($rdom,$rname) = ($realm =~ m{^/($match_domain)/($match_username)$});
+ $realm = &plainname($rname,$rdom).':'.$rdom;
+ }
# realm
if ($env{'request.course.id'}) {
+ if ($env{'request.role'} !~ /^cr/) {
+ $role = &Apache::lonnet::plaintext($role,&course_type());
+ }
$realm = $env{'course.'.$env{'request.course.id'}.'.description'};
+ } else {
+ $role = &Apache::lonnet::plaintext($role);
}
+
if (!$realm) { $realm=' '; }
# Set messages
my $messages=&domainlogo($domain);
@@ -2818,7 +3360,7 @@ sub bodytag {
my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
- my $extra_body_attr = &make_attr_string($forcereg,$addentries);
+ my $extra_body_attr = &make_attr_string($forcereg,\%design);
# construct main body tag
my $bodytag = "".
@@ -2838,21 +3380,24 @@ sub bodytag {
return $bodytag;
}
-
+ my $name = &plainname($env{'user.name'},$env{'user.domain'});
+ if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
+ undef($role);
+ } else {
+ $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});
+ }
my $roleinfo=(<
- $env{'environment.firstname'}
- $env{'environment.middlename'}
- $env{'environment.lastname'}
- $env{'environment.generation'}
+ $name
+
-$role
+$role
-$realm
+$realm
ENDROLE
@@ -2869,6 +3414,7 @@ ENDROLE
'.domain'}.'/'})) {
my $cid = $env{'request.course.id'};
$dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
+ $dc_info =~ s/\s+$//;
$dc_info = '('.$dc_info.')';
}
@@ -2895,7 +3441,7 @@ ENDROLE
$lastitem = $thisdisfn;
}
$titleinfo =
- &Apache::loncommon::help_open_menu('','','','',3,'Authoring').
+ &Apache::loncommon::help_open_menu('','',3,'Authoring').
'Construction Space : '.
'
';
+ }
+ }
+ if (($args->{'ccdomain'}) && ($args->{'ccuname'})) {
+ if ($args->{'setpolicy'}) {
+ $cenv{'policy.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
+ }
+ if ($args->{'setcontent'}) {
+ $cenv{'question.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
+ }
+ }
+ if ($args->{'reshome'}) {
+ $cenv{'reshome'}=$args->{'reshome'}.'/';
+ $cenv{'reshome'}=~s/\/+$/\//;
+ }
+#
+# course has keyed access
+#
+ if ($args->{'setkeys'}) {
+ $cenv{'keyaccess'}='yes';
+ }
+# if specified, key authority is not course, but user
+# only active if keyaccess is yes
+ if ($args->{'keyauth'}) {
+ my ($user,$domain) = split(':',$args->{'keyauth'});
+ $user = &LONCAPA::clean_username($user);
+ $domain = &LONCAPA::clean_username($domain);
+ if ($user ne '' && $domain ne '') {
+ $cenv{'keyauth'}=$user.':'.$domain;
+ }
+ }
+
+ if ($args->{'disresdis'}) {
+ $cenv{'pch.roles.denied'}='st';
+ }
+ if ($args->{'disablechat'}) {
+ $cenv{'plc.roles.denied'}='st';
+ }
+
+ # Record we've not yet viewed the Course Initialization Helper for this
+ # course
+ $cenv{'course.helper.not.run'} = 1;
+ #
+ # Use new Randomseed
+ #
+ $cenv{'rndseed'}=&Apache::lonnet::latest_rnd_algorithm_id();;
+ $cenv{'receiptalg'}=&Apache::lonnet::latest_receipt_algorithm_id();;
+ #
+ # The encryption code and receipt prefix for this course
+ #
+ $cenv{'internal.encseed'}=$Apache::lonnet::perlvar{'lonReceipt'}.$$.time.int(rand(9999));
+ $cenv{'internal.encpref'}=100+int(9*rand(99));
+ #
+ # By default, use standard grading
+ if (!defined($cenv{'grading'})) { $cenv{'grading'} = 'standard'; }
+
+ $outcome .= (' '.&mt('Setting environment').': '.
+ &Apache::lonnet::put('environment',\%cenv,$$crsudom,$$crsunum).' ');
+#
+# Open all assignments
+#
+ if ($args->{'openall'}) {
+ my $storeunder=$$crsudom.'_'.$$crsunum.'.0.opendate';
+ my %storecontent = ($storeunder => time,
+ $storeunder.'.type' => 'date_start');
+
+ $outcome .= &mt('Opening all assignments').': '.&Apache::lonnet::cput
+ ('resourcedata',\%storecontent,$$crsudom,$$crsunum).' ';
+ }
+#
+# Set first page
+#
+ unless (($args->{'nonstandard'}) || ($args->{'firstres'} eq 'blank')
+ || ($cloneid)) {
+ use LONCAPA::map;
+ $outcome .= &mt('Setting first resource').': ';
+
+ my $map = '/uploaded/'.$$crsudom.'/'.$$crsunum.'/default.sequence';
+ my ($errtext,$fatal)=&LONCAPA::map::mapread($map);
+
+ $outcome .= ($fatal?$errtext:'read ok').' - ';
+ my $title; my $url;
+ if ($args->{'firstres'} eq 'syl') {
+ $title='Syllabus';
+ $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';
+ } else {
+ $title='Navigate Contents';
+ $url='/adm/navmaps';
+ }
+
+ $LONCAPA::map::resources[1]=$title.':'.$url.':false:start:res';
+ (my $outtext,$errtext) = &LONCAPA::map::storemap($map,1);
+
+ if ($errtext) { $fatal=2; }
+ $outcome .= ($fatal?$errtext:'write ok').' ';
+ }
+ return $outcome;
+}
+
+############################################################
+############################################################
+
+sub course_type {
+ my ($cid) = @_;
+ if (!defined($cid)) {
+ $cid = $env{'request.course.id'};
+ }
+ if (defined($env{'course.'.$cid.'.type'})) {
+ return $env{'course.'.$cid.'.type'};
+ } else {
+ return 'Course';
+ }
+}
+
+sub group_term {
+ my $crstype = &course_type();
+ my %names = (
+ 'Course' => 'group',
+ 'Group' => 'team',
+ );
+ return $names{$crstype};
+}
sub icon {
my ($file)=@_;
@@ -5125,9 +6582,174 @@ sub escape_double {
sub escape_url {
my ($url) = @_;
my @urlslices = split(/\//, $url,-1);
- my $lastitem = &Apache::lonnet::escape(pop(@urlslices));
+ my $lastitem = &escape(pop(@urlslices));
return join('/',@urlslices).'/'.$lastitem;
}
+
+# -------------------------------------------------------- Initliaze user login
+sub init_user_environment {
+ my ($r, $username, $domain, $authhost, $form, $args) = @_;
+ my $lonids=$Apache::lonnet::perlvar{'lonIDsDir'};
+
+ my $public=($username eq 'public' && $domain eq 'public');
+
+# See if old ID present, if so, remove
+
+ my ($filename,$cookie,$userroles);
+ my $now=time;
+
+ if ($public) {
+ my $max_public=100;
+ my $oldest;
+ my $oldest_time=0;
+ for(my $next=1;$next<=$max_public;$next++) {
+ if (-e $lonids."/publicuser_$next.id") {
+ my $mtime=(stat($lonids."/publicuser_$next.id"))[9];
+ if ($mtime<$oldest_time || !$oldest_time) {
+ $oldest_time=$mtime;
+ $oldest=$next;
+ }
+ } else {
+ $cookie="publicuser_$next";
+ last;
+ }
+ }
+ if (!$cookie) { $cookie="publicuser_$oldest"; }
+ } else {
+ # if this isn't a robot, kill any existing non-robot sessions
+ if (!$args->{'robot'}) {
+ opendir(DIR,$lonids);
+ while ($filename=readdir(DIR)) {
+ if ($filename=~/^$username\_\d+\_$domain\_$authhost\.id$/) {
+ unlink($lonids.'/'.$filename);
+ }
+ }
+ closedir(DIR);
+ }
+# Give them a new cookie
+ my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'}
+ : $now);
+ $cookie="$username\_$id\_$domain\_$authhost";
+
+# Initialize roles
+
+ $userroles=&Apache::lonnet::rolesinit($domain,$username,$authhost);
+ }
+# ------------------------------------ Check browser type and MathML capability
+
+ my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
+ $clientunicode,$clientos) = &decode_user_agent($r);
+
+# -------------------------------------- Any accessibility options to remember?
+ if (($form->{'interface'}) && ($form->{'remember'} eq 'true')) {
+ foreach my $option ('imagesuppress','appletsuppress',
+ 'embedsuppress','fontenhance','blackwhite') {
+ if ($form->{$option} eq 'true') {
+ &Apache::lonnet::put('environment',{$option => 'on'},
+ $domain,$username);
+ } else {
+ &Apache::lonnet::del('environment',[$option],
+ $domain,$username);
+ }
+ }
+ }
+# ------------------------------------------------------------- Get environment
+
+ my %userenv = &Apache::lonnet::dump('environment',$domain,$username);
+ my ($tmp) = keys(%userenv);
+ if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
+ # default remote control to off
+ if ($userenv{'remote'} ne 'on') { $userenv{'remote'} = 'off'; }
+ } else {
+ undef(%userenv);
+ }
+ if (($userenv{'interface'}) && (!$form->{'interface'})) {
+ $form->{'interface'}=$userenv{'interface'};
+ }
+ $env{'environment.remote'}=$userenv{'remote'};
+ if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; }
+
+# --------------- Do not trust query string to be put directly into environment
+ foreach my $option ('imagesuppress','appletsuppress',
+ 'embedsuppress','fontenhance','blackwhite',
+ 'interface','localpath','localres') {
+ $form->{$option}=~s/[\n\r\=]//gs;
+ }
+# --------------------------------------------------------- Write first profile
+
+ {
+ my %initial_env =
+ ("user.name" => $username,
+ "user.domain" => $domain,
+ "user.home" => $authhost,
+ "browser.type" => $clientbrowser,
+ "browser.version" => $clientversion,
+ "browser.mathml" => $clientmathml,
+ "browser.unicode" => $clientunicode,
+ "browser.os" => $clientos,
+ "server.domain" => $Apache::lonnet::perlvar{'lonDefDomain'},
+ "request.course.fn" => '',
+ "request.course.uri" => '',
+ "request.course.sec" => '',
+ "request.role" => 'cm',
+ "request.role.adv" => $env{'user.adv'},
+ "request.host" => $ENV{'REMOTE_ADDR'},);
+
+ if ($form->{'localpath'}) {
+ $initial_env{"browser.localpath"} = $form->{'localpath'};
+ $initial_env{"browser.localres"} = $form->{'localres'};
+ }
+
+ if ($public) {
+ $initial_env{"environment.remote"} = "off";
+ }
+ if ($form->{'interface'}) {
+ $form->{'interface'}=~s/\W//gs;
+ $initial_env{"browser.interface"} = $form->{'interface'};
+ $env{'browser.interface'}=$form->{'interface'};
+ foreach my $option ('imagesuppress','appletsuppress',
+ 'embedsuppress','fontenhance','blackwhite') {
+ if (($form->{$option} eq 'true') ||
+ ($userenv{$option} eq 'on')) {
+ $initial_env{"browser.$option"} = "on";
+ }
+ }
+ }
+
+ $env{'user.environment'} = "$lonids/$cookie.id";
+
+ if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",
+ &GDBM_WRCREAT(),0640)) {
+ &_add_to_env(\%disk_env,\%initial_env);
+ &_add_to_env(\%disk_env,\%userenv,'environment.');
+ &_add_to_env(\%disk_env,$userroles);
+ if (ref($args->{'extra_env'})) {
+ &_add_to_env(\%disk_env,$args->{'extra_env'});
+ }
+ untie(%disk_env);
+ } else {
+ &Apache::lonnet::logthis("WARNING: ".
+ 'Could not create environment storage in lonauth: '.$!.' ');
+ return 'error: '.$!;
+ }
+ }
+ $env{'request.role'}='cm';
+ $env{'request.role.adv'}=$env{'user.adv'};
+ $env{'browser.type'}=$clientbrowser;
+
+ return $cookie;
+
+}
+
+sub _add_to_env {
+ my ($idf,$env_data,$prefix) = @_;
+ while (my ($key,$value) = each(%$env_data)) {
+ $idf->{$prefix.$key} = $value;
+ $env{$prefix.$key} = $value;
+ }
+}
+
+
=pod
=back