Browse Source

Increased the capabilities of the service validation functions.

qdn
CalDescent 3 years ago
parent
commit
57e82b62a1
  1. 6
      src/main/java/org/qortal/arbitrary/ArbitraryDataReader.java
  2. 6
      src/main/java/org/qortal/arbitrary/ArbitraryDataWriter.java
  3. 18
      src/main/java/org/qortal/arbitrary/misc/Service.java
  4. 78
      src/test/java/org/qortal/test/arbitrary/ArbitraryServiceTests.java

6
src/main/java/org/qortal/arbitrary/ArbitraryDataReader.java

@ -444,11 +444,7 @@ public class ArbitraryDataReader {
private void validate() throws IOException, DataException {
if (this.service.isValidationRequired()) {
byte[] data = FilesystemUtils.getSingleFileContents(this.filePath);
long size = FilesystemUtils.getDirectorySize(this.filePath);
Service.ValidationResult result = this.service.validate(data, size);
Service.ValidationResult result = this.service.validate(this.filePath);
if (result != Service.ValidationResult.OK) {
throw new DataException(String.format("Validation of %s failed: %s", this.service, result.toString()));
}

6
src/main/java/org/qortal/arbitrary/ArbitraryDataWriter.java

@ -105,11 +105,7 @@ public class ArbitraryDataWriter {
private void validateService() throws IOException, DataException {
if (this.service.isValidationRequired()) {
byte[] data = FilesystemUtils.getSingleFileContents(this.filePath);
long size = FilesystemUtils.getDirectorySize(this.filePath);
Service.ValidationResult result = this.service.validate(data, size);
Service.ValidationResult result = this.service.validate(this.filePath);
if (result != Service.ValidationResult.OK) {
throw new DataException(String.format("Validation of %s failed: %s", this.service, result.toString()));
}

18
src/main/java/org/qortal/arbitrary/misc/Service.java

@ -1,8 +1,13 @@
package org.qortal.arbitrary.misc;
import org.json.JSONObject;
import org.qortal.arbitrary.ArbitraryDataRenderer;
import org.qortal.transaction.Transaction;
import org.qortal.utils.FilesystemUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -44,20 +49,26 @@ public enum Service {
this.requiredKeys = requiredKeys;
}
public ValidationResult validate(byte[] data, long size) {
public ValidationResult validate(Path path) throws IOException {
if (!this.isValidationRequired()) {
return ValidationResult.OK;
}
byte[] data = FilesystemUtils.getSingleFileContents(path);
long size = FilesystemUtils.getDirectorySize(path);
// Validate max size if needed
if (this.maxSize != null) {
if (size > this.maxSize || data.length > this.maxSize) {
if (size > this.maxSize) {
return ValidationResult.EXCEEDS_SIZE_LIMIT;
}
}
// Validate required keys if needed
if (this.requiredKeys != null) {
if (data == null) {
return ValidationResult.MISSING_KEYS;
}
JSONObject json = Service.toJsonObject(data);
for (String key : this.requiredKeys) {
if (!json.has(key)) {
@ -86,7 +97,8 @@ public enum Service {
public enum ValidationResult {
OK(1),
MISSING_KEYS(2),
EXCEEDS_SIZE_LIMIT(3);
EXCEEDS_SIZE_LIMIT(3),
MISSING_INDEX_FILE(4);
public final int value;

78
src/test/java/org/qortal/test/arbitrary/ArbitraryServiceTests.java

@ -7,6 +7,11 @@ import org.qortal.arbitrary.misc.Service.ValidationResult;
import org.qortal.repository.DataException;
import org.qortal.test.common.Common;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Random;
import static org.junit.Assert.*;
@ -19,49 +24,94 @@ public class ArbitraryServiceTests extends Common {
}
@Test
public void testDefaultValidation() {
// We don't validate websites yet, but we still want to test the default validation method
public void testDefaultValidation() throws IOException {
// We don't validate the ARBITRARY_DATA service specifically, so we can use it to test the default validation method
byte[] data = new byte[1024];
new Random().nextBytes(data);
Service service = Service.WEBSITE;
// Write to temp path
Path path = Files.createTempFile("testDefaultValidation", null);
path.toFile().deleteOnExit();
Files.write(path, data, StandardOpenOption.CREATE);
Service service = Service.ARBITRARY_DATA;
assertFalse(service.isValidationRequired());
// Test validation anyway to ensure that no exception is thrown
assertEquals(ValidationResult.OK, service.validate(data, data.length));
assertEquals(ValidationResult.OK, service.validate(path));
}
@Test
public void testValidQortalMetadata() {
public void testValidQortalMetadata() throws IOException {
// Metadata is to describe an arbitrary resource (title, description, tags, etc)
String dataString = "{\"title\":\"Test Title\", \"description\":\"Test description\", \"tags\":[\"test\"]}";
byte[] data = dataString.getBytes();
// Write to temp path
Path path = Files.createTempFile("testValidQortalMetadata", null);
path.toFile().deleteOnExit();
Files.write(path, dataString.getBytes(), StandardOpenOption.CREATE);
Service service = Service.QORTAL_METADATA;
assertTrue(service.isValidationRequired());
assertEquals(ValidationResult.OK, service.validate(data, data.length));
assertEquals(ValidationResult.OK, service.validate(path));
}
@Test
public void testQortalMetadataMissingKeys() {
public void testQortalMetadataMissingKeys() throws IOException {
// Metadata is to describe an arbitrary resource (title, description, tags, etc)
String dataString = "{\"description\":\"Test description\", \"tags\":[\"test\"]}";
byte[] data = dataString.getBytes();
// Write to temp path
Path path = Files.createTempFile("testQortalMetadataMissingKeys", null);
path.toFile().deleteOnExit();
Files.write(path, dataString.getBytes(), StandardOpenOption.CREATE);
Service service = Service.QORTAL_METADATA;
assertTrue(service.isValidationRequired());
assertEquals(ValidationResult.MISSING_KEYS, service.validate(path));
}
@Test
public void testQortalMetadataTooLarge() throws IOException {
// Metadata is to describe an arbitrary resource (title, description, tags, etc)
String dataString = "{\"title\":\"Test Title\", \"description\":\"Test description\", \"tags\":[\"test\"]}";
// Generate some large data to go along with it
int largeDataSize = 11*1024; // Larger than allowed 10kiB
byte[] largeData = new byte[largeDataSize];
new Random().nextBytes(largeData);
// Write to temp path
Path path = Files.createTempDirectory("testQortalMetadataTooLarge");
path.toFile().deleteOnExit();
Files.write(Paths.get(path.toString(), "data"), dataString.getBytes(), StandardOpenOption.CREATE);
Files.write(Paths.get(path.toString(), "large_data"), largeData, StandardOpenOption.CREATE);
Service service = Service.QORTAL_METADATA;
assertTrue(service.isValidationRequired());
assertEquals(ValidationResult.MISSING_KEYS, service.validate(data, data.length));
assertEquals(ValidationResult.EXCEEDS_SIZE_LIMIT, service.validate(path));
}
@Test
public void testQortalMetadataTooLarge() {
public void testMultipleFileMetadata() throws IOException {
// Metadata is to describe an arbitrary resource (title, description, tags, etc)
String dataString = "{\"title\":\"Test Title\", \"description\":\"Test description\", \"tags\":[\"test\"]}";
byte[] data = dataString.getBytes();
long totalResourceSize = 11*1024L; // Larger than allowed 10kiB
// Generate some large data to go along with it
int otherDataSize = 1024; // Smaller than 10kiB limit
byte[] otherData = new byte[otherDataSize];
new Random().nextBytes(otherData);
// Write to temp path
Path path = Files.createTempDirectory("testMultipleFileMetadata");
path.toFile().deleteOnExit();
Files.write(Paths.get(path.toString(), "data"), dataString.getBytes(), StandardOpenOption.CREATE);
Files.write(Paths.get(path.toString(), "other_data"), otherData, StandardOpenOption.CREATE);
Service service = Service.QORTAL_METADATA;
assertTrue(service.isValidationRequired());
assertEquals(ValidationResult.EXCEEDS_SIZE_LIMIT, service.validate(data, totalResourceSize));
// There are multiple files, so we don't know which one to parse as JSON
assertEquals(ValidationResult.MISSING_KEYS, service.validate(path));
}
}

Loading…
Cancel
Save