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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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,19 +129,129 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
*
|
||||
|
@@ -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.
|
||||
@@ -283,4 +286,67 @@ public abstract class BaseAuthenticationFilter
|
||||
*/
|
||||
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