diff --git a/CloudObjects/SDK/COIDParser.php b/CloudObjects/SDK/COIDParser.php index 45de308..32b88b8 100644 --- a/CloudObjects/SDK/COIDParser.php +++ b/CloudObjects/SDK/COIDParser.php @@ -36,7 +36,11 @@ class COIDParser { (strtolower(substr($coidString, 0, 7)) == 'coid://') ? $coidString : 'coid://'.$coidString ); // Normalize scheme and host segments to lower case - return new IRI('coid://'.strtolower($coidPre->getHost()).$coidPre->getPath()); + // Keep query and fragment (will currently make those IRIs invalid as COIDs + // but may be used in future) + return new IRI('coid://'.strtolower($coidPre->getHost()).$coidPre->getPath() + .($coidPre->getQuery() !== null ? '?'.$coidPre->getQuery() : '') + .($coidPre->getFragment() !== null ? '#'.$coidPre->getFragment() : '')); } /** @@ -47,7 +51,8 @@ class COIDParser { */ public static function getType(IRI $coid) : ?int { if ($coid->getScheme()!='coid' || $coid->getHost()=='' - || preg_match(self::REGEX_HOSTNAME, $coid->getHost()) != 1) + || preg_match(self::REGEX_HOSTNAME, $coid->getHost()) !== 1 + || $coid->getQuery() !== null || $coid->getFragment() !== null) return self::COID_INVALID; if ($coid->getPath()=='' || $coid->getPath()=='/') @@ -55,10 +60,10 @@ class COIDParser { $segments = explode('/', $coid->getPath()); switch (count($segments)) { - case 2: - return (preg_match(self::REGEX_SEGMENT, $segments[1]) == 1) - ? self::COID_UNVERSIONED - : self::COID_INVALID; + case 2: + return (preg_match(self::REGEX_SEGMENT, $segments[1]) == 1) + ? self::COID_UNVERSIONED + : self::COID_INVALID; case 3: if (preg_match(self::REGEX_SEGMENT, $segments[1]) != 1) return self::COID_INVALID; diff --git a/tests/OfflineTests/COIDParserTest.php b/tests/OfflineTests/COIDParserTest.php index e539121..268cf8b 100644 --- a/tests/OfflineTests/COIDParserTest.php +++ b/tests/OfflineTests/COIDParserTest.php @@ -50,6 +50,24 @@ class COIDParserTest extends \PHPUnit\Framework\TestCase { $coid = new IRI('coid://exAMPle.CoM'); $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = new IRI('coid://example.com#hash=something'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = new IRI('coid://example.com?query=something'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = new IRI('coid://example.com/Example/1.0?query=something'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = new IRI('coid://example.com/Example#hash'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = new IRI('coid://example.com?'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = new IRI('coid://example.com#'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); } public function testUnversionedCOID() { @@ -145,4 +163,20 @@ class COIDParserTest extends \PHPUnit\Framework\TestCase { $this->assertFalse($coid1->equals($coid4)); } + public function testQueryAndFragmentFromString() { + $coid = COIDParser::fromString('example.com/Example?query=something'); + $this->assertEquals('coid://example.com/Example?query=something', (string)$coid); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = COIDParser::fromString('COID://Example.com/Example/1.0#hash'); + $this->assertEquals('coid://example.com/Example/1.0#hash', (string)$coid); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = COIDParser::fromString('example.com?'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + + $coid = COIDParser::fromString('example.com#'); + $this->assertEquals(COIDParser::COID_INVALID, COIDParser::getType($coid)); + } + }