From 368f01a338bad22523e52709645de7338d8024f3 Mon Sep 17 00:00:00 2001 From: Britt Park Date: Tue, 29 Aug 2006 17:46:32 +0000 Subject: [PATCH] The AVM repository does name validation. Changed internal representation of AVM NodeRefs to make the Node Browser in the UI happier. Added minimal test to ensure that AVM is case insensitive. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3627 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../alfresco/repo/avm/AVMNodeConverter.java | 10 +++++ .../org/alfresco/repo/avm/AVMServiceImpl.java | 37 ++++++++-------- .../org/alfresco/repo/avm/AVMServiceTest.java | 25 +++++++++++ .../alfresco/repo/avm/FileNameValidator.java | 42 +++++++++++++++++++ .../repo/avm/FileNameValidatorTest.java | 37 ++++++++++++++++ 5 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 source/java/org/alfresco/repo/avm/FileNameValidator.java create mode 100644 source/java/org/alfresco/repo/avm/FileNameValidatorTest.java 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)); + } + } +}