From ac60ef30a3a40d503c2c746b1ce2285319a5c6b0 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sun, 5 Mar 2023 10:51:26 +0000 Subject: [PATCH] Added JSON service, with a maximum size of 25KB, and a requirement that the data must be valid JSON. --- .../org/qortal/arbitrary/misc/Service.java | 34 ++++++++++++- .../test/arbitrary/ArbitraryServiceTests.java | 49 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/qortal/arbitrary/misc/Service.java b/src/main/java/org/qortal/arbitrary/misc/Service.java index 5ea1b7aa..3a549180 100644 --- a/src/main/java/org/qortal/arbitrary/misc/Service.java +++ b/src/main/java/org/qortal/arbitrary/misc/Service.java @@ -8,10 +8,13 @@ import org.qortal.utils.FilesystemUtils; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; +import com.fasterxml.jackson.databind.ObjectMapper; + import static java.util.Arrays.stream; import static java.util.stream.Collectors.toMap; @@ -94,6 +97,31 @@ public enum Service { PLAYLIST(910, true, null, null), APP(1000, false, null, null), METADATA(1100, false, null, null), + JSON(1110, true, 25*1024L, null) { + @Override + public ValidationResult validate(Path path) throws IOException { + ValidationResult superclassResult = super.validate(path); + if (superclassResult != ValidationResult.OK) { + return superclassResult; + } + + File[] files = path.toFile().listFiles(); + + // Require a single file + if (files != null || !path.toFile().isFile()) { + return ValidationResult.INVALID_FILE_COUNT; + } + + // Require valid JSON + String json = Files.readString(path); + try { + objectMapper.readTree(json); + return ValidationResult.OK; + } catch (IOException e) { + return ValidationResult.INVALID_CONTENT; + } + } + }, GIF_REPOSITORY(1200, true, 25*1024*1024L, null) { @Override public ValidationResult validate(Path path) throws IOException { @@ -139,6 +167,9 @@ public enum Service { private static final Map map = stream(Service.values()) .collect(toMap(service -> service.value, service -> service)); + // For JSON validation + private static final ObjectMapper objectMapper = new ObjectMapper(); + Service(int value, boolean requiresValidation, Long maxSize, List requiredKeys) { this.value = value; this.requiresValidation = requiresValidation; @@ -199,7 +230,8 @@ public enum Service { DIRECTORIES_NOT_ALLOWED(5), INVALID_FILE_EXTENSION(6), MISSING_DATA(7), - INVALID_FILE_COUNT(8); + INVALID_FILE_COUNT(8), + INVALID_CONTENT(9); public final int value; diff --git a/src/test/java/org/qortal/test/arbitrary/ArbitraryServiceTests.java b/src/test/java/org/qortal/test/arbitrary/ArbitraryServiceTests.java index 96843876..8978a3df 100644 --- a/src/test/java/org/qortal/test/arbitrary/ArbitraryServiceTests.java +++ b/src/test/java/org/qortal/test/arbitrary/ArbitraryServiceTests.java @@ -22,6 +22,8 @@ import org.qortal.test.common.transaction.TestTransaction; import org.qortal.transaction.RegisterNameTransaction; import org.qortal.utils.Base58; +import java.io.BufferedWriter; +import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -389,4 +391,51 @@ public class ArbitraryServiceTests extends Common { } } + @Test + public void testValidateValidJson() throws IOException { + String invalidJsonString = "{\"test\": true, \"test2\": \"valid\"}"; + + // Write the data a single file in a temp path + Path path = Files.createTempDirectory("testValidateValidJson"); + Path filePath = Paths.get(path.toString(), "test.json"); + filePath.toFile().deleteOnExit(); + + BufferedWriter writer = new BufferedWriter(new FileWriter(filePath.toFile())); + writer.write(invalidJsonString); + writer.close(); + + Service service = Service.JSON; + assertTrue(service.isValidationRequired()); + + assertEquals(ValidationResult.OK, service.validate(filePath)); + } + @Test + public void testValidateInvalidJson() throws IOException { + String invalidJsonString = "{\"test\": true, \"test2\": invalid}"; + + // Write the data a single file in a temp path + Path path = Files.createTempDirectory("testValidateInvalidJson"); + Path filePath = Paths.get(path.toString(), "test.json"); + filePath.toFile().deleteOnExit(); + + BufferedWriter writer = new BufferedWriter(new FileWriter(filePath.toFile())); + writer.write(invalidJsonString); + writer.close(); + + Service service = Service.JSON; + assertTrue(service.isValidationRequired()); + + assertEquals(ValidationResult.INVALID_CONTENT, service.validate(filePath)); + } + + @Test + public void testValidateEmptyJson() throws IOException { + Path path = Files.createTempDirectory("testValidateEmptyJson"); + + Service service = Service.JSON; + assertTrue(service.isValidationRequired()); + + assertEquals(ValidationResult.INVALID_FILE_COUNT, service.validate(path)); + } + } \ No newline at end of file