diff --git a/source/java/org/alfresco/repo/avm/AVMNodeConverter.java b/source/java/org/alfresco/repo/avm/AVMNodeConverter.java index 592db678d5..a6954bdf4e 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeConverter.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeConverter.java @@ -19,6 +19,7 @@ package org.alfresco.repo.avm; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; +import org.apache.log4j.Logger; /** * Utility for going back and forth between the AVM world and @@ -27,6 +28,8 @@ import org.alfresco.service.cmr.repository.StoreRef; */ public class AVMNodeConverter { + private static Logger fgLogger = Logger.getLogger(AVMNodeConverter.class); + /** * Get a NodeRef corresponding to the given path and version. * @param version The version id. @@ -42,6 +45,7 @@ public class AVMNodeConverter } StoreRef storeRef = ToStoreRef(pathParts[0]); String translated = version + pathParts[1]; + translated = translated.replaceAll("/+", ";"); return new NodeRef(storeRef, translated); } @@ -64,7 +68,13 @@ public class AVMNodeConverter { StoreRef store = nodeRef.getStoreRef(); String translated = nodeRef.getId(); + translated = translated.replace(';', '/'); int off = translated.indexOf("/"); + if (off == -1) + { + fgLogger.error(translated); + throw new AVMException("Bad Node Reference."); + } int version = Integer.parseInt(translated.substring(0, off)); String path = translated.substring(off); Object [] result = new Object[2]; diff --git a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java index 77bd39032f..3c3b5d6799 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java @@ -263,9 +263,9 @@ public class AVMServiceImpl implements AVMService */ public OutputStream createFile(final String path, final String name) { - if (path == null || name == null) + if (path == null || name == null || !FileNameValidator.IsValid(name)) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Illegal argument."); } class TxnCallback implements RetryingTransactionCallback { @@ -281,7 +281,6 @@ public class AVMServiceImpl implements AVMService return doit.out; } - // TODO Eliminate this. /** * Create a file with content specified by the InputStream. * Guaranteed to be created atomically. @@ -291,9 +290,9 @@ public class AVMServiceImpl implements AVMService */ public void createFile(final String path, final String name, InputStream in) { - if (path == null || name == null || in == null) + if (path == null || name == null || in == null || !FileNameValidator.IsValid(name)) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Illegal argument."); } // Save the contents to temp space. final File temp; @@ -339,9 +338,9 @@ public class AVMServiceImpl implements AVMService */ public void createDirectory(final String path, final String name) { - if (path == null || name == null) + if (path == null || name == null || !FileNameValidator.IsValid(name)) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Illegal argument."); } class TxnCallback implements RetryingTransactionCallback { @@ -362,9 +361,10 @@ public class AVMServiceImpl implements AVMService */ public void createLayeredFile(final String srcPath, final String parent, final String name) { - if (srcPath == null || parent == null || name == null) + if (srcPath == null || parent == null || name == null || + !FileNameValidator.IsValid(name)) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Illegal argument."); } class TxnCallback implements RetryingTransactionCallback { @@ -385,9 +385,10 @@ public class AVMServiceImpl implements AVMService */ public void createLayeredDirectory(final String srcPath, final String parent, final String name) { - if (srcPath == null || parent == null || name == null) + if (srcPath == null || parent == null || name == null || + !FileNameValidator.IsValid(name)) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Illegal argument."); } class TxnCallback implements RetryingTransactionCallback { @@ -406,9 +407,9 @@ public class AVMServiceImpl implements AVMService */ public void createAVMStore(final String name) { - if (name == null) + if (name == null || !FileNameValidator.IsValid(name)) { - throw new AVMBadArgumentException("Name is null."); + throw new AVMBadArgumentException("Bad Name."); } class TxnCallback implements RetryingTransactionCallback { @@ -431,9 +432,10 @@ public class AVMServiceImpl implements AVMService public void createBranch(final int version, final String srcPath, final String dstPath, final String name) { - if (srcPath == null || dstPath == null || name == null) + if (srcPath == null || dstPath == null || name == null || + !FileNameValidator.IsValid(name)) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Illegal argument."); } class TxnCallback implements RetryingTransactionCallback { @@ -479,9 +481,10 @@ public class AVMServiceImpl implements AVMService public void rename(final String srcParent, final String srcName, final String dstParent, final String dstName) { - if (srcParent == null || srcName == null || dstParent == null || dstName == null) + if (srcParent == null || srcName == null || dstParent == null || dstName == null || + !FileNameValidator.IsValid(dstName)) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Illegal argument."); } class TxnCallback implements RetryingTransactionCallback { diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 0d8b9b2076..b825673736 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -2223,4 +2223,29 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } + + /** + * Test case insensitivity. + */ + public void testCaseInsensitive() + { + try + { + setupBasicTree(); + try + { + fService.createFile("main:/a/b/c", "Foo").close(); + fail(); + } + catch (AVMExistsException e) + { + // Do nothing. + } + } + catch (Exception e) + { + e.printStackTrace(System.err); + fail(); + } + } } diff --git a/source/java/org/alfresco/repo/avm/FileNameValidator.java b/source/java/org/alfresco/repo/avm/FileNameValidator.java new file mode 100644 index 0000000000..d4b8c542ee --- /dev/null +++ b/source/java/org/alfresco/repo/avm/FileNameValidator.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.repo.avm; + +import java.util.regex.Pattern; + +/** + * Static checker for valid file names. + * @author britt + */ +public class FileNameValidator +{ + /** + * The bad file name pattern. + */ + private static String fgBadPattern = ".*[\"\\*\\\\><\\?/:\\|\\xA3\\xAC%&\\+;]+.*"; + + /** + * The compiled regex. + */ + private static Pattern fgPattern = Pattern.compile(fgBadPattern); + + public static boolean IsValid(String name) + { + return !fgPattern.matcher(name).matches(); + } +} diff --git a/source/java/org/alfresco/repo/avm/FileNameValidatorTest.java b/source/java/org/alfresco/repo/avm/FileNameValidatorTest.java new file mode 100644 index 0000000000..a628572aa5 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/FileNameValidatorTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.repo.avm; + +import junit.framework.TestCase; + +/** + * Test File Name validation. + * @author britt + */ +public class FileNameValidatorTest extends TestCase +{ + public void testValidator() + { + String [] badNames = new String[] { "\"", "\\", "/", "<", ">", "?", "*", "%", "&", "+", + ":", ";", "|" }; + for (String name : badNames) + { + assertFalse(FileNameValidator.IsValid(name)); + } + } +}