diff --git a/src/main/java/com/networknt/schema/AbsoluteIri.java b/src/main/java/com/networknt/schema/AbsoluteIri.java index 687455b0e..d8f793e64 100644 --- a/src/main/java/com/networknt/schema/AbsoluteIri.java +++ b/src/main/java/com/networknt/schema/AbsoluteIri.java @@ -106,11 +106,21 @@ public static String resolve(String parent, String iri) { scheme = scheme + 3; } base = parent(base, scheme); - while (iri.startsWith("../")) { - base = parent(base, scheme); - iri = iri.substring(3); + + String[] iriParts = iri.split("/"); + for (int x = 0; x < iriParts.length; x++) { + if ("..".equals(iriParts[x])) { + base = parent(base, scheme); + } else if (".".equals(iriParts[x])) { + // skip + } else { + base = base + "/" + iriParts[x]; + } + } + if (iri.endsWith("/")) { + base = base + "/"; } - return base + "/" + iri; + return base; } } } diff --git a/src/test/java/com/networknt/schema/RefValidatorTest.java b/src/test/java/com/networknt/schema/RefValidatorTest.java new file mode 100644 index 000000000..26308799d --- /dev/null +++ b/src/test/java/com/networknt/schema/RefValidatorTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.networknt.schema; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Collections; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import com.networknt.schema.SpecVersion.VersionFlag; + +/** + * Tests for RefValidator. + */ +public class RefValidatorTest { + @Test + void resolveSamePathDotSlash() { + String mainSchema = "{\r\n" + + " \"$id\": \"https://www.example.com/schema/test.json\",\r\n" + + " \"$ref\": \"./integer.json\"\r\n" + + "}"; + + String otherSchema = "{\r\n" + + " \"type\": \"integer\"\r\n" + + "}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012, + builder -> builder.schemaLoaders(schemaLoaders -> schemaLoaders.schemas( + Collections.singletonMap("https://www.example.com/schema/integer.json", otherSchema)))); + JsonSchema jsonSchema = factory.getSchema(mainSchema); + Set messages = jsonSchema.validate("\"string\"", InputFormat.JSON); + assertEquals(1, messages.size()); + } + + @Test + void resolveSamePath() { + String mainSchema = "{\r\n" + + " \"$id\": \"https://www.example.com/schema/test.json\",\r\n" + + " \"$ref\": \"integer.json\"\r\n" + + "}"; + + String otherSchema = "{\r\n" + + " \"type\": \"integer\"\r\n" + + "}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012, + builder -> builder.schemaLoaders(schemaLoaders -> schemaLoaders.schemas( + Collections.singletonMap("https://www.example.com/schema/integer.json", otherSchema)))); + JsonSchema jsonSchema = factory.getSchema(mainSchema); + Set messages = jsonSchema.validate("\"string\"", InputFormat.JSON); + assertEquals(1, messages.size()); + } + + @Test + void resolveParent() { + String mainSchema = "{\r\n" + + " \"$id\": \"https://www.example.com/schema/test.json\",\r\n" + + " \"$ref\": \"../integer.json\"\r\n" + + "}"; + + String otherSchema = "{\r\n" + + " \"type\": \"integer\"\r\n" + + "}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012, + builder -> builder.schemaLoaders(schemaLoaders -> schemaLoaders.schemas( + Collections.singletonMap("https://www.example.com/integer.json", otherSchema)))); + JsonSchema jsonSchema = factory.getSchema(mainSchema); + Set messages = jsonSchema.validate("\"string\"", InputFormat.JSON); + assertEquals(1, messages.size()); + } + + @Test + void resolveComplex() { + String mainSchema = "{\r\n" + + " \"$id\": \"https://www.example.com/schema/test.json\",\r\n" + + " \"$ref\": \"./hello/././world/../integer.json\"\r\n" + + "}"; + + String otherSchema = "{\r\n" + + " \"type\": \"integer\"\r\n" + + "}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012, + builder -> builder.schemaLoaders(schemaLoaders -> schemaLoaders.schemas( + Collections.singletonMap("https://www.example.com/schema/hello/integer.json", otherSchema)))); + JsonSchema jsonSchema = factory.getSchema(mainSchema); + Set messages = jsonSchema.validate("\"string\"", InputFormat.JSON); + assertEquals(1, messages.size()); + } +}