From 5e37a4a285508c0acefe9d771077a7ff48f83ddb Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Thu, 14 Apr 2016 15:52:34 +0000
Subject: [PATCH] OPENDJ-2792 Fix schema parsing to correctly read base64 encoded values

---
 opendj-server-legacy/src/messages/org/opends/messages/backend.properties |    6 +
 opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java   |  146 +++++++++++++++++++++---------------------------
 2 files changed, 69 insertions(+), 83 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
index 4b90c7c..60c7bf0 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
@@ -23,6 +23,7 @@
 import java.io.FileWriter;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -63,6 +64,7 @@
 import org.opends.server.schema.NameFormSyntax;
 import org.opends.server.schema.ObjectClassSyntax;
 import org.opends.server.schema.SomeSchemaElement;
+import org.opends.server.util.Base64;
 import org.opends.server.util.ServerConstants;
 import org.opends.server.util.StaticUtils;
 
@@ -2257,27 +2259,8 @@
       // element list.
       for (StringBuilder buffer : lines)
       {
-        // Get the line and add the X-SCHEMA-FILE extension to the end
-        // of it.  All of them should end with " )" but some might
-        // have the parenthesis crammed up against the last character
-        // so deal with that as well.
         String line = buffer.toString().trim();
-        if (line.endsWith(" )"))
-        {
-         line = line.substring(0, line.length()-1) +
-                SCHEMA_PROPERTY_FILENAME + " '" + f.getName() + "' )";
-        }
-        else if (line.endsWith(")"))
-        {
-         line = line.substring(0, line.length()-1) + " " +
-                SCHEMA_PROPERTY_FILENAME + " '" + f.getName() + "' )";
-        }
-        else
-        {
-          continue;
-        }
-
-        parseSchemaLine(line, attributeTypes, objectClasses,
+        parseSchemaLine(line, f.getName(), attributeTypes, objectClasses,
             nameForms, ditContentRules, ditStructureRules, matchingRuleUses,
             ldapSyntaxes);
       }
@@ -2336,7 +2319,7 @@
       {
         break;
       }
-      parseSchemaLine(line, attributeTypes, objectClasses,
+      parseSchemaLine(line, null, attributeTypes, objectClasses,
           nameForms, ditContentRules, ditStructureRules, matchingRuleUses,
           ldapSyntaxes);
     }
@@ -2344,79 +2327,80 @@
     reader.close();
   }
 
-  /**
-   * Parse a line of a schema file into the provided sets.
-   *
-   * @param line                The current line of schema.
-   * @param  attributeTypes     The set into which to place the
-   *                            attribute type if the line represents
-   *                            one.
-   * @param  objectClasses      The set into which to place the object
-   *                            class if the line represents one.
-   * @param  nameForms          The set into which to place the name
-   *                            form if the line represents one.
-   * @param  ditContentRules    The set into which to place the DIT
-   *                            content rule if the line represents one.
-   * @param  ditStructureRules  The set into which to place the DIT
-   *                            structure rule if the line represents one.
-   * @param  matchingRuleUses   The set into which to place the
-   *                            matching rule use if the line represents
-   *                            one.
-   * @param ldapSyntaxes        The set into which to place the ldap
-   *                            syntax if the line represents one.
-   */
-
-  private static void parseSchemaLine(String line,
-                               Set<String> attributeTypes,
-                               Set<String> objectClasses,
-                               Set<String> nameForms,
-                               Set<String> ditContentRules,
-                               Set<String> ditStructureRules,
-                               Set<String> matchingRuleUses,
-                               Set<String> ldapSyntaxes)
+  private static void parseSchemaLine(String line, String fileName,
+      Set<String> attributeTypes,
+      Set<String> objectClasses,
+      Set<String> nameForms,
+      Set<String> ditContentRules,
+      Set<String> ditStructureRules,
+      Set<String> matchingRuleUses,
+      Set<String> ldapSyntaxes)
   {
-    String value;
     String lowerLine = toLowerCase(line);
-    if (lowerLine.startsWith(ATTR_ATTRIBUTE_TYPES_LC))
+
+    try
     {
-      value =
-          line.substring(ATTR_ATTRIBUTE_TYPES.length()+1).trim();
-      attributeTypes.add(value);
-    }
-    else if (lowerLine.startsWith(ATTR_OBJECTCLASSES_LC))
+      if (lowerLine.startsWith(ATTR_ATTRIBUTE_TYPES_LC))
+      {
+        attributeTypes.add(getSchemaDefinition(line.substring(ATTR_ATTRIBUTE_TYPES_LC.length()), fileName));
+      }
+      else if (lowerLine.startsWith(ATTR_OBJECTCLASSES_LC))
+      {
+        objectClasses.add(getSchemaDefinition(line.substring(ATTR_OBJECTCLASSES_LC.length()), fileName));
+      }
+      else if (lowerLine.startsWith(ATTR_NAME_FORMS_LC))
+      {
+        nameForms.add(getSchemaDefinition(line.substring(ATTR_NAME_FORMS_LC.length()), fileName));
+      }
+      else if (lowerLine.startsWith(ATTR_DIT_CONTENT_RULES_LC))
+      {
+        ditContentRules.add(getSchemaDefinition(line.substring(ATTR_DIT_CONTENT_RULES_LC.length()), fileName));
+      }
+      else if (lowerLine.startsWith(ATTR_DIT_STRUCTURE_RULES_LC))
+      {
+        ditStructureRules.add(getSchemaDefinition(line.substring(ATTR_DIT_STRUCTURE_RULES_LC.length()), fileName));
+      }
+      else if (lowerLine.startsWith(ATTR_MATCHING_RULE_USE_LC))
+      {
+        matchingRuleUses.add(getSchemaDefinition(line.substring(ATTR_MATCHING_RULE_USE_LC.length()), fileName));
+      }
+      else if (lowerLine.startsWith(ATTR_LDAP_SYNTAXES_LC))
+      {
+        ldapSyntaxes.add(getSchemaDefinition(line.substring(ATTR_LDAP_SYNTAXES_LC.length()), fileName));
+      }
+    } catch (ParseException pe)
     {
-      value = line.substring(ATTR_OBJECTCLASSES.length()+1).trim();
-      objectClasses.add(value);
+      logger.error(ERR_SCHEMA_PARSE_LINE.get(line, pe.getLocalizedMessage()));
     }
