pnever      2004/04/25 10:34:27

  Modified:    src/webdav/server/org/apache/slide/webdav/method Tag:
                        SLIDE_2_0_RELEASE_BRANCH PutMethod.java
                        GetMethod.java AbstractWebdavMethod.java
  Log:
  FIXED BUG: If headers were not checked for PUT
  
  Revision  Changes    Path
  No                   revision
  No                   revision
  1.69.2.2  +25 -4     
jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java
  
  Index: PutMethod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java,v
  retrieving revision 1.69.2.1
  retrieving revision 1.69.2.2
  diff -u -r1.69.2.1 -r1.69.2.2
  --- PutMethod.java    5 Feb 2004 16:11:23 -0000       1.69.2.1
  +++ PutMethod.java    25 Apr 2004 17:34:27 -0000      1.69.2.2
  @@ -5,7 +5,7 @@
    *
    * ====================================================================
    *
  - * Copyright 1999-2002 The Apache Software Foundation 
  + * Copyright 1999-2002 The Apache Software Foundation
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
  @@ -187,6 +187,16 @@
                       revisionDescriptor.setContentLength(-1);
                   }
                   
  +                ResourceInfo resourceInfo =
  +                    new ResourceInfo(resourcePath, revisionDescriptor);
  +                
  +                // Checking If headers
  +                if (!checkIfHeaders(req, resp, resourceInfo)) {
  +                    int statusCode = WebdavStatus.SC_PRECONDITION_FAILED;
  +                    sendError( statusCode, "Check If Header failed" );
  +                    throw new WebdavException( statusCode );
  +                }
  +                
                   ResourceKind resourceKind = 
AbstractResourceKind.determineResourceKind(token, resourcePath, revisionDescriptor);
                   
                   versioningHelper.isWriteLocked(slideToken, revisionDescriptors);
  @@ -294,6 +304,17 @@
                   
                   NodeRevisionDescriptor revisionDescriptor =
                       new NodeRevisionDescriptor(req.getContentLength());
  +                
  +                ResourceInfo resourceInfo =
  +                    new ResourceInfo(resourcePath, revisionDescriptor);
  +                resourceInfo.exists = false;
  +                
  +                // Checking If headers
  +                if (!checkIfHeaders(req, resp, resourceInfo)) {
  +                    int statusCode = WebdavStatus.SC_PRECONDITION_FAILED;
  +                    sendError( statusCode, "Check If Header failed" );
  +                    throw new WebdavException( statusCode );
  +                }
                   
                   //NodeProperty property = null;
                   
  
  
  
  1.40.2.4  +4 -248    
jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java
  
  Index: GetMethod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java,v
  retrieving revision 1.40.2.3
  retrieving revision 1.40.2.4
  diff -u -r1.40.2.3 -r1.40.2.4
  --- GetMethod.java    9 Feb 2004 07:27:51 -0000       1.40.2.3
  +++ GetMethod.java    25 Apr 2004 17:34:27 -0000      1.40.2.4
  @@ -5,7 +5,7 @@
    *
    * ====================================================================
    *
  - * Copyright 1999-2002 The Apache Software Foundation 
  + * Copyright 1999-2002 The Apache Software Foundation
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
  @@ -27,10 +27,8 @@
   import java.io.IOException;
   import java.io.InputStream;
   import java.text.ParseException;
  -import java.text.SimpleDateFormat;
   import java.util.Date;
   import java.util.Enumeration;
  -import java.util.Locale;
   import java.util.StringTokenizer;
   import java.util.Vector;
   import javax.servlet.ServletOutputStream;
  @@ -71,15 +69,6 @@
       protected final int BUFFER_SIZE = 2048;
   
   
  -    /**
  -     * The set of SimpleDateFormat formats to use in getDateHeader().
  -     */
  -    protected static final SimpleDateFormat formats[] = {
  -        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
  -            new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
  -            new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
  -    };
  -
   
       /**
        * MIME multipart separation string
  @@ -339,186 +328,6 @@
       // -------------------------------------------------------- Private Methods
   
   
  -    /**
  -     * Check if the conditions specified in the optional If headers are
  -     * satisfied.
  -     *
  -     * @param request The servlet request we are processing
  -     * @param response The servlet response we are creating
  -     * @param resourceInfo File object
  -     * @return boolean true if the resource meets all the specified conditions,
  -     * and false if any of the conditions is not satisfied, in which case
  -     * request processing is stopped
  -     */
  -    private boolean checkIfHeaders(HttpServletRequest request,
  -                                   HttpServletResponse response,
  -                                   ResourceInfo resourceInfo)
  -        throws IOException {
  -
  -        String eTag = getETag(resourceInfo, true);
  -        long fileLength = resourceInfo.length;
  -        long lastModified = resourceInfo.date;
  -
  -        StringTokenizer commaTokenizer;
  -
  -        String headerValue;
  -
  -        // Checking If-Match
  -        headerValue = request.getHeader("If-Match");
  -        if (headerValue != null) {
  -            if (headerValue.indexOf("*") == -1) {
  -
  -                commaTokenizer = new StringTokenizer(headerValue, ",");
  -                boolean conditionSatisfied = false;
  -
  -                while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
  -                    String currentToken = commaTokenizer.nextToken();
  -                    if (currentToken.trim().equals(eTag))
  -                        conditionSatisfied = true;
  -                }
  -
  -                // If none of the given ETags match, 412 Precodition failed is
  -                // sent back
  -                if (!conditionSatisfied) {
  -                    response.sendError
  -                        (HttpServletResponse.SC_PRECONDITION_FAILED);
  -                    return false;
  -                }
  -
  -            }
  -        }
  -
  -        // Checking If-Modified-Since
  -        headerValue = request.getHeader("If-Modified-Since");
  -        if (headerValue != null) {
  -
  -            // If an If-None-Match header has been specified, if modified since
  -            // is ignored.
  -            if (request.getHeader("If-None-Match") == null) {
  -
  -                Date date = null;
  -
  -                // Parsing the HTTP Date
  -                for (int i = 0; (date == null) && (i < formats.length); i++) {
  -                    try {
  -                        synchronized (formats[i]) {
  -                            date = formats[i].parse(headerValue);
  -                        }
  -                    } catch (ParseException e) {
  -                        ;
  -                    }
  -                }
  -
  -                if ((date != null)
  -                    && (lastModified <= (date.getTime() + 1000)) ) {
  -                    // The entity has not been modified since the date
  -                    // specified by the client. This is not an error case.
  -                    response.sendError
  -                        (HttpServletResponse.SC_NOT_MODIFIED);
  -                    return false;
  -                }
  -
  -            }
  -
  -        }
  -
  -        // Checking If-None-Match
  -        headerValue = request.getHeader("If-None-Match");
  -        if (headerValue != null) {
  -            if (headerValue.indexOf("*") == -1) {
  -
  -                commaTokenizer = new StringTokenizer(headerValue, ",");
  -                boolean conditionSatisfied = false;
  -
  -                while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
  -                    String currentToken = commaTokenizer.nextToken();
  -                    if (currentToken.trim().equals(eTag))
  -                        conditionSatisfied = true;
  -                }
  -
  -                if (conditionSatisfied) {
  -
  -                    // For GET and HEAD, we should respond with
  -                    // 304 Not Modified.
  -                    // For every other method, 412 Precondition Failed is sent
  -                    // back.
  -                    if ( ("GET".equals(request.getMethod()))
  -                        || ("HEAD".equals(request.getMethod())) ) {
  -                        response.sendError
  -                            (HttpServletResponse.SC_NOT_MODIFIED);
  -                        return false;
  -                    } else {
  -                        response.sendError
  -                            (HttpServletResponse.SC_PRECONDITION_FAILED);
  -                        return false;
  -                    }
  -                }
  -
  -            } else {
  -                if (resourceInfo.exists()) {
  -
  -                }
  -            }
  -        }
  -
  -        // Checking If-Unmodified-Since
  -        headerValue = request.getHeader("If-Unmodified-Since");
  -        if (headerValue != null) {
  -
  -            Date date = null;
  -
  -            // Parsing the HTTP Date
  -            for (int i = 0; (date == null) && (i < formats.length); i++) {
  -                try {
  -                    synchronized (formats[i]) {
  -                        date = formats[i].parse(headerValue);
  -                    }
  -                } catch (ParseException e) {
  -                    ;
  -                }
  -            }
  -
  -            if ( (date != null) && (lastModified > date.getTime()) ) {
  -                // The entity has not been modified since the date
  -                // specified by the client. This is not an error case.
  -                response.sendError
  -                    (HttpServletResponse.SC_PRECONDITION_FAILED);
  -                return false;
  -            }
  -
  -        }
  -
  -        return true;
  -    }
  -
  -
  -    /**
  -     * Get the ETag value associated with a file.
  -     *
  -     * @param resourceInfo File object
  -     * @param strong True if we want a strong ETag, in which case a checksum
  -     * of the file has to be calculated
  -     */
  -    private String getETagValue(ResourceInfo resourceInfo, boolean strong) {
  -        // FIXME : Compute a strong ETag if requested, using an MD5 digest
  -        // of the file contents
  -        return resourceInfo.length + "-" + resourceInfo.date;
  -    }
  -
  -
  -    /**
  -     * Get the ETag associated with a file.
  -     *
  -     * @param resourceInfo File object
  -     * @param strong True if we want a strong ETag, in which case a checksum
  -     * of the file has to be calculated
  -     */
  -    private String getETag(ResourceInfo resourceInfo, boolean strong) {
  -        if (strong)
  -            return "\"" + getETagValue(resourceInfo, strong) + "\"";
  -        else
  -            return "W/\"" + getETagValue(resourceInfo, strong) + "\"";
  -    }
   
   
       /**
  @@ -923,57 +732,4 @@
           }
   
       }
  -
  -
  -    // ----------------------------------------------  ResourceInfo Inner Class
  -
  -
  -    private class ResourceInfo {
  -
  -
  -        /**
  -         * Constructor.
  -         *
  -         * @param pathname Path name of the file
  -         */
  -        public ResourceInfo(String path, NodeRevisionDescriptor properties) {
  -
  -            this.path = path;
  -            this.exists = true;
  -            this.creationDate = properties.getCreationDateAsDate().getTime();
  -            this.date = properties.getLastModifiedAsDate().getTime();
  -            this.httpDate = properties.getLastModified();
  -            this.length = properties.getContentLength();
  -
  -        }
  -
  -
  -        public String path;
  -        public long creationDate;
  -        public String httpDate;
  -        public long date;
  -        public long length;
  -        //public boolean collection;
  -        public boolean exists;
  -
  -
  -        /**
  -         * Test if the associated resource exists.
  -         */
  -        public boolean exists() {
  -            return exists;
  -        }
  -
  -
  -        /**
  -         * String representation.
  -         */
  -        public String toString() {
  -            return path;
  -        }
  -
  -
  -    }
  -
  -
   }
  
  
  
  1.20.2.4  +416 -173  
jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AbstractWebdavMethod.java
  
  Index: AbstractWebdavMethod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AbstractWebdavMethod.java,v
  retrieving revision 1.20.2.3
  retrieving revision 1.20.2.4
  diff -u -r1.20.2.3 -r1.20.2.4
  --- AbstractWebdavMethod.java 1 Apr 2004 13:46:39 -0000       1.20.2.3
  +++ AbstractWebdavMethod.java 25 Apr 2004 17:34:27 -0000      1.20.2.4
  @@ -5,7 +5,7 @@
    *
    * ====================================================================
    *
  - * Copyright 1999-2002 The Apache Software Foundation 
  + * Copyright 1999-2002 The Apache Software Foundation
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
  @@ -27,15 +27,18 @@
   import java.io.StringWriter;
   import java.security.MessageDigest;
   import java.security.NoSuchAlgorithmException;
  +import java.text.ParseException;
  +import java.text.SimpleDateFormat;
   import java.util.ArrayList;
   import java.util.Collections;
  +import java.util.Date;
   import java.util.Enumeration;
   import java.util.Iterator;
   import java.util.List;
  -
  +import java.util.Locale;
  +import java.util.StringTokenizer;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
  -
   import org.apache.slide.common.Domain;
   import org.apache.slide.common.NamespaceAccessToken;
   import org.apache.slide.common.NestedSlideException;
  @@ -45,10 +48,10 @@
   import org.apache.slide.common.SlideTokenWrapper;
   import org.apache.slide.content.Content;
   import org.apache.slide.content.NodeProperty;
  +import org.apache.slide.content.NodeProperty.NamespaceCache;
   import org.apache.slide.content.NodeRevisionContent;
   import org.apache.slide.content.NodeRevisionDescriptor;
   import org.apache.slide.content.NodeRevisionDescriptors;
  -import org.apache.slide.content.NodeProperty.NamespaceCache;
   import org.apache.slide.lock.Lock;
   import org.apache.slide.lock.NodeLock;
   import org.apache.slide.lock.UnlockListener;
  @@ -88,163 +91,171 @@
    */
   public abstract class AbstractWebdavMethod
       implements WebdavMethod, WebdavConstants, DeltavConstants, BindConstants {
  -
  -
  +    
  +    
       // -------------------------------------------------------------- Constants
  -
  +    
       /**
        * String constant for <code>no-cache</code>.
        */
       protected static final String NO_CACHE = "no-cache";
  -
  +    
       /**
        * String constant for <code>http://</code>.
        */
       public static final String HTTP_PROTOCOL = "http://";;
  -
  +    
       /**
        * String constant for <code>HTTP/1.1</code>.
        */
       public static final String HTTP_VERSION = "HTTP/1.1";
  -
  +    
       /**
        * String constant for <code>text/xml</code>.
        */
       public static final String TEXT_XML = "text/xml";
  -
  +    
       /**
        * String constant for <code>text/xml; charset="UTF-8"</code>.
        */
       public static final String TEXT_XML_UTF_8 = "text/xml; charset=\"UTF-8\"";
  -
  +    
       /**
        * The indent to use in the XML response.
        */
       public static final String XML_REPONSE_INDENT = "    ";
  -
  +    
       private static final String LOG_CHANNEL =
           AbstractWebdavMethod.class.getName();
  -
  +    
       //  public static final String PRINCIPAL =
       //      "org.apache.slide.webdav.method.principal";
  -
  +    
       protected static final int INFINITY = Integer.MAX_VALUE;
       
       protected static final Namespace DNSP = NamespaceCache.DEFAULT_NAMESPACE;
       
  -
  +    /**
  +     * The set of SimpleDateFormat formats to use in getDateHeader().
  +     */
  +    protected static final SimpleDateFormat formats[] = {
  +        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
  +            new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
  +            new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
  +    };
  +    
       // ----------------------------------------------------- Instance Variables
  -
  -
  +    
  +    
       /**
        * Requested Uri.
        */
       protected String requestUri;
  -
  -
  +    
  +    
       /**
        * Servlet request.
        */
       protected HttpServletRequest req;
  -
  -
  +    
  +    
       /**
        * Servlet response.
        */
       protected HttpServletResponse resp;
  -
  -
  +    
  +    
       /**
        * Configuration.
        */
       protected WebdavServletConfig config;
  -
  -
  +    
  +    
       /**
        * Request body.
        */
       protected String requestBody;
  -
  -
  +    
  +    
       /**
        * Namespace access token.
        */
       protected NamespaceAccessToken token;
  -
  -
  +    
  +    
       /**
        * Structure helper.
        */
       protected Structure structure;
  -
  -
  +    
  +    
       /**
        * Content helper.
        */
       protected Content content;
  -
  -
  +    
  +    
       /**
        * Security helper.
        */
       protected Security security;
  -
  -
  +    
  +    
       /**
        * Lock helper.
        */
       protected Lock lock;
  -
  -
  +    
  +    
       /** wam
        * Search helper.
        */
       protected Search search;
  -
  -
  +    
  +    
       /**
        * Macro helper.
        */
       protected Macro macro;
  -
  -
  +    
  +    
       /**
        * Slide token.
        */
       protected SlideToken slideToken;
  -
  -
  +    
  +    
       /**
        * MD5 message digest provider.
        */
       protected static MessageDigest md5Helper;
  -
  -
  +    
  +    
       /**
        * The MD5 helper object for this class.
        */
       protected static final MD5Encoder md5Encoder = new MD5Encoder();
  -
  +    
       /**
        * The request content (XML) Document.
        */
       private Document requestContentDocument = null;
  -
  +    
       /**
        * Indicates if the request content has already been parsed.
        */
       private boolean isRequestContentParsed = false;
  -
  +    
       /**
        * Request headers
        */
       protected RequestHeaders requestHeaders = new RequestHeaders();
  -
  +    
       // -------------------------------------------------- Static Initialization
  -
  -
  +    
  +    
       static {
  -
  +        
           // Load the MD5 helper used to calculate signatures.
           try {
               md5Helper = MessageDigest.getInstance("MD5");
  @@ -253,11 +264,11 @@
               throw new IllegalStateException();
           }
       }
  -
  -
  +    
  +    
       // ----------------------------------------------------------- Constructors
  -
  -
  +    
  +    
       /**
        * Constructor.
        *
  @@ -266,10 +277,10 @@
        */
       public AbstractWebdavMethod(NamespaceAccessToken token,
                                   WebdavServletConfig config) {
  -
  +        
           this.config = config;
           this.token = token;
  -
  +        
           // initialize helpers
           structure = token.getStructureHelper();
           content = token.getContentHelper();
  @@ -277,11 +288,11 @@
           lock = token.getLockHelper();
           macro = token.getMacroHelper();
       }
  -
  -
  +    
  +    
       // -------------------------------------------- WebdavMethod Implementation
  -
  -
  +    
  +    
       /**
        * Exceute method.
        *
  @@ -289,13 +300,13 @@
        */
       public void run(HttpServletRequest req, HttpServletResponse resp)
           throws WebdavException {
  -
  +        
           this.req = req;
           this.resp = resp;
           this.slideToken = WebdavUtils.getSlideToken(req);
           this.requestUri = WebdavUtils.getRelativePath(req, config);
           parseRequestHeaders();
  -
  +        
           boolean transactionIsStarted = false;
           try {
               parseRequest();
  @@ -303,19 +314,19 @@
                   token.begin();
                   transactionIsStarted = true;
               }
  -
  +            
               // clear expired lock-tokens
               try {
                   UnlockListener listener =
                       new UnlockListenerImpl( slideToken, token, config, req, resp );
                   lock.clearExpiredLocks( slideToken, requestUri, listener );
  -
  +                
                   // if the URI has no more locks associated to it and is
                   // a lock-null resource, we must attempt to delete it
  -
  +                
                   Enumeration locks = lock.enumerateLocks(slideToken, requestUri);
                   if (!locks.hasMoreElements()) {
  -
  +                    
                       NodeRevisionDescriptors revisionDescriptors = 
content.retrieve(slideToken, requestUri);
                       NodeRevisionDescriptor revisionDescriptor = 
content.retrieve(slideToken, revisionDescriptors);
                       if (isLockNull(revisionDescriptor)) {
  @@ -328,7 +339,7 @@
                   
               }
               catch (SlideException e) {}
  -
  +            
               executeRequest();
               if (methodNeedsTransactionSupport()) {
                   token.commit();
  @@ -351,33 +362,33 @@
                   }
               }
           }
  -
  +        
       }
  -
  -
  +    
  +    
       // --------------------------------------------------------- Public Methods
  -
  -
  +    
  +    
       /**
        * Returns the configuration of the WebdavServlet.
        *
        * @return WebdavServletConfig
        */
       public WebdavServletConfig getConfig() {
  -
  +        
           return config;
       }
  -
  -
  +    
  +    
       /**
        * Return an absolute path (absolute in the HTTP sense) based on a Slide
        * path.
        */
       public String getFullPath(String slidePath) {
  -       return WebdavUtils.getAbsolutePath(slidePath, req, getConfig());
  +        return WebdavUtils.getAbsolutePath(slidePath, req, getConfig());
       }
  -
  -
  +    
  +    
       /**
        * Returns a Slide path based on an absolute URL
        * (absolute in the HTTP sense)
  @@ -385,11 +396,11 @@
       public String getSlidePath(String fullpath) {
           return WebdavUtils.getSlidePath(fullpath, req.getContextPath());
       }
  -
  -
  +    
  +    
       // ------------------------------------------------------ Protected Methods
  -
  -
  +    
  +    
       /**
        * Return true if the method needs transaction support.
        * Return true if the method needs transaction support, e.g.
  @@ -402,8 +413,8 @@
           // overwrite it to true, but PropFind creates a RevisionDescriptors
           // on the fly
       }
  -
  -
  +    
  +    
       /**
        * Read request contents.
        *
  @@ -411,12 +422,12 @@
        * @return char[] Array of char which contains the body of the request
        */
       protected void readRequestContent() {
  -
  +        
           if (req.getContentLength() == 0)
               return;
  -
  +        
           // TODO : Modify this and make it chunking aware
  -
  +        
           try {
               requestBody = new String(NodeRevisionContent.read(req.getInputStream()),
                                        getEncodingString(req.getCharacterEncoding()));
  @@ -425,9 +436,9 @@
               token.getLogger().log(e,LOG_CHANNEL,Logger.ERROR);
           }
       }
  -
  -
  -
  +    
  +    
  +    
       /**
        * Translate the encoding string into a proper Java encoding String.
        */
  @@ -438,8 +449,8 @@
           if (result.endsWith("\""))   result = result.substring(0, 
result.length()-1);
           return result;
       }
  -
  -
  +    
  +    
       /**
        * Method parseHeaders
        *
  @@ -447,14 +458,14 @@
       private void parseRequestHeaders() throws WebdavException {
           requestHeaders.parse();
       }
  -
  +    
       /**
        * Test if a resource given by a path is a collection
        */
       protected boolean isCollection(String path) {
           return WebdavUtils.isCollection(token, slideToken, path);
       }
  -
  +    
       /**
        * Test whether the resource given by lowerNode is a descendant of the
        * resource given by upperNode
  @@ -473,7 +484,7 @@
           if (upperNode.hasBinding(lowerNode)) {
               return true;
           }
  -
  +        
           // use a non-blocking slide token.
           SlideToken stoken = readonlySlideToken();
           
  @@ -482,7 +493,7 @@
           try {
               lowerNrds = content.retrieve(stoken, lowerNode.getUri());
               lowerNrd = content.retrieve(stoken, lowerNrds);
  -
  +            
               NodeProperty psProp = lowerNrd.getProperty(P_PARENT_SET);
               XMLValue xv = new XMLValue( String.valueOf(psProp.getValue()) );
               Iterator i = xv.getList().iterator();
  @@ -496,11 +507,11 @@
           } catch (ServiceAccessException e) {
               throw e;
           } catch (Exception e) {}
  -
  +        
           return false;
       }
  -
  -
  +    
  +    
       /**
        * Parse WebDAV XML query.
        *
  @@ -508,9 +519,9 @@
        */
       protected abstract void parseRequest()
           throws WebdavException;
  -
  -
  -
  +    
  +    
  +    
       /**
        * Returns the request content (XML) Document.
        *
  @@ -519,9 +530,9 @@
       protected Document getRequestContent() {
           return requestContentDocument;
       }
  -
  +    
       //--
  -
  +    
       /**
        * precondition: sourceUri != null
        */
  @@ -542,12 +553,12 @@
               if ((hostName != null) && (uri.startsWith(hostName))) {
                   uri = uri.substring(hostName.length());
               }
  -
  +            
               int portIndex = uri.indexOf(":");
               if (portIndex >= 0) {
                   uri = uri.substring(portIndex);
               }
  -
  +            
               if (uri.startsWith(":")) {
                   int firstSeparator = uri.indexOf("/");
                   if (firstSeparator < 0) {
  @@ -557,16 +568,16 @@
                   }
               }
           }
  -
  +        
           // headers are "ISO-8859-1" encoded [not any more with TC 4.1.18
           // destinationUri = 
