mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged V2.1 to HEAD
6515: Fix for AWC-1362 (system error page when clicking on space that doesn't exist in navigator) 6516: Fix for AR-1688 - Vista 6518: Fix for AWC-1479, AWC-1199 and AWC-426 (javascript insertion into forum posts security related fixes) limit to subset of safe tags for posting 6519: Fix AR-1690 Web Scripts url.args is missing even though it's documented in WIKI 6520: Fix for AWC-1271 (component generator config ignored for associations) 6521: Fix AWC-1492 Some included javascript files in template/webscripts use the wrong app context path i.e. /alfresco when the app is called /alfzip 6522: Build fix 6523: - Fix rendering of tasks with no description in office portlets 6524: Added thread pool for index merging (AR-1633, AR-1579) 6525: One more fix for rendering of tasks with no description in office portlets 6527: Renamed axis jar to reflect version number. 6528: WebServices query cache refactoring git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6741 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -476,6 +476,113 @@ public class BrowseBean implements IContextListener
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page accessed bean method to get the parent container nodes currently being browsed
|
||||
*
|
||||
* @return List of parent container Node objects for the current browse location
|
||||
*/
|
||||
public List<Node> getParentNodes(NodeRef currNodeRef)
|
||||
{
|
||||
// As per AWC-1507 there are two scenarios for navigating to the space details. First
|
||||
// scenario is to show space details of the current space. Second scenario is to show
|
||||
// space details of a child space of the current space. For now, added an extra query
|
||||
// so that existing context remains unaffected for second scenario, although it does
|
||||
// mean that in first scenario there will be an extra query even though parentContainerNodes
|
||||
// and containerNodes will contain the same list.
|
||||
|
||||
if (this.parentContainerNodes == null)
|
||||
{
|
||||
long startTime = 0;
|
||||
if (logger.isDebugEnabled())
|
||||
startTime = System.currentTimeMillis();
|
||||
|
||||
UserTransaction tx = null;
|
||||
try
|
||||
{
|
||||
FacesContext context = FacesContext.getCurrentInstance();
|
||||
tx = Repository.getUserTransaction(context, true);
|
||||
tx.begin();
|
||||
|
||||
NodeRef parentRef = nodeService.getPrimaryParent(currNodeRef).getParentRef();
|
||||
|
||||
List<FileInfo> children = this.fileFolderService.list(parentRef);
|
||||
this.parentContainerNodes = new ArrayList<Node>(children.size());
|
||||
for (FileInfo fileInfo : children)
|
||||
{
|
||||
// create our Node representation from the NodeRef
|
||||
NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
|
||||
// find it's type so we can see if it's a node we are interested in
|
||||
QName type = this.nodeService.getType(nodeRef);
|
||||
|
||||
// make sure the type is defined in the data dictionary
|
||||
TypeDefinition typeDef = this.dictionaryService.getType(type);
|
||||
|
||||
if (typeDef != null)
|
||||
{
|
||||
MapNode node = null;
|
||||
|
||||
// look for Space folder node
|
||||
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) == true &&
|
||||
this.dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
|
||||
{
|
||||
// create our Node representation
|
||||
node = new MapNode(nodeRef, this.nodeService, fileInfo.getProperties());
|
||||
node.addPropertyResolver("icon", this.resolverSpaceIcon);
|
||||
node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
|
||||
|
||||
this.parentContainerNodes.add(node);
|
||||
}
|
||||
else if (ApplicationModel.TYPE_FOLDERLINK.equals(type))
|
||||
{
|
||||
// create our Folder Link Node representation
|
||||
node = new MapNode(nodeRef, this.nodeService, fileInfo.getProperties());
|
||||
node.addPropertyResolver("icon", this.resolverSpaceIcon);
|
||||
node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
|
||||
|
||||
this.parentContainerNodes.add(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isEnabledFor(Priority.WARN))
|
||||
logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
|
||||
}
|
||||
}
|
||||
|
||||
// commit the transaction
|
||||
tx.commit();
|
||||
}
|
||||
catch (InvalidNodeRefException refErr)
|
||||
{
|
||||
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {refErr.getNodeRef()}), refErr );
|
||||
this.parentContainerNodes = Collections.<Node>emptyList();
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
|
||||
this.parentContainerNodes = Collections.<Node>emptyList();
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
long endTime = System.currentTimeMillis();
|
||||
logger.debug("Time to query and build map parent nodes: " + (endTime - startTime) + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
List<Node> result = this.parentContainerNodes;
|
||||
|
||||
// we clear the member variable during invalidateComponents()
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup the common properties required at data-binding time.
|
||||
@@ -1733,6 +1840,7 @@ public class BrowseBean implements IContextListener
|
||||
// clear the storage of the last set of nodes
|
||||
this.containerNodes = null;
|
||||
this.contentNodes = null;
|
||||
this.parentContainerNodes = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1880,6 +1988,7 @@ public class BrowseBean implements IContextListener
|
||||
/** Transient lists of container and content nodes for display */
|
||||
protected List<Node> containerNodes = null;
|
||||
protected List<Node> contentNodes = null;
|
||||
protected List<Node> parentContainerNodes = null;
|
||||
|
||||
/** The current space and it's properties - if any */
|
||||
protected Node actionSpace;
|
||||
|
@@ -177,7 +177,8 @@ public class SpaceDetailsBean extends BaseDetailsBean
|
||||
String id = params.get("id");
|
||||
if (id != null && id.length() != 0)
|
||||
{
|
||||
List<Node> nodes = this.browseBean.getNodes();
|
||||
NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id);
|
||||
List<Node> nodes = this.browseBean.getParentNodes(currNodeRef);
|
||||
if (nodes.size() > 1)
|
||||
{
|
||||
// perform a linear search - this is slow but stateless
|
||||
@@ -214,7 +215,6 @@ public class SpaceDetailsBean extends BaseDetailsBean
|
||||
// to the default one.
|
||||
if (foundNextItem == false)
|
||||
{
|
||||
NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id);
|
||||
Node currNode = new Node(currNodeRef);
|
||||
this.navigator.setupDispatchContext(currNode);
|
||||
}
|
||||
@@ -232,7 +232,8 @@ public class SpaceDetailsBean extends BaseDetailsBean
|
||||
String id = params.get("id");
|
||||
if (id != null && id.length() != 0)
|
||||
{
|
||||
List<Node> nodes = this.browseBean.getNodes();
|
||||
NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id);
|
||||
List<Node> nodes = this.browseBean.getParentNodes(currNodeRef);
|
||||
if (nodes.size() > 1)
|
||||
{
|
||||
// see above
|
||||
@@ -266,7 +267,6 @@ public class SpaceDetailsBean extends BaseDetailsBean
|
||||
// to the default one.
|
||||
if (foundPreviousItem == false)
|
||||
{
|
||||
NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id);
|
||||
Node currNode = new Node(currNodeRef);
|
||||
this.navigator.setupDispatchContext(currNode);
|
||||
}
|
||||
|
@@ -831,7 +831,7 @@ public class ForumsBean implements IContextListener
|
||||
|
||||
if (reader != null)
|
||||
{
|
||||
content = reader.getContentString();
|
||||
content = Utils.stripUnsafeHTMLTags(reader.getContentString());
|
||||
}
|
||||
|
||||
return content;
|
||||
|
@@ -171,6 +171,9 @@ public class DeclarativeWebScript extends AbstractWebScript
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Caught exception & redirecting to status template: " + e.getMessage());
|
||||
|
||||
// extract status code, if specified
|
||||
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
if (e instanceof WebScriptException)
|
||||
|
@@ -524,6 +524,7 @@ public class TestWebScriptServer
|
||||
String[] parts = arg.split("=");
|
||||
req.addParameter(parts[0], (parts.length == 2) ? URLDecoder.decode(parts[1], "UTF-8") : null);
|
||||
}
|
||||
req.setQueryString(URLDecoder.decode(uriArgs, "UTF-8"));
|
||||
}
|
||||
String requestURI = "/alfresco/service" + (iArgIndex == -1 ? uri : uri.substring(0, iArgIndex));
|
||||
req.setRequestURI(URLDecoder.decode(requestURI, "UTF-8"));
|
||||
|
@@ -113,6 +113,22 @@ public class URLModel
|
||||
return getFull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments (query string)
|
||||
*
|
||||
* @return args (query string)
|
||||
*/
|
||||
public String getArgs()
|
||||
{
|
||||
String args = req.getQueryString();
|
||||
return (args == null) ? "" : args;
|
||||
}
|
||||
|
||||
public String jsGet_args()
|
||||
{
|
||||
return getArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the matching service path
|
||||
*
|
||||
|
@@ -190,6 +190,9 @@ public abstract class WebScriptRuntime
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Caught exception & redirecting to status template: " + e.getMessage());
|
||||
|
||||
// extract status code, if specified
|
||||
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
if (e instanceof WebScriptException)
|
||||
|
@@ -34,9 +34,11 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.faces.component.NamingContainer;
|
||||
@@ -102,7 +104,45 @@ public final class Utils
|
||||
|
||||
private static final Map<String, String> s_fileExtensionMap = new HashMap<String, String>(89, 1.0f);
|
||||
|
||||
private static Log logger = LogFactory.getLog(Utils.class);
|
||||
private static final Log logger = LogFactory.getLog(Utils.class);
|
||||
|
||||
private static final Set<String> safeTags = new HashSet<String>();
|
||||
|
||||
static
|
||||
{
|
||||
safeTags.add("p");
|
||||
safeTags.add("/p");
|
||||
safeTags.add("b");
|
||||
safeTags.add("/b");
|
||||
safeTags.add("i");
|
||||
safeTags.add("/i");
|
||||
safeTags.add("br");
|
||||
safeTags.add("ul");
|
||||
safeTags.add("/ul");
|
||||
safeTags.add("ol");
|
||||
safeTags.add("/ol");
|
||||
safeTags.add("li");
|
||||
safeTags.add("/li");
|
||||
safeTags.add("h1");
|
||||
safeTags.add("/h1");
|
||||
safeTags.add("h2");
|
||||
safeTags.add("/h2");
|
||||
safeTags.add("h3");
|
||||
safeTags.add("/h3");
|
||||
safeTags.add("h4");
|
||||
safeTags.add("/h4");
|
||||
safeTags.add("h5");
|
||||
safeTags.add("/h5");
|
||||
safeTags.add("h6");
|
||||
safeTags.add("/h6");
|
||||
safeTags.add("span");
|
||||
safeTags.add("/span");
|
||||
safeTags.add("a");
|
||||
safeTags.add("/a");
|
||||
safeTags.add("img");
|
||||
safeTags.add("font");
|
||||
safeTags.add("/font");
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
@@ -256,6 +296,92 @@ public final class Utils
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip unsafe HTML tags from a string - only leaves most basic formatting tags
|
||||
* and encodes or strips the remaining characters.
|
||||
*
|
||||
* @param s HTML string to strip tags from
|
||||
*
|
||||
* @return safe string
|
||||
*/
|
||||
public static String stripUnsafeHTMLTags(String s)
|
||||
{
|
||||
s = s.replace("onclick", "$");
|
||||
s = s.replace("onmouseover", "$");
|
||||
s = s.replace("onmouseout", "$");
|
||||
s = s.replace("onmousemove", "$");
|
||||
s = s.replace("onfocus", "$");
|
||||
s = s.replace("onblur", "$");
|
||||
StringBuilder buf = new StringBuilder(s.length());
|
||||
char[] chars = s.toCharArray();
|
||||
for (int i=0; i<chars.length; i++)
|
||||
{
|
||||
if (chars[i] == '<')
|
||||
{
|
||||
// found a tag?
|
||||
int endMatchIndex = -1;
|
||||
int endTagIndex = -1;
|
||||
if (i < chars.length - 2)
|
||||
{
|
||||
for (int x=(i + 1); x<chars.length; x++)
|
||||
{
|
||||
if (chars[x] == ' ' && endMatchIndex == -1)
|
||||
{
|
||||
// keep track of the match point for comparing tags in the safeTags set
|
||||
endMatchIndex = x;
|
||||
}
|
||||
else if (chars[x] == '>')
|
||||
{
|
||||
endTagIndex = x;
|
||||
break;
|
||||
}
|
||||
else if (chars[x] == '<')
|
||||
{
|
||||
// found another angle bracket - not a tag def so we can safely output to here
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (endTagIndex != -1)
|
||||
{
|
||||
// found end of the tag to match
|
||||
String tag = s.substring(i + 1, endTagIndex).toLowerCase();
|
||||
String matchTag = tag;
|
||||
if (endMatchIndex != -1)
|
||||
{
|
||||
matchTag = s.substring(i + 1, endMatchIndex).toLowerCase();
|
||||
}
|
||||
if (safeTags.contains(matchTag))
|
||||
{
|
||||
// safe tag - append to buffer
|
||||
buf.append('<').append(tag).append('>');
|
||||
}
|
||||
// inc counter to skip past whole tag
|
||||
i = endTagIndex;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
String enc = null;
|
||||
switch (chars[i])
|
||||
{
|
||||
case '"': enc = """; break;
|
||||
case '&': enc = "&"; break;
|
||||
case '<': enc = "<"; break;
|
||||
case '>': enc = ">"; break;
|
||||
|
||||
default:
|
||||
if (((int)chars[i]) >= 0x80)
|
||||
{
|
||||
//encode all non basic latin characters
|
||||
enc = "&#" + ((int)chars[i]) + ";";
|
||||
}
|
||||
break;
|
||||
}
|
||||
buf.append(enc == null ? chars[i] : enc);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace one string instance with another within the specified string
|
||||
*
|
||||
@@ -337,8 +463,12 @@ public final class Utils
|
||||
String line = reader.readLine();
|
||||
while (line != null)
|
||||
{
|
||||
parsedContent.append(line).append("<br/>");
|
||||
parsedContent.append(line);
|
||||
line = reader.readLine();
|
||||
if (line != null)
|
||||
{
|
||||
parsedContent.append("<br>");
|
||||
}
|
||||
}
|
||||
|
||||
replaced = parsedContent.toString();
|
||||
|
@@ -30,6 +30,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
@@ -37,9 +38,11 @@ import javax.faces.el.ValueBinding;
|
||||
import javax.faces.event.AbortProcessingException;
|
||||
import javax.faces.event.ActionEvent;
|
||||
import javax.faces.event.FacesEvent;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.web.app.Application;
|
||||
import org.alfresco.web.app.servlet.FacesHelper;
|
||||
import org.alfresco.web.bean.BrowseBean;
|
||||
@@ -183,17 +186,44 @@ public class UINavigator extends SelfRenderingComponent
|
||||
case NODE_SELECTED:
|
||||
{
|
||||
// a node was clicked in the tree
|
||||
boolean nodeExists = true;
|
||||
NodeRef nodeClicked = new NodeRef(navEvent.getItem());
|
||||
|
||||
// setup the context to make the node the current node
|
||||
BrowseBean bb = (BrowseBean)FacesHelper.getManagedBean(
|
||||
context, BrowseBean.BEAN_NAME);
|
||||
if (bb != null)
|
||||
// make sure the node exists still before navigating to it
|
||||
UserTransaction tx = null;
|
||||
try
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Selected node: " + nodeClicked);
|
||||
tx = Repository.getUserTransaction(context, true);
|
||||
tx.begin();
|
||||
|
||||
bb.clickSpace(nodeClicked);
|
||||
NodeService nodeSvc = Repository.getServiceRegistry(
|
||||
context).getNodeService();
|
||||
nodeExists = nodeSvc.exists(nodeClicked);
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
}
|
||||
|
||||
if (nodeExists)
|
||||
{
|
||||
// setup the context to make the node the current node
|
||||
BrowseBean bb = (BrowseBean)FacesHelper.getManagedBean(
|
||||
context, BrowseBean.BEAN_NAME);
|
||||
if (bb != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Selected node: " + nodeClicked);
|
||||
|
||||
bb.clickSpace(nodeClicked);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String msg = Application.getMessage(context, "navigator_node_deleted");
|
||||
Utils.addErrorMessage(msg);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@@ -121,8 +121,17 @@ public class UIAssociation extends PropertySheetItem
|
||||
private void generateControl(FacesContext context, UIPropertySheet propSheet,
|
||||
AssociationDefinition assocDef)
|
||||
{
|
||||
// get the custom component generator (if one)
|
||||
String componentGeneratorName = this.getComponentGenerator();
|
||||
|
||||
// use the default component generator if there wasn't an overridden one
|
||||
if (componentGeneratorName == null)
|
||||
{
|
||||
componentGeneratorName = RepoConstants.GENERATOR_ASSOCIATION;
|
||||
}
|
||||
|
||||
UIAssociationEditor control = (UIAssociationEditor)FacesHelper.getComponentGenerator(
|
||||
context, RepoConstants.GENERATOR_ASSOCIATION).generateAndAdd(context, propSheet, this);
|
||||
context, componentGeneratorName).generateAndAdd(context, propSheet, this);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Created control " + control + "(" +
|
||||
|
@@ -121,8 +121,17 @@ public class UIChildAssociation extends PropertySheetItem
|
||||
private void generateControl(FacesContext context, UIPropertySheet propSheet,
|
||||
AssociationDefinition assocDef)
|
||||
{
|
||||
// get the custom component generator (if one)
|
||||
String componentGeneratorName = this.getComponentGenerator();
|
||||
|
||||
// use the default component generator if there wasn't an overridden one
|
||||
if (componentGeneratorName == null)
|
||||
{
|
||||
componentGeneratorName = RepoConstants.GENERATOR_CHILD_ASSOCIATION;
|
||||
}
|
||||
|
||||
UIChildAssociationEditor control = (UIChildAssociationEditor)FacesHelper.getComponentGenerator(
|
||||
context, RepoConstants.GENERATOR_CHILD_ASSOCIATION).generateAndAdd(context, propSheet, this);
|
||||
context, componentGeneratorName).generateAndAdd(context, propSheet, this);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Created control " + control + "(" +
|
||||
|
Reference in New Issue
Block a user