-    else if (lowerLine.startsWith(ATTR_NAME_FORMS_LC))
+  }
+
+  private static String getSchemaDefinition(String line, String fileName) throws ParseException
+  {
+    if (line.startsWith("::"))
     {
-      value = line.substring(ATTR_NAME_FORMS.length()+1).trim();
-      nameForms.add(value);
+      line = ByteString.wrap(Base64.decode(line.substring(2).trim())).toString();
     }
-    else if (lowerLine.startsWith(ATTR_DIT_CONTENT_RULES_LC))
+    else if (line.startsWith(":"))
     {
-      value = line.substring(
-          ATTR_DIT_CONTENT_RULES.length()+1).trim();
-      ditContentRules.add(value);
+      line = line.substring(1).trim();
     }
-    else if (lowerLine.startsWith(ATTR_DIT_STRUCTURE_RULES_LC))
+    else
     {
-      value = line.substring(
-          ATTR_DIT_STRUCTURE_RULES.length()+1).trim();
-      ditStructureRules.add(value);
+      throw new ParseException(ERR_SCHEMA_COULD_NOT_PARSE_DEFINITION.get().toString(), 0);
     }
-    else if (lowerLine.startsWith(ATTR_MATCHING_RULE_USE_LC))
+
+    if (fileName != null)
     {
-      value = line.substring(
-          ATTR_MATCHING_RULE_USE.length()+1).trim();
-      matchingRuleUses.add(value);
+      if (line.endsWith(" )"))
+      {
+        line = line.substring(0, line.length() - 1) + SCHEMA_PROPERTY_FILENAME + " '" + fileName + "' )";
+      }
+      else if (line.endsWith(")"))
+      {
+        line = line.substring(0, line.length() - 1) + " " + SCHEMA_PROPERTY_FILENAME + " '" + fileName + "' )";
+      }
     }
-    else if (lowerLine.startsWith(ATTR_LDAP_SYNTAXES_LC))
-    {
-      value = line.substring(
-          ATTR_LDAP_SYNTAXES.length()+1).trim();
-      ldapSyntaxes.add(value);
-    }
+    return line;
   }
 
   /**
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/backend.properties b/opendj-server-legacy/src/messages/org/opends/messages/backend.properties
index b208b23..bb434f0 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/backend.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/backend.properties
@@ -1078,6 +1078,8 @@
 children for DN <%s> (got %d, expecting %d)
 ERR_VERIFY_ID2COUNT_WRONG_ID_597=File id2ChildrenCount references non-existing EntryID <%d>.
 NOTE_REBUILD_NOTHING_TO_REBUILD_598=Rebuilding index finished: no indexes to rebuild.
-NOTE_IMPORT_LDIF_OFFHEAP_MEM_BUF_INFO_520=Setting DB cache size to %d bytes. \
+NOTE_IMPORT_LDIF_OFFHEAP_MEM_BUF_INFO_599=Setting DB cache size to %d bytes. \
  Using %d Mb off-heap memory through %d phase one buffers of %d Kb.
- 
\ No newline at end of file
+ERR_SCHEMA_PARSE_LINE_600=Ignoring schema definition '%s' because the following error occurred while \
+  it was being parsed: %s
+ERR_SCHEMA_COULD_NOT_PARSE_DEFINITION_601=Schema definition could not be parsed as valid attribute value

--
Gitblit v1.10.0