WebdavUtils.decodeURL(WebdavUtils.fixTomcatURL(destinationUri, "ISO-8859-1"));
           uri = WebdavUtils.decodeURL(uri);
  -
  +        
           String contextPath = req.getContextPath();
           if ((contextPath != null) && (uri.startsWith(contextPath))) {
               uri = uri.substring(contextPath.length());
           }
  -
  +        
           String pathInfo = req.getPathInfo();
           if (pathInfo != null) {
               String servletPath = req.getServletPath();
  @@ -575,14 +586,14 @@
               }
           }
           uri = getConfig().getScope() + uri;
  -
  +        
           return uri;
       }
  -
  +    
       protected Element parseRequestContent(String rootName) throws JDOMException, 
IOException {
           Document document;
           Element root;
  -
  +        
           document = parseRequestContent();
           if (document == null) {
               throw new JDOMException("Request content missing");
  @@ -594,7 +605,7 @@
           }
           return root;
       }
  -
  +    
       /**
        * Parses the request content (XML) Document.
        *
  @@ -604,15 +615,15 @@
        * @throws     JDOMException   if parsing the document failed.
        */
       protected Document parseRequestContent() throws JDOMException, IOException {
  -
  +        
           if (isRequestContentParsed) {
               return requestContentDocument;
           }
  -
  +        
           if (req.getContentLength() == 0) {
               return requestContentDocument;
           }
  -
  +        
           try {
               requestContentDocument = new SAXBuilder().build(req.getInputStream());
               isRequestContentParsed = true;
  @@ -625,11 +636,11 @@
                   throw e;
               }
           }
  -
  +        
           return requestContentDocument;
       }
  -
  -
  +    
  +    
       /**
        * Generate XML response.
        *
  @@ -637,8 +648,8 @@
        */
       protected abstract void executeRequest()
           throws WebdavException, IOException;
  -
  -
  +    
  +    
       /**
        * Simulate MS IIS5 ?
        *
  @@ -647,7 +658,7 @@
       protected boolean isMsProprietarySupport() {
           return (token.getNamespaceConfig().getParameter("ms") != null);
       }
  -
  +    
       /**
        * Sends a precondition vilolation response.
        *
  @@ -655,11 +666,11 @@
        *            precondition.
        */
       protected void sendPreconditionViolation(PreconditionViolationException pve) 
