aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2014-12-04 01:17:26 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2014-12-04 01:17:26 +0000
commitd327ceb55eef6e222749346e2c20c7e5dfd08041 (patch)
treed8e5c186306570a001c5608fe51d00c7534ef535 /src
parente6e0208c973f6a67e8d4593aa665133a6d7e7f03 (diff)
downloadjackcess-d327ceb55eef6e222749346e2c20c7e5dfd08041.tar.gz
jackcess-d327ceb55eef6e222749346e2c20c7e5dfd08041.zip
Better validation of identifier names (disallow invalid characters according to access naming rules)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@902 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src')
-rw-r--r--src/changes/changes.xml4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/IndexBuilder.java8
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java55
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java9
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/TableCreator.java9
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java3
6 files changed, 79 insertions, 9 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 5137378..d128dc3 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -14,6 +14,10 @@
<action dev="jahlborn" type="fix" system="SourceForge2Patches" issue="18">
Don't double quote already quoted identifiers.
</action>
+ <action dev="jahlborn" type="update">
+ Better validation of identifier names (disallow invalid characters
+ according to Access naming rules).
+ </action>
</release>
<release version="2.0.7" date="2014-11-22">
<action dev="jahlborn" type="fix" system="SourceForge2" issue="111">
diff --git a/src/main/java/com/healthmarketscience/jackcess/IndexBuilder.java b/src/main/java/com/healthmarketscience/jackcess/IndexBuilder.java
index 26c2c85..4a55205 100644
--- a/src/main/java/com/healthmarketscience/jackcess/IndexBuilder.java
+++ b/src/main/java/com/healthmarketscience/jackcess/IndexBuilder.java
@@ -24,8 +24,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.impl.IndexData;
import com.healthmarketscience.jackcess.impl.IndexImpl;
+import com.healthmarketscience.jackcess.impl.JetFormat;
/**
* Builder style class for constructing an {@link Index}. See {@link
@@ -133,7 +135,11 @@ public class IndexBuilder
return this;
}
- public void validate(Set<String> tableColNames) {
+ public void validate(Set<String> tableColNames, JetFormat format) {
+
+ DatabaseImpl.validateIdentifierName(
+ getName(), format.MAX_INDEX_NAME_LENGTH, "index");
+
if(getColumns().isEmpty()) {
throw new IllegalArgumentException("index " + getName() +
" has no columns");
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
index 548833b..2afd394 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -56,6 +56,7 @@ import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
+import java.util.regex.Pattern;
import com.healthmarketscience.jackcess.ColumnBuilder;
import com.healthmarketscience.jackcess.Cursor;
@@ -248,7 +249,10 @@ public class DatabaseImpl implements Database
/** the columns to read when getting object propertyes */
private static Collection<String> SYSTEM_CATALOG_PROPS_COLUMNS =
new HashSet<String>(Arrays.asList(CAT_COL_ID, CAT_COL_PROPS));
-
+
+ /** regex matching characters which are invalid in identifier names */
+ private static final Pattern INVALID_IDENTIFIER_CHARS =
+ Pattern.compile("[\\p{Cntrl}.!`\\]\\[]");
/** the File of the database */
private final File _file;
@@ -960,8 +964,8 @@ public class DatabaseImpl implements Database
}
validateIdentifierName(name, getFormat().MAX_TABLE_NAME_LENGTH, "table");
- validateIdentifierName(linkedDbName, DataType.MEMO.getMaxSize(),
- "linked database");
+ validateName(linkedDbName, DataType.MEMO.getMaxSize(),
+ "linked database");
validateIdentifierName(linkedTableName, getFormat().MAX_TABLE_NAME_LENGTH,
"linked table");
@@ -1481,22 +1485,61 @@ public class DatabaseImpl implements Database
/**
* Validates an identifier name.
+ *
+ * Names of fields, controls, and objects in Microsoft Access:
+ * <ul>
+ * <li>Can include any combination of letters, numbers, spaces, and special
+ * characters except a period (.), an exclamation point (!), an accent
+ * grave (`), and brackets ([ ]).</li>
+ * <li>Can't begin with leading spaces.</li>
+ * <li>Can't include control characters (ASCII values 0 through 31).</li>
+ * </ul>
+ *
* @usage _advanced_method_
*/
public static void validateIdentifierName(String name,
int maxLength,
String identifierType)
{
- if((name == null) || (name.trim().length() == 0)) {
+ // basic name validation
+ validateName(name, maxLength, identifierType);
+
+ // additional identifier validation
+ if(INVALID_IDENTIFIER_CHARS.matcher(name).find()) {
throw new IllegalArgumentException(
- identifierType + " must have non-empty name");
+ identifierType + " name contains invalid characters");
+ }
+
+ // cannot start with spaces
+ if(name.charAt(0) == ' ') {
+ throw new IllegalArgumentException(
+ identifierType + " name cannot start with a space character");
+ }
+ }
+
+ /**
+ * Validates a name.
+ */
+ private static void validateName(String name, int maxLength, String nameType)
+ {
+ if(isBlank(name)) {
+ throw new IllegalArgumentException(
+ nameType + " must have non-blank name");
}
if(name.length() > maxLength) {
throw new IllegalArgumentException(
- identifierType + " name is longer than max length of " + maxLength +
+ nameType + " name is longer than max length of " + maxLength +
": " + name);
}
}
+
+ /**
+ * Returns {@code true} if the given string is {@code null} or all blank
+ * space, {@code false} otherwise.
+ */
+ public static boolean isBlank(String name) {
+ return((name == null) || (name.trim().length() == 0));
+ }
@Override
public String toString() {
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
index fcb39bd..4c915e3 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java
@@ -264,6 +264,7 @@ public abstract class JetFormat {
public final int USAGE_MAP_TABLE_BYTE_LENGTH;
public final int MAX_COLUMNS_PER_TABLE;
+ public final int MAX_INDEXES_PER_TABLE;
public final int MAX_TABLE_NAME_LENGTH;
public final int MAX_COLUMN_NAME_LENGTH;
public final int MAX_INDEX_NAME_LENGTH;
@@ -399,6 +400,7 @@ public abstract class JetFormat {
USAGE_MAP_TABLE_BYTE_LENGTH = defineUsageMapTableByteLength();
MAX_COLUMNS_PER_TABLE = defineMaxColumnsPerTable();
+ MAX_INDEXES_PER_TABLE = defineMaxIndexesPerTable();
MAX_TABLE_NAME_LENGTH = defineMaxTableNameLength();
MAX_COLUMN_NAME_LENGTH = defineMaxColumnNameLength();
MAX_INDEX_NAME_LENGTH = defineMaxIndexNameLength();
@@ -502,6 +504,7 @@ public abstract class JetFormat {
protected abstract int defineUsageMapTableByteLength();
protected abstract int defineMaxColumnsPerTable();
+ protected abstract int defineMaxIndexesPerTable();
protected abstract int defineMaxTableNameLength();
protected abstract int defineMaxColumnNameLength();
protected abstract int defineMaxIndexNameLength();
@@ -710,6 +713,9 @@ public abstract class JetFormat {
protected int defineMaxColumnsPerTable() { return 255; }
@Override
+ protected int defineMaxIndexesPerTable() { return 32; }
+
+ @Override
protected int defineMaxTableNameLength() { return 64; }
@Override
@@ -938,6 +944,9 @@ public abstract class JetFormat {
@Override
protected int defineMaxColumnsPerTable() { return 255; }
+
+ @Override
+ protected int defineMaxIndexesPerTable() { return 32; }
@Override
protected int defineMaxTableNameLength() { return 64; }
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableCreator.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableCreator.java
index 8828ac2..c720654 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/TableCreator.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableCreator.java
@@ -231,11 +231,18 @@ class TableCreator
}
if(hasIndexes()) {
+
+ if(_indexes.size() > getFormat().MAX_INDEXES_PER_TABLE) {
+ throw new IllegalArgumentException(
+ "Cannot create table with more than " +
+ getFormat().MAX_INDEXES_PER_TABLE + " indexes");
+ }
+
// now, validate the indexes
Set<String> idxNames = new HashSet<String>();
boolean foundPk = false;
for(IndexBuilder index : _indexes) {
- index.validate(colNames);
+ index.validate(colNames, getFormat());
if(!idxNames.add(index.getName().toUpperCase())) {
throw new IllegalArgumentException("duplicate index name: " +
index.getName());
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java b/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java
index ebeb480..4899d38 100644
--- a/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java
+++ b/src/main/java/com/healthmarketscience/jackcess/util/ImportUtil.java
@@ -47,6 +47,7 @@ import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.TableBuilder;
import com.healthmarketscience.jackcess.impl.ByteUtil;
+import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -451,7 +452,7 @@ public class ImportUtil
throws IOException
{
String line = in.readLine();
- if (line == null || line.trim().length() == 0) {
+ if(DatabaseImpl.isBlank(line)) {
return null;
}