--- loncom/interface/loncommon.pm 2010/02/21 02:38:23 1.942
+++ loncom/interface/loncommon.pm 2010/12/25 16:01:54 1.948.2.17
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.942 2010/02/21 02:38:23 raeburn Exp $
+# $Id: loncommon.pm,v 1.948.2.17 2010/12/25 16:01:54 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -900,7 +900,7 @@ sub select_language {
$langchoices{$code} = &plainlanguagedescription($id);
}
}
- return &select_form($selected,$name,%langchoices);
+ return &select_form($selected,$name,\%langchoices);
}
=pod
@@ -1072,7 +1072,7 @@ END
=pod
-=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height)
+=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height,$imgid)
Returns a string corresponding to an HTML link to the given help
$topic, where $topic corresponds to the name of a .tex file in
@@ -1095,7 +1095,7 @@ be useful for certain help topics with b
=cut
sub help_open_topic {
- my ($topic, $text, $stayOnPage, $width, $height) = @_;
+ my ($topic, $text, $stayOnPage, $width, $height, $imgid) = @_;
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
$width = 350 if (not defined $width);
@@ -1124,12 +1124,15 @@ sub help_open_topic {
# (Always) Add the graphic
my $title = &mt('Online Help');
my $helpicon=&lonhttpdurl("/adm/help/help.png");
+ if ($imgid ne '') {
+ $imgid = ' id="'.$imgid.'"';
+ }
$template.=' '
.'';
- if ($text ne "") {
+ if ($text ne "") {
$template.='';
}
return $template;
@@ -1800,7 +1803,7 @@ sub domain_select {
return &multiple_select_form($name,$value,4,\%domains);
} else {
$domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))];
- return &select_form($name,$value,%domains);
+ return &select_form($name,$value,\%domains);
}
}
@@ -1862,29 +1865,36 @@ sub multiple_select_form {
=pod
-=item * &select_form($defdom,$name,%hash)
+=item * &select_form($defdom,$name,$hashref,$onchange)
Returns a string containing a
'."\n".'
'.
+ &mt('LON-CAPA can make the required changes to your HTML file.').'
'."\n".
+ ''."\n";
+ }
+ return;
+}
+
+sub modify_html_refs {
+ my ($context,$dirpath,$uname,$udom,$dir_root) = @_;
+ my $container;
+ if ($context eq 'portfolio') {
+ $container = $env{'form.container'};
+ } elsif ($context eq 'coursedoc') {
+ $container = $env{'form.primaryurl'};
+ } else {
+ $container = $env{'form.filename'};
+ $container =~ s{^/priv/(\Q$uname\E)/(.*)}{/home/$1/public_html/$2};
+ }
+ my (%allfiles,%codebase,$output,$content);
+ my @changes = &get_env_multiple('form.namechange');
+ return unless (@changes > 0);
+ if (($context eq 'portfolio') || ($context eq 'coursedoc')) {
+ return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/});
+ $content = &Apache::lonnet::getfile($container);
+ return if ($content eq '-1');
+ } else {
+ return unless ($container =~ /^\Q$dir_root\E/);
+ if (open(my $fh,"<$container")) {
+ $content = join('', <$fh>);
+ close($fh);
+ } else {
+ return;
+ }
+ }
+ my ($count,$codebasecount) = (0,0);
+ my $mm = new File::MMagic;
+ my $mime_type = $mm->checktype_contents($content);
+ if ($mime_type eq 'text/html') {
+ my $parse_result =
+ &Apache::lonnet::extract_embedded_items($container,\%allfiles,
+ \%codebase,\$content);
+ if ($parse_result eq 'ok') {
+ foreach my $i (@changes) {
+ my $orig = &unescape($env{'form.embedded_orig_'.$i});
+ my $ref = &unescape($env{'form.embedded_ref_'.$i});
+ if ($allfiles{$ref}) {
+ my $newname = $orig;
+ my ($attrib_regexp,$codebase);
+ my $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i});
+ if ($attrib_regexp =~ /:/) {
+ $attrib_regexp =~ s/\:/|/g;
+ }
+ if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) {
+ my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
+ $count += $numchg;
+ }
+ if ($env{'form.embedded_codebase_'.$i} ne '') {
+ my $codebase = &unescape($env{'form.embedded_codebase_'.$i});
+ my $numchg = ($content =~ s/(codebase\s*=\s*["']?)\Q$codebase\E(["']?)/$1.$2/i); #' stupid emacs
+ $codebasecount ++;
+ }
+ }
+ }
+ if ($count || $codebasecount) {
+ my $saveresult;
+ if ($context eq 'portfolio' || $context eq 'coursedoc') {
+ my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
+ if ($url eq $container) {
+ my ($fname) = ($container =~ m{/([^/]+)$});
+ $output = '
'.&mt('Updated [quant,_1,reference] in [_2].',
+ $count,''.
+ $fname.'').'
'.&mt('Updated [quant,_1,reference] in [_2].',
+ $count,''.
+ $container.'').'
';
+ } else {
+ $output = '
'.
+ &mt('Error: could not update [_1].',
+ ''.
+ $container.'').'
';
+ }
+ }
+ }
+ } else {
+ &logthis('Failed to parse '.$container.
+ ' to modify references: '.$parse_result);
+ }
}
return $output;
}
@@ -8430,14 +9080,24 @@ sub check_for_existing {
sub check_for_upload {
my ($path,$fname,$group,$element,$portfolio_root,$port_path,
$disk_quota,$current_disk_usage,$uname,$udom) = @_;
- my $filesize = (length($env{'form.'.$element})) / 1000; #express in k (1024?)
+ my $filesize = length($env{'form.'.$element});
+ if (!$filesize) {
+ my $msg = ''.
+ &mt('Unable to upload [_1]. (size = [_2] bytes)',
+ ''.$fname.'',
+ $filesize).' '.
+ &mt('Either the file you uploaded was empty, or your web browser was unable to read its contents.').' ';
+ '';
+ return ('zero_bytes',$msg);
+ }
+ $filesize = $filesize/1000; #express in k (1024?)
my $getpropath = 1;
my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,
$getpropath);
my $found_file = 0;
my $locked_file = 0;
foreach my $line (@dir_list) {
- my ($file_name)=split(/\&/,$line,2);
+ my ($file_name,$rest)=split(/\&/,$line,2);
if ($file_name eq $fname){
$file_name = $path.$file_name;
if ($group ne '') {
@@ -8446,6 +9106,20 @@ sub check_for_upload {
$found_file = 1;
if (&Apache::lonnet::is_locked($file_name,$udom,$uname) eq 'true') {
$locked_file = 1;
+ } else {
+ my @info = split(/\&/,$rest);
+ my $currsize = $info[6]/1000;
+ if ($currsize < $filesize) {
+ my $extra = $filesize - $currsize;
+ if (($current_disk_usage + $extra) > $disk_quota) {
+ my $msg = ''.
+ &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
+ ''.$fname.'',$filesize,$currsize).''.
+ ' '.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
+ $disk_quota,$current_disk_usage);
+ return ('will_exceed_quota',$msg);
+ }
+ }
}
}
}
@@ -8463,15 +9137,55 @@ sub check_for_upload {
return ('file_locked',$msg);
} else {
my $msg = '';
- $msg .= &mt('Unable to upload [_1]. A file by that name was found in [_2].',''.$fname.'',$port_path.$env{'form.currentpath'});
+ $msg .= &mt(' A file by that name: [_1] was found in [_2].',''.$fname.'',$port_path.$env{'form.currentpath'});
$msg .= '';
- $msg .= ' ';
- $msg .= &mt('To upload, rename or delete existing [_1] in [_2].',''.$fname.'', $port_path.$env{'form.currentpath'});
- return ('file_exists',$msg);
+ return ('existingfile',$msg);
}
}
}
+sub check_for_traversal {
+ my ($path,$url,$toplevel) = @_;
+ my @parts=split(/\//,$path);
+ my $cleanpath;
+ my $fullpath = $url;
+ for (my $i=0;$i<@parts;$i++) {
+ next if ($parts[$i] eq '.');
+ if ($parts[$i] eq '..') {
+ $fullpath =~ s{([^/]+/)$}{};
+ } else {
+ $fullpath .= $parts[$i].'/';
+ }
+ }
+ if ($fullpath =~ /^\Q$url\E(.*)$/) {
+ $cleanpath = $1;
+ } elsif ($fullpath =~ /^\Q$toplevel\E(.*)$/) {
+ my $curr_toprel = $1;
+ my @parts = split(/\//,$curr_toprel);
+ my ($url_toprel) = ($url =~ /^\Q$toplevel\E(.*)$/);
+ my @urlparts = split(/\//,$url_toprel);
+ my $doubledots;
+ my $startdiff = -1;
+ for (my $i=0; $i<@urlparts; $i++) {
+ if ($startdiff == -1) {
+ unless ($urlparts[$i] eq $parts[$i]) {
+ $startdiff = $i;
+ $doubledots .= '../';
+ }
+ } else {
+ $doubledots .= '../';
+ }
+ }
+ if ($startdiff > -1) {
+ $cleanpath = $doubledots;
+ for (my $i=$startdiff; $i<@parts; $i++) {
+ $cleanpath .= $parts[$i].'/';
+ }
+ }
+ }
+ $cleanpath =~ s{(/)$}{};
+ return $cleanpath;
+}
=pod
@@ -9993,19 +10707,19 @@ sub check_clone {
my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
my $clonemsg;
my $can_clone = 0;
- my $lctype = lc($args->{'type'});
+ my $lctype = lc($args->{'crstype'});
if ($lctype ne 'community') {
$lctype = 'course';
}
if ($clonehome eq 'no_host') {
- if ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
$clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a non-existent community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
} else {
$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 ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
if ($clonedesc{'type'} ne 'Community') {
$clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a course not a community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
return ($can_clone, $clonemsg, $cloneid, $clonehome);
@@ -10024,7 +10738,7 @@ sub check_clone {
$can_clone = 1;
} else {
my $ccrole = 'cc';
- if ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
$ccrole = 'co';
}
my %roleshash =
@@ -10037,7 +10751,7 @@ sub check_clone {
} elsif (&Apache::lonnet::is_course_owner($args->{'clonedomain'},$args->{'clonecourse'},$args->{'ccuname'},$args->{'ccdomain'})) {
$can_clone = 1;
} else {
- if ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
$clonemsg = &mt('No new community created.').$linefeed.&mt('The new community could not be cloned from the existing community because the new community owner ([_1]) does not have cloning rights in the existing community ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
} 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'});
@@ -10096,11 +10810,19 @@ 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;
+ if ($$courseid =~ /^error:/) {
+ return (0,$outcome);
+ }
+
#
# Check if created correctly
#
($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);
my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
+ if ($crsuhome eq 'no_host') {
+ $outcome .= &mt('Course creation failed, unrecognized course home server.').$linefeed;
+ return (0,$outcome);
+ }
$outcome .= &mt('Created on').': '.$crsuhome.$linefeed;
#
@@ -10119,6 +10841,10 @@ sub construct_course {
$cenv{'url'}=$oldcenv{'url'};
# Restore title
$cenv{'description'}=$oldcenv{'description'};
+# Restore creation date, creator and creation context.
+ $cenv{'internal.created'}=$oldcenv{'internal.created'};
+ $cenv{'internal.creator'}=$oldcenv{'internal.creator'};
+ $cenv{'internal.creationcontext'}=$oldcenv{'internal.creationcontext'};
# Mark as cloned
$cenv{'clonedfrom'}=$cloneid;
# Need to clone grading mode
@@ -10365,7 +11091,7 @@ sub construct_course {
$title=&mt('Syllabus');
$url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';
} else {
- $title=&mt('Navigate Contents');
+ $title=&mt('Table of Contents');
$url='/adm/navmaps';
}
@@ -10595,16 +11321,20 @@ sub init_user_environment {
$initial_env{"browser.interface"} = $form->{'interface'};
$env{'browser.interface'}=$form->{'interface'};
}
+ my %is_adv = ( is_adv => $env{'user.adv'} );
+ my %domdef = &Apache::lonnet::get_domain_defaults($domain);
foreach my $tool ('aboutme','blog','portfolio') {
$userenv{'availabletools.'.$tool} =
- &Apache::lonnet::usertools_access($username,$domain,$tool,'reload');
+ &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',
+ undef,\%userenv,\%domdef,\%is_adv);
}
foreach my $crstype ('official','unofficial','community') {
$userenv{'canrequest.'.$crstype} =
&Apache::lonnet::usertools_access($username,$domain,$crstype,
- 'reload','requestcourses');
+ 'reload','requestcourses',
+ \%userenv,\%domdef,\%is_adv);
}
$env{'user.environment'} = "$lonids/$cookie.id";
@@ -10683,6 +11413,36 @@ sub clean_symb {
return ($symb,$enc);
}
+sub build_release_hashes {
+ my ($checkparms,$checkresponsetypes,$checkcrstypes,$anonsurvey,$randomizetry) = @_;
+ return unless((ref($checkparms) eq 'HASH') && (ref($checkresponsetypes) eq 'HASH') &&
+ (ref($checkcrstypes) eq 'HASH') && (ref($anonsurvey) eq 'HASH') &&
+ (ref($randomizetry) eq 'HASH'));
+ foreach my $key (keys(%Apache::lonnet::needsrelease)) {
+ my ($item,$name,$value) = split(/:/,$key);
+ if ($item eq 'parameter') {
+ if (ref($checkparms->{$name}) eq 'ARRAY') {
+ unless(grep(/^\Q$name\E$/,@{$checkparms->{$name}})) {
+ push(@{$checkparms->{$name}},$value);
+ }
+ } else {
+ push(@{$checkparms->{$name}},$value);
+ }
+ } elsif ($item eq 'resourcetag') {
+ if ($name eq 'responsetype') {
+ $checkresponsetypes->{$value} = $Apache::lonnet::needsrelease{$key}
+ }
+ } elsif ($item eq 'course') {
+ if ($name eq 'crstype') {
+ $checkcrstypes->{$value} = $Apache::lonnet::needsrelease{$key};
+ }
+ }
+ }
+ ($anonsurvey->{major},$anonsurvey->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'});
+ ($randomizetry->{major},$randomizetry->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'});
+ return;
+}
+
=pod
=back