diff --git a/source/java/org/alfresco/repo/webdav/PutMethod.java b/source/java/org/alfresco/repo/webdav/PutMethod.java
index 5087c189c8..0768c40f5f 100644
--- a/source/java/org/alfresco/repo/webdav/PutMethod.java
+++ b/source/java/org/alfresco/repo/webdav/PutMethod.java
@@ -19,12 +19,7 @@
package org.alfresco.repo.webdav;
import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.HashMap;
@@ -34,14 +29,13 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
+import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.namespace.QName;
-import org.alfresco.util.TempFileProvider;
-import org.springframework.util.FileCopyUtils;
/**
* Implements the WebDAV PUT method
@@ -55,8 +49,6 @@ public class PutMethod extends WebDAVMethod
private String m_strContentType = null;
private boolean m_expectHeaderPresent = false;
- private File requestBody = null;
-
/**
* Default constructor
*/
@@ -91,16 +83,8 @@ public class PutMethod extends WebDAVMethod
*/
protected void parseRequestBody() throws WebDAVServerException
{
- requestBody = TempFileProvider.createTempFile("webdav_PUT_", ".bin");
- try
- {
- OutputStream out = new FileOutputStream(requestBody);
- FileCopyUtils.copy(m_request.getInputStream(), out);
- }
- catch (IOException e)
- {
- throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
- }
+ // Nothing to do in this method, the body contains
+ // the content it will be dealt with later
}
/**
@@ -156,6 +140,16 @@ public class PutMethod extends WebDAVMethod
}
}
+ LockStatus lockSts = getLockService().getLockStatus(contentNodeInfo.getNodeRef());
+ String userName = getDAVHelper().getAuthenticationService().getCurrentUserName();
+ String owner = (String) getNodeService().getProperty(contentNodeInfo.getNodeRef(), ContentModel.PROP_LOCK_OWNER);
+
+ if (lockSts == LockStatus.LOCKED || (lockSts == LockStatus.LOCK_OWNER && !userName.equals(owner)))
+ {
+ // Indicate that the resource is locked
+ throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
+ }
+
// Access the content
ContentWriter writer = fileFolderService.getWriter(contentNodeInfo.getNodeRef());
// set content properties
@@ -166,13 +160,13 @@ public class PutMethod extends WebDAVMethod
}
else
{
- String guessedMimetype = getMimetypeService().guessMimetype(getPath());
+ String guessedMimetype = getMimetypeService().guessMimetype(contentNodeInfo.getName());
mimetype = guessedMimetype;
}
writer.setMimetype(mimetype);
// Get the input stream from the request data
- InputStream is = new FileInputStream(requestBody);
+ InputStream is = m_request.getInputStream();
is = is.markSupported() ? is : new BufferedInputStream(is);
ContentCharsetFinder charsetFinder = getMimetypeService().getContentCharsetFinder();
@@ -185,17 +179,4 @@ public class PutMethod extends WebDAVMethod
// Set the response status, depending if the node existed or not
m_response.setStatus(created ? HttpServletResponse.SC_CREATED : HttpServletResponse.SC_NO_CONTENT);
}
-
- @Override
- protected void cleanup()
- {
- try
- {
- requestBody.delete();
- }
- catch (Throwable t)
- {
- logger.error("Failed to delete temp file", t);
- }
- }
}
diff --git a/source/java/org/alfresco/repo/webdav/WebDAVMethod.java b/source/java/org/alfresco/repo/webdav/WebDAVMethod.java
index bd33ebe81c..f59dbd44cd 100644
--- a/source/java/org/alfresco/repo/webdav/WebDAVMethod.java
+++ b/source/java/org/alfresco/repo/webdav/WebDAVMethod.java
@@ -18,14 +18,22 @@
*/
package org.alfresco.repo.webdav;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -50,11 +58,13 @@ import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
+import org.springframework.util.FileCopyUtils;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
@@ -80,6 +90,9 @@ public abstract class WebDAVMethod
protected HttpServletRequest m_request;
protected HttpServletResponse m_response;
+ private File m_requestBody;
+ private ServletInputStream m_inputStream;
+ private BufferedReader m_reader;
// WebDAV helper
@@ -116,21 +129,131 @@ public abstract class WebDAVMethod
/**
* Set the request/response details
*
- * @param req HttpServletRequest
- * @param resp HttpServletResponse
- * @param registry ServiceRegistry
- * @param rootNode NodeRef
+ * @param req
+ * HttpServletRequest
+ * @param resp
+ * HttpServletResponse
+ * @param registry
+ * ServiceRegistry
+ * @param rootNode
+ * NodeRef
*/
- public void setDetails(HttpServletRequest req, HttpServletResponse resp, WebDAVHelper davHelper, NodeRef rootNode)
+ public void setDetails(final HttpServletRequest req, HttpServletResponse resp, WebDAVHelper davHelper,
+ NodeRef rootNode)
{
- m_request = req;
- m_response = resp;
- m_davHelper = davHelper;
- m_rootNodeRef = rootNode;
+ // Wrap the request so that it is 'retryable'. Calls to getInputStream() and getReader() will result in the
+ // request body being read into an intermediate file.
+ this.m_request = new HttpServletRequestWrapper(req)
+ {
- m_strPath = WebDAV.getRepositoryPath(req);
+ @Override
+ public ServletInputStream getInputStream() throws IOException
+ {
+ if (WebDAVMethod.this.m_reader != null)
+ {
+ throw new IllegalStateException("Reader in use");
+ }
+ if (WebDAVMethod.this.m_inputStream == null)
+ {
+ final FileInputStream in = new FileInputStream(getRequestBodyAsFile(req));
+ WebDAVMethod.this.m_inputStream = new ServletInputStream()
+ {
+
+ @Override
+ public int read() throws IOException
+ {
+ return in.read();
+ }
+
+ @Override
+ public int read(byte b[]) throws IOException
+ {
+ return in.read(b);
+ }
+
+ @Override
+ public int read(byte b[], int off, int len) throws IOException
+ {
+ return in.read(b, off, len);
+ }
+
+ @Override
+ public long skip(long n) throws IOException
+ {
+ return in.skip(n);
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ return in.available();
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ in.close();
+ }
+
+ @Override
+ public void mark(int readlimit)
+ {
+ in.mark(readlimit);
+ }
+
+ @Override
+ public void reset() throws IOException
+ {
+ in.reset();
+ }
+
+ @Override
+ public boolean markSupported()
+ {
+ return in.markSupported();
+ }
+ };
+ }
+
+ return WebDAVMethod.this.m_inputStream;
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException
+ {
+ if (WebDAVMethod.this.m_inputStream != null)
+ {
+ throw new IllegalStateException("Input Stream in use");
+ }
+ if (WebDAVMethod.this.m_reader == null)
+ {
+ String encoding = req.getCharacterEncoding();
+ WebDAVMethod.this.m_reader = new BufferedReader(new InputStreamReader(new FileInputStream(
+ getRequestBodyAsFile(req)), encoding == null ? "ISO-8859-1" : encoding));
+ }
+
+ return WebDAVMethod.this.m_reader;
+ }
+
+ };
+ this.m_response = resp;
+ this.m_davHelper = davHelper;
+ this.m_rootNodeRef = rootNode;
+
+ this.m_strPath = WebDAV.getRepositoryPath(req);
}
-
+
+ private File getRequestBodyAsFile(HttpServletRequest req) throws IOException
+ {
+ if (this.m_requestBody == null)
+ {
+ this.m_requestBody = TempFileProvider.createTempFile("webdav_" + req.getMethod() + "_", ".bin");
+ OutputStream out = new FileOutputStream(this.m_requestBody);
+ FileCopyUtils.copy(req.getInputStream(), out);
+ }
+ return this.m_requestBody;
+ }
+
/**
* Override and return true if the method is a query method only. The default implementation
* returns false.
@@ -168,6 +291,10 @@ public abstract class WebDAVMethod
{
public Object execute() throws Exception
{
+ // Reset the request input stream / reader state
+ WebDAVMethod.this.m_inputStream = null;
+ WebDAVMethod.this.m_reader = null;
+
executeImpl();
return null;
}
@@ -201,7 +328,19 @@ public abstract class WebDAVMethod
}
finally
{
- cleanup();
+ // Remove temporary file if created
+ if (this.m_requestBody != null)
+ {
+ try
+ {
+ this.m_requestBody.delete();
+ this.m_requestBody = null;
+ }
+ catch (Throwable t)
+ {
+ WebDAVMethod.logger.error("Failed to delete temp file", t);
+ }
+ }
}
}
@@ -650,10 +789,6 @@ public abstract class WebDAVMethod
return ns.toString();
}
-
- protected void cleanup()
- {
- }
/**
* Checks if write operation can be performed on node.
*
diff --git a/source/java/org/alfresco/repo/webdav/auth/BaseAuthenticationFilter.java b/source/java/org/alfresco/repo/webdav/auth/BaseAuthenticationFilter.java
index a8c2ec5b97..1ca44cebd8 100644
--- a/source/java/org/alfresco/repo/webdav/auth/BaseAuthenticationFilter.java
+++ b/source/java/org/alfresco/repo/webdav/auth/BaseAuthenticationFilter.java
@@ -19,6 +19,7 @@
package org.alfresco.repo.webdav.auth;
import java.io.IOException;
+import java.io.Reader;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
@@ -37,6 +38,8 @@ import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
+import org.json.JSONException;
+import org.json.JSONObject;
/**
* A base class for authentication filters. Handles management of the session user.
@@ -282,5 +285,68 @@ public abstract class BaseAuthenticationFilter
* @return Log
*/
protected abstract Log getLogger();
+
+ /**
+ * Handles the login form directly, allowing management of the session user.
+ *
+ * @param req
+ * the request
+ * @param res
+ * the response
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ * @throws ServletException
+ * on error
+ */
+ protected void handleLoginForm(HttpServletRequest req, HttpServletResponse res) throws IOException,
+ ServletException
+ {
+ // Invalidate current session
+ HttpSession session = req.getSession(false);
+ if (session != null)
+ {
+ session.invalidate();
+ }
+ StringBuilder out = new StringBuilder(1024);
+ Reader in = req.getReader();
+ char[] buff = new char[1024];
+ int charsRead;
+ while ((charsRead = in.read(buff)) != -1)
+ {
+ out.append(buff, 0, charsRead);
+ }
+ in.close();
+ try
+ {
+ JSONObject json = new JSONObject(out.toString());
+ String username = json.getString("username");
+ String password = json.getString("password");
+
+ if (username == null || username.length() == 0)
+ {
+ res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Username not specified");
+ return;
+ }
+
+ if (password == null)
+ {
+ res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Password not specified");
+ return;
+ }
+
+ authenticationService.authenticate(username, password.toCharArray());
+ session = req.getSession();
+ createUserEnvironment(session, username, authenticationService.getCurrentTicket(session.getId()), false);
+ res.setStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
+ catch (AuthenticationException e)
+ {
+ res.sendError(HttpServletResponse.SC_FORBIDDEN, "Login failed");
+ }
+ catch (JSONException jErr)
+ {
+ res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unable to parse JSON POST body: " + jErr.getMessage());
+ }
+ }
}
\ No newline at end of file