[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