diff --git a/source/java/org/alfresco/repo/jscript/ScriptNode.java b/source/java/org/alfresco/repo/jscript/ScriptNode.java index d82dbb3d80..81fcbf142b 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/source/java/org/alfresco/repo/jscript/ScriptNode.java @@ -1173,25 +1173,29 @@ public class ScriptNode implements Serializable, Scopeable, NamespacePrefixResol { try { - List paths = this.services.getFileFolderService().getNamePath(null, getNodeRef()); - - // build up the webdav url - StringBuilder path = new StringBuilder(128); - path.append("/webdav"); - - // build up the path skipping the first path as it is the root folder - for (int i=1; i paths = this.services.getFileFolderService().getNamePath(null, getNodeRef()); + + // build up the webdav url + StringBuilder path = new StringBuilder(128); + path.append("/webdav"); + + // build up the path skipping the first path as it is the root folder + for (int i=1; i(defaultEnvironment.size()); - env.putAll(defaultEnvironment); - if (env.get(Context.SECURITY_PRINCIPAL) != null) + String principal = defaultEnvironment.get(Context.SECURITY_PRINCIPAL); + if (principal != null) { // Correct principal invalid password - env = new Hashtable(defaultEnvironment.size()); - env.putAll(defaultEnvironment); + env = new Hashtable(authenticatedEnvironment.size()); + env.putAll(authenticatedEnvironment); + env.put(Context.SECURITY_PRINCIPAL, principal); env.put(Context.SECURITY_CREDENTIALS, "sdasdasdasdasd123123123"); try { diff --git a/source/java/org/alfresco/repo/template/BaseContentNode.java b/source/java/org/alfresco/repo/template/BaseContentNode.java index 78f4bffe72..aa341bcee5 100644 --- a/source/java/org/alfresco/repo/template/BaseContentNode.java +++ b/source/java/org/alfresco/repo/template/BaseContentNode.java @@ -404,25 +404,29 @@ public abstract class BaseContentNode implements TemplateContent { try { - List paths = this.services.getFileFolderService().getNamePath(null, getNodeRef()); - - // build up the webdav url - StringBuilder path = new StringBuilder(128); - path.append("/webdav"); - - // build up the path skipping the first path as it is the root folder - for (int i=1; i paths = this.services.getFileFolderService().getNamePath(null, getNodeRef()); + + // build up the webdav url + StringBuilder path = new StringBuilder(128); + path.append("/webdav"); + + // build up the path skipping the first path as it is the root folder + for (int i=1; i<\\?/:\\|]+.*"); - private static final Pattern FILENAME_ILLEGAL_PATTERN_REPLACE = Pattern.compile("[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|]"); + public static final String FILENAME_ILLEGAL_REGEX = "[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|]"; + private static final Pattern FILENAME_ILLEGAL_PATTERN_REPLACE = Pattern.compile(FILENAME_ILLEGAL_REGEX); public static boolean isValid(String name) { - return !FILENAME_ILLEGAL_PATTERN.matcher(name).matches(); + return !FILENAME_ILLEGAL_PATTERN_REPLACE.matcher(name).find(); } /** diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxServiceImplTest.java b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImplTest.java index e1923ddd05..ea3a673c42 100644 --- a/source/java/org/alfresco/wcm/sandbox/SandboxServiceImplTest.java +++ b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImplTest.java @@ -1496,6 +1496,7 @@ public class SandboxServiceImplTest extends AbstractWCMServiceImplTest // submit (new assets) ! sbService.submitWebApp(authorSandboxIdA, webAppA, "A1", "A1"); + // wait for submit to complete pollForSnapshotCount(stagingSandboxIdA, 1); assets = sbService.listChangedWebApp(authorSandboxIdA, webAppA, false); @@ -1531,6 +1532,9 @@ public class SandboxServiceImplTest extends AbstractWCMServiceImplTest assertEquals(1, assetService.listAssets(authorSandboxIdB, -1, authorSandboxPathB, false).size()); + assets = sbService.listChangedWebApp(authorSandboxIdB, webAppB, false); + assertEquals(0, assets.size()); + // modify file final String MYFILE_MODIFIED = "This is testfile.txt modified in BBB"; @@ -1542,18 +1546,12 @@ public class SandboxServiceImplTest extends AbstractWCMServiceImplTest assets = sbService.listChangedWebApp(authorSandboxIdB, webAppB, false); assertEquals(1, assets.size()); - // ETHREEOH_2836 + // ETHREEOH-2836 assertEquals(AVMDifference.NEWER, assets.get(0).getDiffCode()); // initiate submit (modified asset) sbService.submitWebApp(authorSandboxIdB, webAppB, "B1", "B1"); - assets = sbService.listChangedWebApp(authorSandboxIdB, webAppB, false); - assertEquals(1, assets.size()); - - // ETHREEOH_2836 - assertEquals(AVMDifference.NEWER, assets.get(0).getDiffCode()); - // wait for submit to complete pollForSnapshotCount(stagingSandboxIdB, 1); diff --git a/source/java/org/alfresco/wcm/util/WCMUtil.java b/source/java/org/alfresco/wcm/util/WCMUtil.java index 84e54591ab..d8f5240a2c 100644 --- a/source/java/org/alfresco/wcm/util/WCMUtil.java +++ b/source/java/org/alfresco/wcm/util/WCMUtil.java @@ -195,9 +195,8 @@ public class WCMUtil extends AVMUtil storeName = WCMUtil.getCorrespondingMainStoreName(storeName); } final int index = storeName.indexOf(WCMUtil.STORE_SEPARATOR); - return (index == -1 - ? null - : storeName.substring(index + WCMUtil.STORE_SEPARATOR.length())); + return (index == -1 ? null : unescapeStoreNameComponent(storeName.substring(index + + WCMUtil.STORE_SEPARATOR.length()))); } /** @@ -303,6 +302,104 @@ public class WCMUtil extends AVMUtil return (buildAVMPath(otherStoreName, WCMUtil.getStoreRelativePath(avmPath))); } + /** + * Utility function for escaping part of a compound store name (delimited by STORE_SEPARATOR sequences). Uses ISO + * 9075 style encoding to escape otherwise problematic character sequences. + * + * @param component + * the component + * @return the escaped string + */ + private static final String escapeStoreNameComponent(String component) + { + StringBuilder builder = null; + int length = component.length(); + // If the component matches one of the common suffixes, encode it + if (component.equals(STORE_PREVIEW) || component.equals(STORE_WORKFLOW)) + { + builder = new StringBuilder(length + 5); + appendEncoded(builder, component); + return builder.toString(); + } + + // Look for problematic character sequences + Matcher matcher = PATTERN_ILLEGAL_SEQUENCE.matcher(component); + int lastAppendPosition = 0; + while (matcher.find()) + { + if (builder == null) + { + builder = new StringBuilder(length + 5); + } + if (matcher.start() != lastAppendPosition) + { + builder.append(component, lastAppendPosition, matcher.start()); + } + lastAppendPosition = matcher.end(); + appendEncoded(builder, matcher.group()); + } + if (builder == null) + { + return component; + } + if (lastAppendPosition < length) + { + builder.append(component, lastAppendPosition, length); + } + + return builder.toString(); + } + + /** + * Utility function for decoding from Strings produced by the above method. + * + * @param component + * the encoded component + * @return the decoded component + */ + private static String unescapeStoreNameComponent(String component) + { + StringBuilder builder = null; + int length = component.length(); + int lastAppendPosition = 0; + int escapeIndex; + while ((escapeIndex = component.indexOf("_x", lastAppendPosition)) != -1) + { + if (builder == null) + { + builder = new StringBuilder(length + 5); + } + if (escapeIndex != lastAppendPosition) + { + builder.append(component, lastAppendPosition, escapeIndex); + } + lastAppendPosition = component.indexOf('_', escapeIndex + 2); + builder.appendCodePoint(Integer.parseInt(component.substring(escapeIndex + 2, lastAppendPosition), 16)); + lastAppendPosition++; + } + if (builder == null) + { + return component; + } + if (lastAppendPosition < length) + { + builder.append(component, lastAppendPosition, length); + } + + return builder.toString(); + } + + private static final void appendEncoded(StringBuilder builder, String sequence) + { + builder.append("_x").append(Integer.toString(sequence.codePointAt(0), 16).toUpperCase()).append("_"); + int length = sequence.length(); + int next = sequence.offsetByCodePoints(0, 1); + if (next < length) + { + builder.append(sequence, next, length); + } + } + /** * Returns the main staging store name for the specified web project * @@ -340,7 +437,7 @@ public class WCMUtil extends AVMUtil final String userName) { ParameterCheck.mandatoryString("userName", userName); - String fixedUserName = FileNameValidator.getValidFileName(userName); + String fixedUserName = escapeStoreNameComponent(userName); return (WCMUtil.buildStagingStoreName(storeId) + WCMUtil.STORE_SEPARATOR + fixedUserName); } @@ -753,6 +850,9 @@ public class WCMUtil extends AVMUtil // Component Separator. protected static final String STORE_SEPARATOR = "--"; + + /** Matches character sequences that must be escaped in a compound store name. */ + protected static final Pattern PATTERN_ILLEGAL_SEQUENCE = Pattern.compile(FileNameValidator.FILENAME_ILLEGAL_REGEX + "|_x|" + STORE_SEPARATOR); // names of the stores representing the layers for an AVM website //XXXarielb this should be private