&').'" ';
$output.='selected="selected" ' if ($selected{$key});
@@ -1377,6 +1385,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',
@@ -2672,7 +2698,9 @@ sub get_student_answers {
}
$moreenv{'grade_target'}='answer';
%moreenv=(%form,%moreenv);
- my $userview=&Apache::lonnet::ssi('/res/'.$feedurl,%moreenv);
+ $feedurl = &Apache::lonnet::clutter($feedurl);
+ &Apache::lonenc::check_encrypt(\$feedurl);
+ my $userview=&Apache::lonnet::ssi($feedurl,%moreenv);
return $userview;
}
@@ -2786,31 +2814,376 @@ sub maketime {
#########################################
sub findallcourses {
- my ($roles) = @_;
+ my ($roles,$uname,$udom) = @_;
my %roles;
if (ref($roles)) { %roles = map { $_ => 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'};
+ }
+
+ # 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);
+ my ($startblock,$endblock)=&get_blocks($setters,$activity,$udom,$uname);
+ return ($startblock,$endblock);
+ }
+
+ my $startblock = 0;
+ my $endblock = 0;
+ 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;
+ }
+ 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.
+
+ my ($start,$end)=&get_blocks($setters,$activity,$cdom,$cnum);
+ if (($start != 0) &&
+ (($startblock == 0) || ($startblock > $start))) {
+ $startblock = $start;
+ }
+ if (($end != 0) &&
+ (($endblock == 0) || ($endblock < $end))) {
+ $endblock = $end;
+ }
+ }
+ 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
@@ -2983,8 +3356,8 @@ sub bodytag {
# role and realm
my ($role,$realm) = split(/\./,$env{'request.role'},2);
if ($role eq 'ca') {
- my ($rdom,$rname) = ($realm =~ m-^/(\w+)/(\w+)$-);
- $realm = &plainname($rname,$rdom).':'.$rdom;
+ my ($rdom,$rname) = ($realm =~ m{^/($match_domain)/($match_username)$});
+ $realm = &plainname($rname,$rdom);
}
# realm
if ($env{'request.course.id'}) {
@@ -3280,6 +3653,7 @@ sub standard_css {
my $mail_other = '#99BBBB';
my $mail_other_hover = '#669999';
my $table_header = '#DDDDDD';
+ my $feedback_link_bg = '#BBBBBB';
my $border = ($env{'browser.type'} eq 'explorer') ? '0px 2px 0px 2px'
: '0px 3px 0px 4px';
@@ -3489,8 +3863,6 @@ table.LC_whatsnew tr.LC_empty_row td {
table.LC_whatsnew tr.LC_empty_row td {
padding: 4ex
}
-
-
table.LC_whatsnew {
}
@@ -3514,6 +3886,19 @@ table.LC_whatsnew tr.LC_odd_row td {
background-color: #EEE;
}
+table.LC_createuser {
+}
+
+table.LC_createuser tr.LC_section_row td {
+ font-size: smaller;
+}
+
+table.LC_createuser tr.LC_info_row td {
+ background-color: #CCC;
+ font-weight: bold;
+ text-align: center;
+}
+
table.LC_calendar {
border: 1px solid #000000;
border-collapse: collapse;
@@ -3556,6 +3941,11 @@ table.LC_mail_list tr.LC_mail_other {
table.LC_mail_list tr.LC_mail_other:hover {
background-color: $mail_other_hover;
}
+table.LC_mail_list tr.LC_mail_even {
+}
+table.LC_mail_list tr.LC_mail_odd {
+}
+
table#LC_portfolio_actions {
width: auto;
@@ -3800,6 +4190,13 @@ table.LC_descriptive_input td.LC_descrip
text-align: right;
font-weight: bold;
}
+table.LC_feedback_link {
+ background: $feedback_link_bg;
+}
+span.LC_feedback_link {
+ background: $feedback_link_bg;
+ font-size: larger;
+}
END
}
@@ -4092,6 +4489,11 @@ Inputs: $args - additional optio
a html attribute
frameset -> if true will start with a
rather than
+ dicsussion -> if true will get discussion from
+ lonxml::xmlend
+ (you can pass the target and parser arguments
+ through optional 'target' and 'parser' args
+ to this routine)
=cut
@@ -4550,7 +4952,7 @@ sub get_course_users {
$usec = 'none';
}
if ($uname ne '' && $udom ne '') {
- if ($end < $now) {
+ if ($end > 0 && $end < $now) {
$status = 'previous';
} elsif ($start > $now) {
$status = 'future';
@@ -4990,7 +5392,12 @@ sub record_sep {
$i++;
}
} else {
- my @allfields=split(/\,/,$record);
+ my @allfields;
+ if ($env{'form.upfiletype'} eq 'semisv') {
+ @allfields=split(/;/,$record);
+ } else {
+ @allfields=split(/\,/,$record);
+ }
my $i=0;
my $j;
for ($j=0;$j<=$#allfields;$j++) {
@@ -5028,6 +5435,7 @@ the file type.
sub upfile_select_html {
my %Types = (
csv => &mt('CSV (comma separated values, spreadsheet)'),
+ semisv => &mt('Semicolon separated values'),
space => &mt('Space separated'),
tab => &mt('Tabulator separated'),
# xml => &mt('HTML/XML'),
@@ -5682,16 +6090,19 @@ Returns: both routines return nothing
#######################################################
#######################################################
sub store_course_settings {
+ return &store_settings($env{'request.course.id'},@_);
+}
+
+sub store_settings {
# save to the environment
# appenv the same items, just to be safe
- my $courseid = $env{'request.course.id'};
my $udom = $env{'user.domain'};
my $uname = $env{'user.name'};
- my ($prefix,$Settings) = @_;
+ my ($context,$prefix,$Settings) = @_;
my %SaveHash;
my %AppHash;
while (my ($setting,$type) = each(%$Settings)) {
- my $basename = join('.','internal',$courseid,$prefix,$setting);
+ my $basename = join('.','internal',$context,$prefix,$setting);
my $envname = 'environment.'.$basename;
if (exists($env{'form.'.$setting})) {
# Save this value away
@@ -5731,11 +6142,14 @@ sub store_course_settings {
}
sub restore_course_settings {
- my $courseid = $env{'request.course.id'};
- my ($prefix,$Settings) = @_;
+ return &restore_settings($env{'request.course.id'},@_);
+}
+
+sub restore_settings {
+ my ($context,$prefix,$Settings) = @_;
while (my ($setting,$type) = each(%$Settings)) {
next if (exists($env{'form.'.$setting}));
- my $envname = 'environment.internal.'.$courseid.'.'.$prefix.
+ my $envname = 'environment.internal.'.$context.'.'.$prefix.
'.'.$setting;
if (exists($env{$envname})) {
if ($type eq 'scalar') {
@@ -5867,7 +6281,7 @@ sub construct_course {
#
# Check if created correctly
#
- ($$crsudom,$$crsunum)=($$courseid=~/^\/(\w+)\/(\w+)$/);
+ ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);
my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
$outcome .= &mt('Created on').': '.$crsuhome.' ';
#
@@ -5876,7 +6290,7 @@ sub construct_course {
my $cloneid='';
if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) {
$cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'};
- my ($clonecrsudom,$clonecrsunum)=($cloneid=~/^\/(\w+)\/(\w+)$/);
+ my ($clonecrsudom,$clonecrsunum)= &LONCAPA::split_courseid($cloneid);
my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
if ($clonehome eq 'no_host') {
$outcome .=
@@ -6049,9 +6463,11 @@ sub construct_course {
# if specified, key authority is not course, but user
# only active if keyaccess is yes
if ($args->{'keyauth'}) {
- $args->{'keyauth'}=~s/[^\w\@]//g;
- if ($args->{'keyauth'}) {
- $cenv{'keyauth'}=$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;
}
}