[LON-CAPA-cvs] cvs: loncom /auth lonwebdavacc.pm
raeburn
raeburn at source.lon-capa.org
Mon Jun 23 16:27:46 EDT 2014
raeburn Mon Jun 23 20:27:46 2014 EDT
Modified files:
/loncom/auth lonwebdavacc.pm
Log:
- Bug 6034
- Methods checking in webDAV:
- MKCOL/PUT disallowed for reserved filenames: *.meta, *.bak, *.save, *.log
- MOVE/DELETE disallowed for published files (unless marked obsolete).
- MOVE/DELETE disallowed for *.meta and *.log if corresponding file has
published status (unless marked obsolete).
- For MOVE/DELETE for a directory do (recursive) count of contained published
files (unless marked obsolete), and disallow if count > 0.
Index: loncom/auth/lonwebdavacc.pm
diff -u loncom/auth/lonwebdavacc.pm:1.1 loncom/auth/lonwebdavacc.pm:1.2
--- loncom/auth/lonwebdavacc.pm:1.1 Mon Feb 27 03:06:33 2012
+++ loncom/auth/lonwebdavacc.pm Mon Jun 23 20:27:46 2014
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Authorization Handler for webDAV access to Authoring Space.
#
-# $Id: lonwebdavacc.pm,v 1.1 2012/02/27 03:06:33 raeburn Exp $
+# $Id: lonwebdavacc.pm,v 1.2 2014/06/23 20:27:46 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -124,6 +124,7 @@
use GDBM_File;
use Apache::Constants qw(:common :http :methods);
use Apache::lonnet;
+use Apache::londiff();
use LONCAPA qw(:DEFAULT :match);
sub handler {
@@ -156,19 +157,62 @@
} elsif (!-d "$docroot/priv/$adom/$aname") {
return FORBIDDEN;
}
- # FIXME method check for MKCOL MOVE PUT DELETE for *.log, *.bak
- # FIXME method check for regexp for "version-style" names: /\.\d+\.\w+$/
- # for MOVE PUT MKCOL
+ my $allowed;
if (($env{'user.name'} eq $aname) && ($env{'user.domain'} eq $adom)) {
if ($env{"user.role.au./$adom/"}) {
- return OK;
+ $allowed = 1;
}
} else {
if (($env{"user.role.ca./$adom/$aname"}) ||
(env{"user.role.aa./$adom/$aname"})) {
- return OK;
+ $allowed = 1;
}
}
+ if ($allowed) {
+ my $method = $r->method();
+ if (($r->filename =~ /.+\.(log|bak|meta|save)$/) || ($r->filename =~ /\.\d+\.\w+$/) ||
+ ($r->filename =~ m{/\.+[^_/]+$})) {
+ if (($method eq 'MKCOL') || ($method eq 'PUT')) {
+ return FORBIDDEN;
+ } elsif ($method eq 'MOVE') {
+ if (($r->filename =~ /\.\d+\.\w+$/) || ($r->filename =~ m{/\.+[^_/]+$})) {
+ return FORBIDDEN;
+ }
+ }
+ }
+ if (($method eq 'DELETE') || ($method eq 'MOVE')) {
+ unless (($r->filename =~ m{/\._[^/]+$}) || ($r->filename =~ m{/\.DS_Store$})) {
+ my $dirptr=16384;
+ my ($cmode,$cmtime)=(stat($r->filename))[2,9];
+ if (($cmode&$dirptr)) {
+ my $numpub = 0;
+ $numpub = &recurse_dir($r->filename,$r->dir_config('lonDocRoot'),$numpub);
+ if ($numpub) {
+ return FORBIDDEN;
+ }
+ } else {
+ if ($r->filename =~ /^(.+)\.(log|bak|save|meta)$/) {
+ my $conjugate = $1;
+ my $type = $2;
+ if (($type eq 'log') || ($type eq 'meta')) {
+ if (-e $conjugate) {
+ my $conjstatus = &pubstatus($conjugate,$r->dir_config('lonDocRoot'));
+ unless (($conjstatus eq 'unpublished') || ($conjstatus eq 'obsolete')) {
+ return FORBIDDEN;
+ }
+ }
+ }
+ } else {
+ my $status = &pubstatus($r->filename,$r->dir_config('lonDocRoot'));
+ unless (($status eq 'unpublished') || ($status eq 'obsolete')) {
+ return FORBIDDEN;
+ }
+ }
+ }
+ }
+ }
+ return OK;
+ }
return FORBIDDEN;
}
@@ -201,4 +245,56 @@
return ($handle);
}
+sub pubstatus {
+ my ($fn,$docroot,$cmtime) = @_;
+ my $privfn = $fn;
+ my $thisdisfn = $fn;
+ $thisdisfn=~s/^\Q$docroot\E\/priv//;
+ my $resfn=$docroot.'/res'.$thisdisfn;
+ my $targetfn = '/res'.$thisdisfn;
+ my $status = 'unpublished';
+ if (-e $resfn) {
+ $status = 'published';
+ my $same = 0;
+ if ((stat($resfn))[9] >= $cmtime) {
+ $same = 1;
+ } else {
+ if (&Apache::londiff::are_different_files($resfn,$privfn)) {
+ $same = 0;
+ } else {
+ $same = 1;
+ }
+ }
+ if ($same) {
+ if (&Apache::lonnet::metadata($targetfn,'obsolete')) {
+ $status = 'obsolete';
+ }
+ }
+ }
+ return $status;
+}
+
+sub recurse_dir {
+ my ($dirname,$docroot,$numpub) = @_;
+ $dirname =~ s{/$}{};
+ my $dirptr=16384;
+ if (opendir(my $dirh,$dirname)) {
+ my @items = readdir($dirh);
+ closedir($dirh);
+ foreach my $item (@items) {
+ next if ($item =~ /.+\.(log|bak|save|meta)$/);
+ next if ($item =~ /^\.+/);
+ my ($cmode,$cmtime)=(stat("$dirname/$item"))[2,9];
+ if (!($cmode&$dirptr)) {
+ if (&pubstatus("$dirname/$item",$docroot,$cmtime) eq 'published') {
+ $numpub ++;
+ }
+ } else {
+ $numpub = &recursedir("$dirname/$item",$docroot,$numpub);
+ }
+ }
+ }
+ return $numpub;
+}
+
1;
More information about the LON-CAPA-cvs
mailing list