mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-21 18:09:20 +00:00
Merged V3.2 to HEAD
19617: ALF-1890: Improvements to make ALL WebDAV methods retryable - Solution from PutMethod promoted to request wrapper that will handle ALL calls to getInputStream and getReader 19623: ALF-1890: Correction to previous checkin to allow defaulting of request body charset 19624: ALF-2231: Merged DEV/BELARUS/V2.2-2009_12_01 to V3.2 17704: ENH-681: alfresco webdav does not respect webdav locks 19647: ALF-2231: Merged DEV/BELARUS/V2.2-2009_12_01 to V3.2 17704: ENH-681: alfresco webdav does not respect webdav locks 19655: ALF-1997: Share with NTLM SSO enabled now supports form-based login as a fallback - If you use the new sample webscript framework NTLM config and go to http://localhost:8080/share/page?f=default&pt=login you can log in as any user in the repository, even an LDAP user! - When you log out again, it will fall back to your NTLM credentials - WebScriptNTLMAuthenticationFilter modified to create the session user for the /api/login call - AlfrescoAuthenticator modified to cope with cookie propagation as well as ticket propagation - LoginServlet bugfixed to kill the old session on login rather than the new one! git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19690 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -19,12 +19,7 @@
|
|||||||
package org.alfresco.repo.webdav;
|
package org.alfresco.repo.webdav;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
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.InputStream;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -34,14 +29,13 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
|
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.FileExistsException;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.TempFileProvider;
|
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the WebDAV PUT method
|
* Implements the WebDAV PUT method
|
||||||
@@ -55,8 +49,6 @@ public class PutMethod extends WebDAVMethod
|
|||||||
private String m_strContentType = null;
|
private String m_strContentType = null;
|
||||||
private boolean m_expectHeaderPresent = false;
|
private boolean m_expectHeaderPresent = false;
|
||||||
|
|
||||||
private File requestBody = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
*/
|
*/
|
||||||
@@ -91,16 +83,8 @@ public class PutMethod extends WebDAVMethod
|
|||||||
*/
|
*/
|
||||||
protected void parseRequestBody() throws WebDAVServerException
|
protected void parseRequestBody() throws WebDAVServerException
|
||||||
{
|
{
|
||||||
requestBody = TempFileProvider.createTempFile("webdav_PUT_", ".bin");
|
// Nothing to do in this method, the body contains
|
||||||
try
|
// the content it will be dealt with later
|
||||||
{
|
|
||||||
OutputStream out = new FileOutputStream(requestBody);
|
|
||||||
FileCopyUtils.copy(m_request.getInputStream(), out);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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
|
// Access the content
|
||||||
ContentWriter writer = fileFolderService.getWriter(contentNodeInfo.getNodeRef());
|
ContentWriter writer = fileFolderService.getWriter(contentNodeInfo.getNodeRef());
|
||||||
// set content properties
|
// set content properties
|
||||||
@@ -166,13 +160,13 @@ public class PutMethod extends WebDAVMethod
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String guessedMimetype = getMimetypeService().guessMimetype(getPath());
|
String guessedMimetype = getMimetypeService().guessMimetype(contentNodeInfo.getName());
|
||||||
mimetype = guessedMimetype;
|
mimetype = guessedMimetype;
|
||||||
}
|
}
|
||||||
writer.setMimetype(mimetype);
|
writer.setMimetype(mimetype);
|
||||||
|
|
||||||
// Get the input stream from the request data
|
// 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);
|
is = is.markSupported() ? is : new BufferedInputStream(is);
|
||||||
|
|
||||||
ContentCharsetFinder charsetFinder = getMimetypeService().getContentCharsetFinder();
|
ContentCharsetFinder charsetFinder = getMimetypeService().getContentCharsetFinder();
|
||||||
@@ -185,17 +179,4 @@ public class PutMethod extends WebDAVMethod
|
|||||||
// Set the response status, depending if the node existed or not
|
// Set the response status, depending if the node existed or not
|
||||||
m_response.setStatus(created ? HttpServletResponse.SC_CREATED : HttpServletResponse.SC_NO_CONTENT);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -18,14 +18,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.webdav;
|
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.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
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.NamespaceService;
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.TempFileProvider;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.dom4j.DocumentHelper;
|
import org.dom4j.DocumentHelper;
|
||||||
import org.dom4j.io.OutputFormat;
|
import org.dom4j.io.OutputFormat;
|
||||||
import org.dom4j.io.XMLWriter;
|
import org.dom4j.io.XMLWriter;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
@@ -80,6 +90,9 @@ public abstract class WebDAVMethod
|
|||||||
|
|
||||||
protected HttpServletRequest m_request;
|
protected HttpServletRequest m_request;
|
||||||
protected HttpServletResponse m_response;
|
protected HttpServletResponse m_response;
|
||||||
|
private File m_requestBody;
|
||||||
|
private ServletInputStream m_inputStream;
|
||||||
|
private BufferedReader m_reader;
|
||||||
|
|
||||||
// WebDAV helper
|
// WebDAV helper
|
||||||
|
|
||||||
@@ -116,19 +129,129 @@ public abstract class WebDAVMethod
|
|||||||
/**
|
/**
|
||||||
* Set the request/response details
|
* Set the request/response details
|
||||||
*
|
*
|
||||||
* @param req HttpServletRequest
|
* @param req
|
||||||
* @param resp HttpServletResponse
|
* HttpServletRequest
|
||||||
* @param registry ServiceRegistry
|
* @param resp
|
||||||
* @param rootNode NodeRef
|
* 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;
|
// Wrap the request so that it is 'retryable'. Calls to getInputStream() and getReader() will result in the
|
||||||
m_response = resp;
|
// request body being read into an intermediate file.
|
||||||
m_davHelper = davHelper;
|
this.m_request = new HttpServletRequestWrapper(req)
|
||||||
m_rootNodeRef = rootNode;
|
{
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -168,6 +291,10 @@ public abstract class WebDAVMethod
|
|||||||
{
|
{
|
||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
|
// Reset the request input stream / reader state
|
||||||
|
WebDAVMethod.this.m_inputStream = null;
|
||||||
|
WebDAVMethod.this.m_reader = null;
|
||||||
|
|
||||||
executeImpl();
|
executeImpl();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -201,7 +328,19 @@ public abstract class WebDAVMethod
|
|||||||
}
|
}
|
||||||
finally
|
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();
|
return ns.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void cleanup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Checks if write operation can be performed on node.
|
* Checks if write operation can be performed on node.
|
||||||
*
|
*
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
package org.alfresco.repo.webdav.auth;
|
package org.alfresco.repo.webdav.auth;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletException;
|
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.cmr.security.PersonService;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.apache.commons.logging.Log;
|
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.
|
* A base class for authentication filters. Handles management of the session user.
|
||||||
@@ -283,4 +286,67 @@ public abstract class BaseAuthenticationFilter
|
|||||||
*/
|
*/
|
||||||
protected abstract Log getLogger();
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user