--- loncom/interface/loncommon.pm 2012/03/17 20:11:26 1.1059
+++ loncom/interface/loncommon.pm 2013/05/10 23:18:42 1.1075.2.35
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1059 2012/03/17 20:11:26 raeburn Exp $
+# $Id: loncommon.pm,v 1.1075.2.35 2013/05/10 23:18:42 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -67,9 +67,13 @@ use Apache::lonhtmlcommon();
use Apache::loncoursedata();
use Apache::lontexconvert();
use Apache::lonclonecourse();
+use Apache::lonuserutils();
+use Apache::lonuserstate();
use LONCAPA qw(:DEFAULT :match);
use DateTime::TimeZone;
use DateTime::Locale::Catalog;
+use Authen::Captcha;
+use Captcha::reCAPTCHA;
# ---------------------------------------------- Designs
use vars qw(%defaultdesign);
@@ -524,7 +528,8 @@ ENDAUTHORBRW
}
sub coursebrowser_javascript {
- my ($domainfilter,$sec_element,$formname,$role_element,$crstype) = @_;
+ my ($domainfilter,$sec_element,$formname,$role_element,$crstype,
+ $credits_element) = @_;
my $wintitle = 'Course_Browser';
if ($crstype eq 'Community') {
$wintitle = 'Community_Browser';
@@ -587,8 +592,9 @@ sub coursebrowser_javascript {
}
$id_functions
ENDSTDBRW
- if (($sec_element ne '') || ($role_element ne '')) {
- $output .= &setsec_javascript($sec_element,$formname,$role_element);
+ if (($sec_element ne '') || ($role_element ne '') || ($credits_element ne '')) {
+ $output .= &setsec_javascript($sec_element,$formname,$role_element,
+ $credits_element);
}
$output .= '
// ]]>
@@ -745,7 +751,7 @@ ENDUSERBRW
}
sub setsec_javascript {
- my ($sec_element,$formname,$role_element) = @_;
+ my ($sec_element,$formname,$role_element,$credits_element) = @_;
my (@courserolenames,@communityrolenames,$rolestr,$courserolestr,
$communityrolestr);
if ($role_element ne '') {
@@ -840,6 +846,14 @@ function setRole(crstype) {
}
|;
}
+ if ($credits_element) {
+ $setsections .= qq|
+function setCredits(defaultcredits) {
+ document.$formname.$credits_element.value = defaultcredits;
+ return;
+}
+|;
+ }
return $setsections;
}
@@ -885,10 +899,14 @@ sub check_uncheck_jscript {
function checkAll(field) {
if (field.length > 0) {
for (i = 0; i < field.length; i++) {
- field[i].checked = true ;
+ if (!field[i].disabled) {
+ field[i].checked = true;
+ }
}
} else {
- field.checked = true
+ if (!field.disabled) {
+ field.checked = true;
+ }
}
}
@@ -990,6 +1008,7 @@ sub select_language {
$langchoices{$code} = &plainlanguagedescription($id);
}
}
+ %langchoices = &Apache::lonlocal::texthash(%langchoices);
return &select_form($selected,$name,\%langchoices);
}
@@ -1021,6 +1040,12 @@ linked_select_forms takes the following
=item * $menuorder, the order of values in the first menu
+=item * $onchangefirst, additional javascript call to execute for an onchange
+ event for the first
generation
+ no_inline_link -> if true and in remote mode, don't show the
+ 'Switch To Inline Menu' link
no_auto_mt_title -> prevent &mt()ing the title arg
inherit_jsmath -> when creating popup window in a page,
should it have jsmath forced on by the
current page
bread_crumbs -> Array containing breadcrumbs
bread_crumbs_component -> if exists show it as headline else show only the breadcrumbs
+ group -> includes the current group, if page is for a
+ specific group
=back
@@ -6963,7 +7465,7 @@ sub start_page {
#&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
$env{'internal.start_page'}++;
- my $result;
+ my ($result,@advtools);
if (! exists($args->{'skip_phases'}{'head'}) ) {
$result .= &xml_begin() . &headtag($title, $head_extra, $args);
@@ -6980,7 +7482,8 @@ sub start_page {
$args->{'function'}, $args->{'add_entries'},
$args->{'only_body'}, $args->{'domain'},
$args->{'force_register'}, $args->{'no_nav_bar'},
- $args->{'bgcolor'}, $args);
+ $args->{'bgcolor'}, $args->{'no_inline_link'},
+ $args, \@advtools);
}
}
@@ -7009,6 +7512,10 @@ sub start_page {
&Apache::lonhtmlcommon::add_breadcrumb($crumb);
}
}
+ # if @advtools array contains items add then to the breadcrumbs
+ if (@advtools > 0) {
+ &Apache::lonmenu::advtools_crumbs(@advtools);
+ }
#if bread_crumbs_component exists show it as headline else show only the breadcrumbs
if(exists($args->{'bread_crumbs_component'})){
@@ -7016,6 +7523,11 @@ sub start_page {
}else{
$result .= &Apache::lonhtmlcommon::breadcrumbs();
}
+ } elsif (($env{'environment.remote'} eq 'on') &&
+ ($env{'form.inhibitmenu'} ne 'yes') &&
+ ($env{'request.noversionuri'} =~ m{^/res/}) &&
+ ($env{'request.noversionuri'} !~ m{^/res/adm/pages/})) {
+ $result .= '
-
ENDPROGBAR
&r_print($r,$content.&LCprogressbar_script($LCcurrentid));
}
@@ -7371,16 +7889,21 @@ sub validate_page {
sub start_scrollbox {
- my ($outerwidth,$width,$height,$id)=@_;
+ my ($outerwidth,$width,$height,$id,$bgcolor)=@_;
unless ($outerwidth) { $outerwidth='520px'; }
unless ($width) { $width='500px'; }
unless ($height) { $height='200px'; }
- my ($table_id,$div_id);
+ my ($table_id,$div_id,$tdcol);
if ($id ne '') {
$table_id = " id='table_$id'";
$div_id = " id='div_$id'";
}
- return "
";
+ if ($bgcolor ne '') {
+ $tdcol = "background-color: $bgcolor;";
+ }
+ return <<"END";
+
+END
}
sub end_scrollbox {
@@ -7391,7 +7914,7 @@ sub simple_error_page {
my ($r,$title,$msg) = @_;
my $page =
&Apache::loncommon::start_page($title).
- &mt($msg).
+ '
'.&mt($msg).'
'.
&Apache::loncommon::end_page();
if (ref($r)) {
$r->print($page);
@@ -7606,8 +8129,7 @@ role status: active, previous or future.
sub check_user_status {
my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
- my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
- my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,$extra);
+ my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
my @uroles = keys %userinfo;
my $srchstr;
my $active_chk = 'none';
@@ -7685,7 +8207,19 @@ sub get_sections {
my %sectioncount;
my $now = time;
- if (!defined($possible_roles) || (grep(/^st$/,@$possible_roles))) {
+ my $check_students = 1;
+ my $only_students = 0;
+ if (ref($possible_roles) eq 'ARRAY') {
+ if (grep(/^st$/,@{$possible_roles})) {
+ if (@{$possible_roles} == 1) {
+ $only_students = 1;
+ }
+ } else {
+ $check_students = 0;
+ }
+ }
+
+ if ($check_students) {
my ($classlist) = &Apache::loncoursedata::get_classlist($cdom,$cnum);
my $sec_index = &Apache::loncoursedata::CL_SECTION();
my $status_index = &Apache::loncoursedata::CL_STATUS();
@@ -7712,6 +8246,9 @@ sub get_sections {
}
}
}
+ if ($only_students) {
+ return %sectioncount;
+ }
my %courseroles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
foreach my $user (sort(keys(%courseroles))) {
if ($user !~ /^(\w{2})/) { next; }
@@ -8509,7 +9046,10 @@ sub user_rule_formats {
my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($domain,$check);
if ((ref($rules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {
if (@{$ruleorder} > 0) {
- $output = ' '.&mt("$text{$check} with the following format(s) may only be used for verified users at [_1]:",$domdesc).'
';
+ $output = ' '.
+ &mt($text{$check}.' with the following format(s) may [_1]only[_2] be used for verified users at [_3]:',
+ '','',$domdesc).
+ '
';
foreach my $rule (@{$ruleorder}) {
if (ref($curr_rules) eq 'ARRAY') {
if (grep(/^\Q$rule\E$/,@{$curr_rules})) {
@@ -8978,21 +9518,37 @@ sub get_env_multiple {
sub ask_for_embedded_content {
my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
- my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges);
- my $num = 0;
+ my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges,
+ %currsubfile,%unused,$rem);
+ my $counter = 0;
+ my $numnew = 0;
my $numremref = 0;
my $numinvalid = 0;
my $numpathchg = 0;
my $numexisting = 0;
- my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath);
- if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+ my $numunused = 0;
+ my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath,$cdom,$cnum,
+ $fileloc,$filename,$delete_output,$modify_output,$title,$symb,$path);
+ my $heading = &mt('Upload embedded files');
+ my $buttontext = &mt('Upload');
+
+ my ($navmap,$cdom,$cnum);
+ if ($env{'request.course.id'}) {
+ if ($actionurl eq '/adm/dependencies') {
+ $navmap = Apache::lonnavmaps::navmap->new();
+ }
+ $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ }
+ if (($actionurl eq '/adm/portfolio') ||
+ ($actionurl eq '/adm/coursegrp_portfolio')) {
my $current_path='/';
if ($env{'form.currentpath'}) {
$current_path = $env{'form.currentpath'};
}
if ($actionurl eq '/adm/coursegrp_portfolio') {
- $udom = $env{'course.'.$env{'request.course.id'}.'.domain'};
- $uname = $env{'course.'.$env{'request.course.id'}.'.num'};
+ $udom = $cdom;
+ $uname = $cnum;
$url = '/userfiles/groups/'.$env{'form.group'}.'/portfolio';
} else {
$udom = $env{'user.domain'};
@@ -9012,12 +9568,55 @@ sub ask_for_embedded_content {
}
} elsif ($actionurl eq '/adm/coursedocs') {
if (ref($args) eq 'HASH') {
- $url = $args->{'docs_url'};
- $toplevel = $url;
+ $url = $args->{'docs_url'};
+ $toplevel = $url;
+ if ($args->{'context'} eq 'paste') {
+ ($cdom,$cnum) = ($url =~ m{^\Q/uploaded/\E($match_domain)/($match_courseid)/});
+ ($path) =
+ ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});
+ $fileloc = &Apache::lonnet::filelocation('',$toplevel);
+ $fileloc =~ s{^/}{};
+ }
+ }
+ } elsif ($actionurl eq '/adm/dependencies') {
+ if ($env{'request.course.id'} ne '') {
+ if (ref($args) eq 'HASH') {
+ $url = $args->{'docs_url'};
+ $title = $args->{'docs_title'};
+ $toplevel = $url;
+ unless ($toplevel =~ m{^/}) {
+ $toplevel = "/$url";
+ }
+ ($rem) = ($toplevel =~ m{^(.+/)[^/]+$});
+ if ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/portfolio/syllabus\E)}) {
+ $path = $1;
+ } else {
+ ($path) =
+ ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});
+ }
+ $fileloc = &Apache::lonnet::filelocation('',$toplevel);
+ $fileloc =~ s{^/}{};
+ ($filename) = ($fileloc =~ m{.+/([^/]+)$});
+ $heading = &mt('Status of dependencies in [_1]',"$title ($filename)");
+ }
}
+ } elsif ($actionurl eq "/public/$cdom/$cnum/syllabus") {
+ $udom = $cdom;
+ $uname = $cnum;
+ $url = "/uploaded/$cdom/$cnum/portfolio/syllabus";
+ $toplevel = $url;
+ $path = $url;
+ $fileloc = &Apache::lonnet::filelocation('',$toplevel).'/';
+ $fileloc =~ s{^/}{};
+ }
}
- my $now = time();
- foreach my $embed_file (keys(%{$allfiles})) {
+ foreach my $file (keys(%{$allfiles})) {
+ my $embed_file;
+ if (($path eq "/uploaded/$cdom/$cnum/portfolio/syllabus") && ($file =~ m{^\Q$path/\E(.+)$})) {
+ $embed_file = $1;
+ } else {
+ $embed_file = $file;
+ }
my $absolutepath;
if ($embed_file =~ m{^\w+://}) {
$newfiles{$embed_file} = 1;
@@ -9052,25 +9651,53 @@ sub ask_for_embedded_content {
}
}
}
+ my $dirptr = 16384;
foreach my $path (keys(%subdependencies)) {
- my %currsubfile;
- if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+ $currsubfile{$path} = {};
+ if (($actionurl eq '/adm/portfolio') ||
+ ($actionurl eq '/adm/coursegrp_portfolio')) {
my ($sublistref,$listerror) =
&Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);
if (ref($sublistref) eq 'ARRAY') {
foreach my $line (@{$sublistref}) {
my ($file_name,$rest) = split(/\&/,$line,2);
- $currsubfile{$file_name} = 1;
+ $currsubfile{$path}{$file_name} = 1;
}
}
} elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
if (opendir(my $dir,$url.'/'.$path)) {
my @subdir_list = grep(!/^\./,readdir($dir));
- map {$currsubfile{$_} = 1;} @subdir_list;
+ map {$currsubfile{$path}{$_} = 1;} @subdir_list;
+ }
+ } elsif (($actionurl eq '/adm/dependencies') ||
+ (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
+ ($args->{'context'} eq 'paste')) ||
+ ($actionurl eq "/public/$cdom/$cnum/syllabus")) {
+ if ($env{'request.course.id'} ne '') {
+ my $dir;
+ if ($actionurl eq "/public/$cdom/$cnum/syllabus") {
+ $dir = $fileloc;
+ } else {
+ ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});
+ }
+ if ($dir ne '') {
+ my ($sublistref,$listerror) =
+ &Apache::lonnet::dirlist($dir.$path,$cdom,$cnum,$getpropath,undef,'/');
+ if (ref($sublistref) eq 'ARRAY') {
+ foreach my $line (@{$sublistref}) {
+ my ($file_name,$dom,undef,$testdir,undef,undef,undef,undef,$size,
+ undef,$mtime)=split(/\&/,$line,12);
+ unless (($testdir&$dirptr) ||
+ ($file_name =~ /^\.\.?$/)) {
+ $currsubfile{$path}{$file_name} = [$size,$mtime];
+ }
+ }
+ }
+ }
}
}
foreach my $file (keys(%{$subdependencies{$path}})) {
- if ($currsubfile{$file}) {
+ if (exists($currsubfile{$path}{$file})) {
my $item = $path.'/'.$file;
unless ($mapping{$item} eq $item) {
$pathchanges{$item} = 1;
@@ -9081,9 +9708,27 @@ sub ask_for_embedded_content {
$newfiles{$path.'/'.$file} = 1;
}
}
+ if ($actionurl eq '/adm/dependencies') {
+ foreach my $path (keys(%currsubfile)) {
+ if (ref($currsubfile{$path}) eq 'HASH') {
+ foreach my $file (keys(%{$currsubfile{$path}})) {
+ unless ($subdependencies{$path}{$file}) {
+ next if (($rem ne '') &&
+ (($env{"httpref.$rem"."$path/$file"} ne '') ||
+ (ref($navmap) &&
+ (($navmap->getResourceByUrl($rem."$path/$file") ne '') ||
+ (($file =~ /^(.*\.s?html?)\.bak$/i) &&
+ ($navmap->getResourceByUrl($rem."$path/$1")))))));
+ $unused{$path.'/'.$file} = 1;
+ }
+ }
+ }
+ }
+ }
}
my %currfile;
- if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+ if (($actionurl eq '/adm/portfolio') ||
+ ($actionurl eq '/adm/coursegrp_portfolio')) {
my ($dirlistref,$listerror) =
&Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);
if (ref($dirlistref) eq 'ARRAY') {
@@ -9097,9 +9742,30 @@ sub ask_for_embedded_content {
my @dir_list = grep(!/^\./,readdir($dir));
map {$currfile{$_} = 1;} @dir_list;
}
+ } elsif (($actionurl eq '/adm/dependencies') ||
+ (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
+ ($args->{'context'} eq 'paste')) ||
+ ($actionurl eq "/public/$cdom/$cnum/syllabus")) {
+ if ($env{'request.course.id'} ne '') {
+ my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$});
+ if ($dir ne '') {
+ my ($dirlistref,$listerror) =
+ &Apache::lonnet::dirlist($dir,$cdom,$cnum,$getpropath,undef,'/');
+ if (ref($dirlistref) eq 'ARRAY') {
+ foreach my $line (@{$dirlistref}) {
+ my ($file_name,$dom,undef,$testdir,undef,undef,undef,undef,
+ $size,undef,$mtime)=split(/\&/,$line,12);
+ unless (($testdir&$dirptr) ||
+ ($file_name =~ /^\.\.?$/)) {
+ $currfile{$file_name} = [$size,$mtime];
+ }
+ }
+ }
+ }
+ }
}
foreach my $file (keys(%dependencies)) {
- if ($currfile{$file}) {
+ if (exists($currfile{$file})) {
unless ($mapping{$file} eq $file) {
$pathchanges{$file} = 1;
}
@@ -9109,41 +9775,137 @@ sub ask_for_embedded_content {
$newfiles{$file} = 1;
}
}
+ foreach my $file (keys(%currfile)) {
+ unless (($file eq $filename) ||
+ ($file eq $filename.'.bak') ||
+ ($dependencies{$file})) {
+ if ($actionurl eq '/adm/dependencies') {
+ unless ($toplevel =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus\E}) {
+ next if (($rem ne '') &&
+ (($env{"httpref.$rem".$file} ne '') ||
+ (ref($navmap) &&
+ (($navmap->getResourceByUrl($rem.$file) ne '') ||
+ (($file =~ /^(.*\.s?html?)\.bak$/i) &&
+ ($navmap->getResourceByUrl($rem.$1)))))));
+ }
+ }
+ $unused{$file} = 1;
+ }
+ }
+ if (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') &&
+ ($args->{'context'} eq 'paste')) {
+ $counter = scalar(keys(%existing));
+ $numpathchg = scalar(keys(%pathchanges));
+ return ($output,$counter,$numpathchg,\%existing);
+ } elsif (($actionurl eq "/public/$cdom/$cnum/syllabus") &&
+ (ref($args) eq 'HASH') && ($args->{'context'} eq 'rewrites')) {
+ $counter = scalar(keys(%existing));
+ $numpathchg = scalar(keys(%pathchanges));
+ return ($output,$counter,$numpathchg,\%existing,\%mapping);
+ }
foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {
+ if ($actionurl eq '/adm/dependencies') {
+ next if ($embed_file =~ m{^\w+://});
+ }
$upload_output .= &start_data_table_row().
- '
';
}
+ if ($context eq 'syllabus') {
+ unless ($saveresult eq 'ok') {
+ $skiprewrites = 1;
+ }
+ }
} else {
if (open(my $fh,">$container")) {
print $fh $content;
@@ -9570,12 +10453,57 @@ sub modify_html_refs {
}
}
}
+ if (($context eq 'syllabus') && (!$skiprewrites)) {
+ my ($actionurl,$state);
+ $actionurl = "/public/$udom/$uname/syllabus";
+ my ($ignore,$num,$numpathchanges,$existing,$mapping) =
+ &ask_for_embedded_content($actionurl,$state,\%allfiles,
+ \%codebase,
+ {'context' => 'rewrites',
+ 'ignore_remote_references' => 1,});
+ if (ref($mapping) eq 'HASH') {
+ my $rewrites = 0;
+ foreach my $key (keys(%{$mapping})) {
+ next if ($key =~ m{^https?://});
+ my $ref = $mapping->{$key};
+ my $newname = "/uploaded/$udom/$uname/portfolio/syllabus/$key";
+ my $attrib;
+ if (ref($allfiles{$mapping->{$key}}) eq 'ARRAY') {
+ $attrib = join('|',@{$allfiles{$mapping->{$key}}});
+ }
+ if ($content =~ m{($attrib\s*=\s*['"]?)\Q$ref\E(['"]?)}) {
+ my $numchg = ($content =~ s{($attrib\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
+ $rewrites += $numchg;
+ }
+ }
+ if ($rewrites) {
+ my $saveresult;
+ my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
+ if ($url eq $container) {
+ my ($fname) = ($container =~ m{/([^/]+)$});
+ $output .= '
'.&mt('Rewrote [quant,_1,link] as [quant,_1,absolute link] in [_2].',
+ $count,''.
+ $fname.'').'
';
+ } else {
+ $output .= '
'.
+ &mt('Error: could not update links in [_1].',
+ ''.
+ $container.'').'
';
+
+ }
+ }
+ }
+ }
} else {
&logthis('Failed to parse '.$container.
' to modify references: '.$parse_result);
}
}
- return $output;
+ if (wantarray) {
+ return ($output,$count,$codebasecount);
+ } else {
+ return $output;
+ }
}
sub check_for_existing {
@@ -9742,43 +10670,226 @@ sub is_archive_file {
}
sub decompress_form {
- my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements) = @_;
+ my ($mimetype,$archiveurl,$action,$noextract,$hiddenelements,$dirlist) = @_;
my %lt = &Apache::lonlocal::texthash (
this => 'This file is an archive file.',
+ camt => 'This file is a Camtasia archive file.',
+ itsc => 'Its contents are as follows:',
youm => 'You may wish to extract its contents.',
- camt => 'Extraction of contents is recommended for Camtasia zip files.',
- perm => 'Permanently remove archive file after extraction of contents?',
extr => 'Extract contents',
+ auto => 'LON-CAPA can process the files automatically, or you can decide how each should be handled.',
+ proa => 'Process automatically?',
yes => 'Yes',
no => 'No',
+ fold => 'Title for folder containing movie',
+ movi => 'Title for page containing embedded movie',
);
- my $output = '