You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2022/09/26 10:39:19 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-658: Importer fails for invalid namespace names (#245)

This is an automated email from the ASF dual-hosted git repository.

reschke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git


The following commit(s) were added to refs/heads/master by this push:
     new e63bc36a JCRVLT-658: Importer fails for invalid namespace names (#245)
e63bc36a is described below

commit e63bc36a185b0175b352d78561c2688f1030447d
Author: Julian Reschke <ju...@gmx.de>
AuthorDate: Mon Sep 26 12:39:13 2022 +0200

    JCRVLT-658: Importer fails for invalid namespace names (#245)
    
    * JCRVLT-658: Importer fails for invalid namespace names
    
    * JCRVLT-658: Importer fails for invalid namespace names - remove unused files
    
    * JCRVLT-658: Importer fails for invalid namespace names - remove unused files
    
    * JCRVLT-658: Importer fails for invalid namespace names - method naming
    
    * JCRVLT-658: Importer fails for invalid namespace names - no sling:folder
    
    * JCRVLT-658: Importer fails for invalid namespace names - avoid ns name confusion, separate tests into same session and new session
    
    * JCRVLT-658: Importer fails for invalid namespace names - cover property names as well
    
    * JCRVLT-658: Importer fails for invalid namespace names - simplify DocViewImporter to always use qualified name
---
 .../vault/fs/impl/io/DocViewImporter.java          | 19 +++++++-----
 .../jackrabbit/vault/util/DocViewProperty2.java    | 34 ++++++++++++++++------
 .../packaging/integration/NamespaceImportIT.java   | 34 ++++++++++++++++++++++
 .../META-INF/vault/filter.xml                      |  4 +++
 .../META-INF/vault/properties.xml                  | 18 ++++++++++++
 .../badnamespacenames.zip/jcr_root/.content.xml    |  4 +++
 .../jcr_root/tmp/.content.xml                      |  4 +++
 .../jcr_root/tmp/badnamespacenames.xml             | 13 +++++++++
 8 files changed, 113 insertions(+), 17 deletions(-)

diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java
index c4bd9431..a2777edc 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java
@@ -218,8 +218,8 @@ public class DocViewImporter implements DocViewParserHandler {
     /**
      * {@code true} in case the repository supports same-name siblings
      */
-	private final boolean isSnsSupported;
-    
+    private final boolean isSnsSupported;
+
     /**
      * Creates a new importer that will imports the
      * items below the given root.
@@ -1203,25 +1203,27 @@ public class DocViewImporter implements DocViewParserHandler {
     private Node getNodeByIdOrName(@NotNull Node currentNode, @NotNull DocViewNode2 ni, boolean isIdNewlyAssigned) throws RepositoryException {
         Node node = null;
         Optional<String> id = ni.getIdentifier();
+        String name = npResolver.getJCRName(ni.getName());
         if (id.isPresent() && !isIdNewlyAssigned) {
             try {
                 node = currentNode.getSession().getNodeByIdentifier(id.get());
             } catch (RepositoryException e) {
-                log.warn("Newly created node not found by uuid {}: {}", currentNode.getPath() + "/" + ni.getName(), e.toString());
+                log.warn("Newly created node not found by uuid {}: {}", currentNode.getPath() + "/" + name, e.toString());
             }
         }
         if (node == null) {
+            String snsName = npResolver.getJCRName(ni.getSnsAwareName());
             try {
-                node = currentNode.getNode(ni.getSnsAwareName().toString());
+                node = currentNode.getNode(snsName);
             } catch (RepositoryException e) {
-                log.warn("Newly created node not found by SNS aware name {}: {}", currentNode.getPath() + "/" + ni.getSnsAwareName(), e.toString());
+                log.warn("Newly created node not found by SNS aware name {}: {}", currentNode.getPath() + "/" + snsName, e.toString());
             }
         }
         if (node == null) {
             try {
-                node = currentNode.getNode(ni.getName().toString());
+                node = currentNode.getNode(name);
             } catch (RepositoryException e) {
-                log.debug("Newly created node not found by name {}: {}", currentNode.getPath() + "/" + ni.getName(), e.toString());
+                log.debug("Newly created node not found by name {}: {}", currentNode.getPath() + "/" + name, e.toString());
                 throw e;
             }
         }
@@ -1239,7 +1241,8 @@ public class DocViewImporter implements DocViewParserHandler {
         boolean modified = false;
         // add properties
         for (DocViewProperty2 prop : ni.getProperties()) {
-            if (prop != null && !isPropertyProtected(effectiveNodeType, prop) && (overwriteExistingProperties || !node.hasProperty(prop.getName().toString())) && wspFilter.includesProperty(node.getPath() + "/" + npResolver.getJCRName(prop.getName()))) {
+            String name = npResolver.getJCRName(prop.getName());
+            if (prop != null && !isPropertyProtected(effectiveNodeType, prop) && (overwriteExistingProperties || !node.hasProperty(name)) && wspFilter.includesProperty(node.getPath() + "/" + npResolver.getJCRName(prop.getName()))) {
                 // check if property is allowed
                 try {
                     modified |= prop.apply(node);
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty2.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty2.java
index 8cb2ce56..d17a84f5 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty2.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewProperty2.java
@@ -33,6 +33,7 @@ import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
 import javax.jcr.lock.LockException;
@@ -125,7 +126,7 @@ public class DocViewProperty2 {
         for (Value value : values) {
             strValues.add(serializeValue(value, useBinaryReferences));
         }
-        
+
         Boolean isBinaryRef = null;
         if (type == PropertyType.BINARY) {
             // either only binary references or regular binaries
@@ -508,6 +509,19 @@ public class DocViewProperty2 {
         return type != PropertyType.STRING && type != PropertyType.UNDEFINED && !UNAMBIGUOUS.contains(name);
     }
 
+    /**
+     * Returns a suitable qualified JCR name.
+     */
+    private String getQualifiedName(Session session, Name name) throws RepositoryException {
+        // TODO: could use nsresolver instead
+        String nsuri = name.getNamespaceURI();
+        if (nsuri.isEmpty()) {
+            return name.getLocalName();
+        } else {
+            return session.getNamespacePrefix(nsuri) + ":" + name.getLocalName();
+        }
+    }
+
     /**
      * Sets this property on the given node.
      *
@@ -516,7 +530,8 @@ public class DocViewProperty2 {
      * @throws RepositoryException if a repository error occurs
      */
     public boolean apply(@NotNull Node node) throws RepositoryException {
-        Property prop = node.hasProperty(name.toString()) ? node.getProperty(name.toString()) : null;
+        String qualifiedName = getQualifiedName(node.getSession(), name);
+        Property prop = node.hasProperty(qualifiedName) ? node.getProperty(qualifiedName) : null;
         // check if multiple flags are equal
         if (prop != null && isMultiValue != prop.getDefinition().isMultiple()) {
             prop.remove();
@@ -547,9 +562,9 @@ public class DocViewProperty2 {
                 }
             }
             if (type == PropertyType.UNDEFINED) {
-                node.setProperty(name.toString(), values.toArray(new String[0]));
+                node.setProperty(qualifiedName, values.toArray(new String[0]));
             } else {
-                node.setProperty(name.toString(), values.toArray(new String[0]), type);
+                node.setProperty(qualifiedName, values.toArray(new String[0]), type);
             }
             // assume modified
             return true;
@@ -561,13 +576,13 @@ public class DocViewProperty2 {
             if (v == null || !v.getString().equals(values.get(0))) {
                 try {
                     if (type == PropertyType.UNDEFINED) {
-                        node.setProperty(name.toString(), values.get(0));
+                        node.setProperty(qualifiedName, values.get(0));
                     } else {
-                        node.setProperty(name.toString(), values.get(0), type);
+                        node.setProperty(qualifiedName, values.get(0), type);
                     }
                 } catch (ValueFormatException e) {
                     // forcing string
-                    node.setProperty(name.toString(), values.get(0), PropertyType.STRING);
+                    node.setProperty(qualifiedName, values.get(0), PropertyType.STRING);
                 }
                 return true;
             }
@@ -607,10 +622,11 @@ public class DocViewProperty2 {
             if (!modified) {
                 return false;
             }
+            String qualifiedName = getQualifiedName(node.getSession(), name);
             if (isMultiValue) {
-                node.setProperty(name.toString(), binaryValues.toArray(new Value[0]));
+                node.setProperty(qualifiedName, binaryValues.toArray(new Value[0]));
             } else {
-                node.setProperty(name.toString(), binaryValues.get(0));
+                node.setProperty(qualifiedName, binaryValues.get(0));
             }
             // the binary property is always modified (TODO: check if still correct with JCRVLT-110)
             return true;
diff --git a/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NamespaceImportIT.java b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NamespaceImportIT.java
index 2225b477..8a52e268 100644
--- a/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NamespaceImportIT.java
+++ b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NamespaceImportIT.java
@@ -169,6 +169,40 @@ public class NamespaceImportIT extends IntegrationTestBase {
         }
     }
 
+    @Test
+    public void testBadNamespaceNames() throws RepositoryException, IOException, PackageException {
+        extractVaultPackageStrict("/test-packages/badnamespacenames.zip");
+
+        // Check that after the import, the session used for the import has
+        // namepace mapping for the namespaced items being imported
+        String prefixFoo = admin.getNamespacePrefix("name_foo");
+        assertNotNull(prefixFoo);
+        String prefixBar = admin.getNamespacePrefix("name_bar");
+        assertNotNull(prefixBar);
+        String prefixQux = admin.getNamespacePrefix("name_qux");
+        assertNotNull(prefixQux);
+
+        // assert node were created, checking the qualified name syntax
+        assertNodeExists("/tmp/badnamespacenames/" + prefixFoo + ":child");
+        assertNodeExists("/tmp/badnamespacenames/" + prefixFoo + ":child/" + prefixBar + ":child");
+        assertProperty("/tmp/badnamespacenames/" + prefixFoo + ":child/" + prefixBar + ":child/" + prefixQux + ":someproperty", "xyz");
+
+        // retry with a fresh session and explicitly set namespace mappings
+        Session secondSession = admin.impersonate(new SimpleCredentials("admin", "admin".toCharArray()));
+        try {
+            secondSession.setNamespacePrefix("t_foo", "name_foo");
+            secondSession.setNamespacePrefix("t_bar", "name_bar");
+            secondSession.setNamespacePrefix("t_qux", "name_qux");
+
+            Node n1 = secondSession.getNode("/tmp/badnamespacenames/t_foo:child");
+            Node n2 = n1.getNode("t_bar:child");
+            n2.getProperty("t_qux:someproperty");
+        }
+        finally {
+            secondSession.logout();
+        }
+    }
+
     /** Simple Oak repository wrapper */
     private static final class Instance {
 
diff --git a/vault-core/src/test/resources/test-packages/badnamespacenames.zip/META-INF/vault/filter.xml b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/META-INF/vault/filter.xml
new file mode 100644
index 00000000..7705dc81
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/META-INF/vault/filter.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workspaceFilter version="1.0">
+    <filter root="/tmp/badnamespacenames"/>
+</workspaceFilter>
diff --git a/vault-core/src/test/resources/test-packages/badnamespacenames.zip/META-INF/vault/properties.xml b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/META-INF/vault/properties.xml
new file mode 100644
index 00000000..2494f50c
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/META-INF/vault/properties.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+<comment>FileVault Package Properties</comment>
+<entry key="createdBy">admin</entry>
+<entry key="name">test_referenceable</entry>
+<entry key="lastModified">2015-12-16T16:59:10.779+01:00</entry>
+<entry key="lastModifiedBy">admin</entry>
+<entry key="created">2015-12-16T16:59:10.795+01:00</entry>
+<entry key="buildCount">5</entry>
+<entry key="version"/>
+<entry key="dependencies"/>
+<entry key="packageFormatVersion">2</entry>
+<entry key="description"/>
+<entry key="lastWrapped">2015-12-16T16:59:10.779+01:00</entry>
+<entry key="group">my_packages</entry>
+<entry key="lastWrappedBy">admin</entry>
+</properties>
diff --git a/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/.content.xml b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/.content.xml
new file mode 100644
index 00000000..6d7a9768
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/.content.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable,rep:RepoAccessControllable]"
+    jcr:primaryType="rep:root"/>
diff --git a/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/tmp/.content.xml b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/tmp/.content.xml
new file mode 100644
index 00000000..fb0a629b
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/tmp/.content.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="nt:unstructured"/>
diff --git a/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/tmp/badnamespacenames.xml b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/tmp/badnamespacenames.xml
new file mode 100644
index 00000000..2ec6804e
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/badnamespacenames.zip/jcr_root/tmp/badnamespacenames.xml
@@ -0,0 +1,13 @@
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" 
+    jcr:primaryType="nt:unstructured"
+    xmlns:prefix_foo="name_foo"
+    xmlns:prefix_bar="name_bar"
+    xmlns:prefix_qux="name_qux">
+    <prefix_foo:child
+        jcr:primaryType="nt:unstructured">
+        <prefix_bar:child
+            jcr:primaryType="nt:unstructured"
+            prefix_qux:someproperty="xyz">
+        </prefix_bar:child>
+    </prefix_foo:child>
+</jcr:root>