throws IOException {
  -
  +        
           if (pve != null) {
  -
  +            
               ViolatedPrecondition violatedPrecondition = 
pve.getViolatedPrecondition();
  -
  +            
               int statusCode = violatedPrecondition.getStatusCode();
               printStackTrace( pve, statusCode );
               String statusText = WebdavStatus.getStatusText(statusCode);
  @@ -667,14 +678,14 @@
                   statusText = statusText+": "+violatedPrecondition.getExplanation();
               }
               resp.setStatus(statusCode, statusText);
  -
  +            
               resp.setContentType(TEXT_XML_UTF_8);
  -
  +            
               new XMLOutputter(XML_REPONSE_INDENT, true).
                   output(new 
Document(MethodUtil.getPreconditionViolationError(pve.getViolatedPrecondition())), 
resp.getWriter());
           }
       }
  -
  +    
       /**
        * Returns the absolute URL of the given <code>uri</code>, e.g.
        * if the server is <code>aloha.com:80</code>, context path is
  @@ -686,18 +697,18 @@
        * @return   the absolute URL.
        */
       protected String getAbsoluteURL(String uri) {
  -
  +        
           StringBuffer buffer = new StringBuffer();
           buffer.append(HTTP_PROTOCOL);
           buffer.append(req.getServerName());
           buffer.append(":");
           buffer.append(req.getServerPort());
  -
  +        
           if ( ! req.getContextPath().startsWith("/") ) {
               buffer.append("/");
           }
           buffer.append(req.getContextPath());
  -
  +        
           if (uri != null) {
               if ( !req.getContextPath().endsWith("/") && !uri.startsWith("/") ) {
                   buffer.append("/");
  @@ -706,35 +717,35 @@
           }
           return buffer.toString();
       }
  -
  +    
       // -------------------------------------------------------- Private Methods
  -
  -
  +    
  +    
       /**
        * Get return status based on exception type.
        */
       protected int getErrorCode(Throwable ex) {
           return WebdavUtils.getErrorCode(ex);
       }
  -
  -
  +    
  +    
       /**
        * Get return status based on exception type.
        */
       protected int getErrorCode(SlideException ex) {
           return WebdavUtils.getErrorCode(ex);
       }
  -
  -
  -
  +    
  +    
  +    
       /**
        * Get return status based on exception type.
        */
       protected int getErrorCode(ServiceAccessException ex) {
           return WebdavUtils.getErrorCode(ex);
       }
  -
  -
  +    
  +    
       /**
        * Returns the value of a boolean init parameter of the servlet.
        * Default value: false.
  @@ -742,8 +753,8 @@
       protected boolean getBooleanInitParameter( String name ) {
           return "true".equalsIgnoreCase( getConfig().getInitParameter(name) );
       }
  -
  -
  +    
  +    
       /**
        * Returns the value of an integer init parameter of the servlet.
        * Default value: -1.
  @@ -756,14 +767,14 @@
           catch( NumberFormatException x ) {};
           return result;
       }
  -
  +    
       /**
        * Error handling routine
        */
       protected void sendError( int statusCode ) {
           try { resp.sendError( statusCode ); } catch( Throwable x ) {};
       }
  -
  +    
       /**
        * Error handling routine
        */
  @@ -775,7 +786,7 @@
                    : "");
           try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
       }
  -
  +    
       /**
        * Error handling routine
        */
  @@ -785,7 +796,7 @@
               Messages.format( message, args );
           try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
       }
  -
  +    
       /**
        * Error handling routine
        */
  @@ -799,7 +810,7 @@
               WebdavStatus.getStatusText(statusCode)+": "+explanation;
           try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
       }
  -
  +    
       /**
        * Prints the stack trace of the given exception if the specified status code
        * is greater-or-equal the value of the servlet init-parameter printStackTrace.
  @@ -813,8 +824,8 @@
           if( statusCode >= printStackTraceFrom )
               x.printStackTrace();
       }
  -
  -
  +    
  +    
       /**
        * Generate status text.
        *
  @@ -823,7 +834,7 @@
        * @param statusCode HTTP status code of the error
        */
       protected void generateStatusText(Element parentElement, String href, int 
statusCode) {
  -
  +        
           Element hrefElement = new Element(E_HREF, DNSP);
           parentElement.addContent(hrefElement);
           hrefElement.setText(getFullPath(href));
  @@ -832,7 +843,7 @@
           statusElement.setText("HTTP/1.1 " + statusCode + " "
                                     + WebdavStatus.getStatusText(statusCode));
       }
  -
  +    
       /**
        * Generate an XML error message.
        *
  @@ -841,13 +852,13 @@
        */
       protected String generateErrorMessage
           (NestedSlideException nestedException) {
  -
  +        
           Element multistatus = new Element(E_MULTISTATUS, DNSP);
  -
  +        
           Enumeration nestedExceptionsList =
               nestedException.enumerateExceptions();
           while (nestedExceptionsList.hasMoreElements()) {
  -
  +            
               Element response = new Element(E_RESPONSE, DNSP);
               multistatus.addContent(response);
               SlideException ex =
  @@ -857,9 +868,9 @@
               if (ex instanceof PreconditionViolationException) {
                   
response.addContent(MethodUtil.getPreconditionViolationResponseDescription((PreconditionViolationException)ex));
               }
  -
  +            
           }
  -
  +        
           StringWriter stringWriter = new StringWriter();
           try {
               new XMLOutputter().output(multistatus, stringWriter);
  @@ -868,13 +879,13 @@
               Domain.log(e);
           }
           return stringWriter.toString();
  -
  +        
       }
  -
  +    
       protected boolean exists( String uriStr ) throws SlideException {
           // use a non-blocking slide token.
           SlideToken stoken = readonlySlideToken();
  -
  +        
           boolean destinationExists = true;
           
           try {
  @@ -885,11 +896,11 @@
           }
           return destinationExists;
       }
  -
  +    
       protected boolean isLocked( String uriStr ) throws ServiceAccessException {
           // use a non-blocking slide token.
           SlideToken stoken = readonlySlideToken();
  -
  +        
           boolean isLocked = false;
           try {
               Enumeration locks = lock.enumerateLocks (stoken, uriStr, false);
  @@ -907,11 +918,11 @@
           }
           return isLocked;
       }
  -
  +    
       protected boolean isLockNull( String uriStr ) throws ServiceAccessException {
           // use a non-blocking slide token.
           SlideToken stoken = readonlySlideToken();
  -
  +        
           boolean isLockNull = false;
           try {
               NodeRevisionDescriptor nrd =
  @@ -926,11 +937,11 @@
           }
           return isLockNull;
       }
  -
  +    
       protected boolean isLockNull( NodeRevisionDescriptor nrd ) {
           return nrd.propertyValueContains(P_RESOURCETYPE, E_LOCKNULL);
       }
  -
  +    
       protected SlideToken readonlySlideToken() {
           SlideToken stoken = slideToken;
           if (stoken.isForceStoreEnlistment()) {
  @@ -938,7 +949,239 @@
           }
           return stoken;
       }
  -
  +    
  +    /**
  +     * Check if the conditions specified in the optional If headers are
  +     * satisfied.
  +     *
  +     * @param request The servlet request we are processing
  +     * @param response The servlet response we are creating
  +     * @param resourceInfo File object
  +     * @return boolean true if the resource meets all the specified conditions,
  +     * and false if any of the conditions is not satisfied, in which case
  +     * request processing is stopped
  +     */
  +    protected boolean checkIfHeaders(HttpServletRequest request,
  +                                     HttpServletResponse response,
  +                                     ResourceInfo resourceInfo)
  +        throws IOException {
  +        
  +        String eTag = getETag(resourceInfo, true);
  +        long fileLength = resourceInfo.length;
  +        long lastModified = resourceInfo.date;
  +        
  +        StringTokenizer commaTokenizer;
  +        
  +        String headerValue;
  +        
  +        // Checking If-Match
  +        headerValue = request.getHeader("If-Match");
  +        if (headerValue != null) {
  +            if (headerValue.indexOf("*") == -1) {
  +                
  +                commaTokenizer = new StringTokenizer(headerValue, ",");
  +                boolean conditionSatisfied = false;
  +                
  +                while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
  +                    String currentToken = commaTokenizer.nextToken();
  +                    if (currentToken.trim().equals(eTag))
  +                        conditionSatisfied = true;
  +                }
  +                
  +                // If none of the given ETags match, 412 Precodition failed is
  +                // sent back
  +                if (!conditionSatisfied) {
  +                    response.sendError
  +                        (HttpServletResponse.SC_PRECONDITION_FAILED);
  +                    return false;
  +                }
  +                
  +            }
  +        }
  +        
  +        // Checking If-Modified-Since
  +        headerValue = request.getHeader("If-Modified-Since");
  +        if (headerValue != null) {
  +            
  +            // If an If-None-Match header has been specified, if modified since
  +            // is ignored.
  +            if (request.getHeader("If-None-Match") == null) {
  +                
  +                Date date = null;
  +                
  +                // Parsing the HTTP Date
  +                for (int i = 0; (date == null) && (i < formats.length); i++) {
  +                    try {
  +                        synchronized (formats[i]) {
  +                            date = formats[i].parse(headerValue);
  +                        }
  +                    } catch (ParseException e) {
  +                        ;
  +                    }
  +                }
  +                
  +                if ((date != null)
  +                    && (lastModified <= (date.getTime() + 1000)) ) {
  +                    // The entity has not been modified since the date
  +                    // specified by the client. This is not an error case.
  +                    response.sendError
  +                        (HttpServletResponse.SC_NOT_MODIFIED);
  +                    return false;
  +                }
  +                
  +            }
  +            
  +        }
  +        
  +        // Checking If-None-Match
  +        headerValue = request.getHeader("If-None-Match");
  +        if (headerValue != null) {
  +            if (headerValue.indexOf("*") == -1) {
  +                
  +                commaTokenizer = new StringTokenizer(headerValue, ",");
  +                boolean conditionSatisfied = true;
  +                
  +                while (conditionSatisfied && commaTokenizer.hasMoreTokens()) {
  +                    String currentToken = commaTokenizer.nextToken();
  +                    if (currentToken.trim().equals(eTag))
  +                        conditionSatisfied = false;
  +                }
  +                
  +                if (conditionSatisfied) {
  +                    
  +                    // For GET and HEAD, we should respond with
  +                    // 304 Not Modified.
  +                    // For every other method, 412 Precondition Failed is sent
  +                    // back.
  +                    if ( ("GET".equals(request.getMethod()))
  +                        || ("HEAD".equals(request.getMethod())) ) {
  +                        response.sendError
  +                            (HttpServletResponse.SC_NOT_MODIFIED);
  +                        return false;
  +                    } else {
  +                        response.sendError
  +                            (HttpServletResponse.SC_PRECONDITION_FAILED);
  +                        return false;
  +                    }
  +                }
  +                
  +            } else {
  +                if (resourceInfo.exists()) {
  +                    return false;
  +                }
  +            }
  +        }
  +        
  +        // Checking If-Unmodified-Since
  +        headerValue = request.getHeader("If-Unmodified-Since");
  +        if (headerValue != null) {
  +            
  +            Date date = null;
  +            
  +            // Parsing the HTTP Date
  +            for (int i = 0; (date == null) && (i < formats.length); i++) {
  +                try {
  +                    synchronized (formats[i]) {
  +                        date = formats[i].parse(headerValue);
  +                    }
  +                } catch (ParseException e) {
  +                    ;
  +                }
  +            }
  +            
  +            if ( (date != null) && (lastModified > date.getTime()) ) {
  +                // The entity has not been modified since the date
  +                // specified by the client. This is not an error case.
  +                response.sendError
  +                    (HttpServletResponse.SC_PRECONDITION_FAILED);
  +                return false;
  +            }
  +            
  +        }
  +        
  +        return true;
  +    }
  +    
  +    /**
  +     * Get the ETag value associated with a file.
  +     *
  +     * @param resourceInfo File object
  +     * @param strong True if we want a strong ETag, in which case a checksum
  +     * of the file has to be calculated
  +     */
  +    protected String getETagValue(ResourceInfo resourceInfo, boolean strong) {
  +        // FIXME : Compute a strong ETag if requested, using an MD5 digest
  +        // of the file contents
  +        if (resourceInfo.exists()) {
  +            return resourceInfo.etag;
  +        }
  +        else {
  +            return resourceInfo.length + "-" + resourceInfo.date;
  +        }
  +    }
  +    
  +    
  +    /**
  +     * Get the ETag associated with a file.
  +     *
  +     * @param resourceInfo File object
  +     * @param strong True if we want a strong ETag, in which case a checksum
  +     * of the file has to be calculated
  +     */
  +    protected String getETag(ResourceInfo resourceInfo, boolean strong) {
  +        if (strong)
  +            return "\"" + getETagValue(resourceInfo, strong) + "\"";
  +        else
  +            return "W/\"" + getETagValue(resourceInfo, strong) + "\"";
  +    }
  +    
  +    protected class ResourceInfo {
  +        
  +        /**
  +         * Constructor.
  +         *
  +         * @param pathname Path name of the file
  +         */
  +        public ResourceInfo(String path, NodeRevisionDescriptor properties) {
  +            
  +            this.path = path;
  +            this.exists = true;
  +            this.creationDate = properties.getCreationDateAsDate().getTime();
  +            this.date = properties.getLastModifiedAsDate().getTime();
  +            this.httpDate = properties.getLastModified();
  +            this.length = properties.getContentLength();
  +            this.etag = properties.getETag();
  +            
  +        }
  +        
  +        
  +        public String path;
  +        public long creationDate;
  +        public String httpDate;
  +        public long date;
  +        public long length;
  +        public String etag;
  +        //public boolean collection;
  +        public boolean exists;
  +        
  +        
  +        /**
  +         * Test if the associated resource exists.
  +         */
  +        public boolean exists() {
  +            return exists;
  +        }
  +        
  +        
  +        /**
  +         * String representation.
  +         */
  +        public String toString() {
  +            return path;
  +        }
  +        
  +        
  +    }
       
       protected class RequestHeaders {
           private static final int
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to