mirror of https://github.com/nextcloud/bookmarks
Re-implement url normalizer based on python implementation
This commit is contained in:
parent
281a07979e
commit
3d9c8d256d
|
@ -6,7 +6,6 @@
|
|||
"pguardiario/phpuri": "1.0.*",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-client": "^0.2.0",
|
||||
"webignition/url": "^2.2"
|
||||
"psr/http-client": "^0.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae",
|
||||
"url":
|
||||
"https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae",
|
||||
"reference": "90b2128806bfde671b6952ab8bea493942c1fdae",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -38,9 +39,7 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
|
@ -63,14 +62,10 @@
|
|||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Common String Manipulations with regard to casing and singular/plural rules.",
|
||||
"description":
|
||||
"Common String Manipulations with regard to casing and singular/plural rules.",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"inflection",
|
||||
"pluralize",
|
||||
"singularize",
|
||||
"string"
|
||||
],
|
||||
"keywords": ["inflection", "pluralize", "singularize", "string"],
|
||||
"time": "2015-11-06T14:35:42+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -83,7 +78,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/etechnika/idna-convert/zipball/85e488474269b19630ca4e711061e4aa61ac879a",
|
||||
"url":
|
||||
"https://api.github.com/repos/etechnika/idna-convert/zipball/85e488474269b19630ca4e711061e4aa61ac879a",
|
||||
"reference": "85e488474269b19630ca4e711061e4aa61ac879a",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -109,9 +105,7 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1"
|
||||
],
|
||||
"license": ["LGPL-2.1"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tomasz Rutkowski",
|
||||
|
@ -122,9 +116,7 @@
|
|||
],
|
||||
"description": "Etechnika.eu idna-convert",
|
||||
"homepage": "https://github.com/etechnika/idna-convert",
|
||||
"keywords": [
|
||||
"lib"
|
||||
],
|
||||
"keywords": ["lib"],
|
||||
"time": "2014-02-15T12:42:32+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -137,7 +129,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
||||
"url":
|
||||
"https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
||||
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -161,14 +154,10 @@
|
|||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
"files": ["src/functions_include.php"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
|
@ -180,7 +169,8 @@
|
|||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||
"description":
|
||||
"PSR-7 message implementation that also provides common utility methods",
|
||||
"keywords": [
|
||||
"http",
|
||||
"message",
|
||||
|
@ -202,7 +192,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/contracts/zipball/67f642e018f3e95fb0b2ebffc206c3200391b1ab",
|
||||
"url":
|
||||
"https://api.github.com/repos/illuminate/contracts/zipball/67f642e018f3e95fb0b2ebffc206c3200391b1ab",
|
||||
"reference": "67f642e018f3e95fb0b2ebffc206c3200391b1ab",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -221,9 +212,7 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
|
@ -244,7 +233,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/support/zipball/feab1d1495fd6d38970bd6c83586ba2ace8f299a",
|
||||
"url":
|
||||
"https://api.github.com/repos/illuminate/support/zipball/feab1d1495fd6d38970bd6c83586ba2ace8f299a",
|
||||
"reference": "feab1d1495fd6d38970bd6c83586ba2ace8f299a",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -273,14 +263,10 @@
|
|||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
},
|
||||
"files": [
|
||||
"helpers.php"
|
||||
]
|
||||
"files": ["helpers.php"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
|
@ -301,7 +287,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/marcelklehr/link-preview/zipball/2b79492e2cba41f0464265c09b93263c0276fc07",
|
||||
"url":
|
||||
"https://api.github.com/repos/marcelklehr/link-preview/zipball/2b79492e2cba41f0464265c09b93263c0276fc07",
|
||||
"reference": "2b79492e2cba41f0464265c09b93263c0276fc07",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -324,9 +311,7 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Denis Mysenko",
|
||||
|
@ -336,13 +321,7 @@
|
|||
],
|
||||
"description": "Link preview generation for PHP with Laravel support",
|
||||
"homepage": "http://github.com/marcelklehr/link-preview",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"php",
|
||||
"preview",
|
||||
"scraping",
|
||||
"url"
|
||||
],
|
||||
"keywords": ["laravel", "php", "preview", "scraping", "url"],
|
||||
"time": "2018-09-01T21:10:51+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -355,7 +334,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d",
|
||||
"url":
|
||||
"https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d",
|
||||
"reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -366,18 +346,15 @@
|
|||
"phpunit/phpunit": "4.*|5.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||
"ext-libsodium":
|
||||
"Provides a modern crypto API that can be used to generate random bytes."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/random.php"
|
||||
]
|
||||
"files": ["lib/random.php"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
|
@ -385,13 +362,9 @@
|
|||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||
"keywords": [
|
||||
"csprng",
|
||||
"polyfill",
|
||||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"description":
|
||||
"PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||
"keywords": ["csprng", "polyfill", "pseudorandom", "random"],
|
||||
"time": "2018-07-04T16:31:37+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -404,15 +377,14 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/monkeysuffrage/phpuri/zipball/ad0a5ec033fe616cfef55578b9c7f2458be8fbfc",
|
||||
"url":
|
||||
"https://api.github.com/repos/monkeysuffrage/phpuri/zipball/ad0a5ec033fe616cfef55578b9c7f2458be8fbfc",
|
||||
"reference": "ad0a5ec033fe616cfef55578b9c7f2458be8fbfc",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "project",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"phpuri.php"
|
||||
]
|
||||
"files": ["phpuri.php"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"description": "A php library for converting relative urls to absolute.",
|
||||
|
@ -428,7 +400,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-client/zipball/82cf0dd2052a44cab9ea400e61ea7c3f5fdc0f8f",
|
||||
"url":
|
||||
"https://api.github.com/repos/php-fig/http-client/zipball/82cf0dd2052a44cab9ea400e61ea7c3f5fdc0f8f",
|
||||
"reference": "82cf0dd2052a44cab9ea400e61ea7c3f5fdc0f8f",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -448,9 +421,7 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
|
@ -459,12 +430,7 @@
|
|||
],
|
||||
"description": "Common interface for HTTP clients",
|
||||
"homepage": "https://github.com/php-fig/http-client",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-client",
|
||||
"psr",
|
||||
"psr-18"
|
||||
],
|
||||
"keywords": ["http", "http-client", "psr", "psr-18"],
|
||||
"time": "2018-08-14T08:56:48+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -477,7 +443,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/378bfe27931ecc54ff824a20d6f6bfc303bbd04c",
|
||||
"url":
|
||||
"https://api.github.com/repos/php-fig/http-factory/zipball/378bfe27931ecc54ff824a20d6f6bfc303bbd04c",
|
||||
"reference": "378bfe27931ecc54ff824a20d6f6bfc303bbd04c",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -497,9 +464,7 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
|
@ -529,7 +494,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"url":
|
||||
"https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -548,9 +514,7 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
|
@ -579,7 +543,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
|
||||
"url":
|
||||
"https://api.github.com/repos/symfony/css-selector/zipball/3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
|
||||
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -596,14 +561,10 @@
|
|||
"psr-4": {
|
||||
"Symfony\\Component\\CssSelector\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
"exclude-from-classmap": ["/Tests/"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jean-François Simon",
|
||||
|
@ -632,7 +593,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/c705bee03ade5b47c087807dd9ffaaec8dda2722",
|
||||
"url":
|
||||
"https://api.github.com/repos/symfony/dom-crawler/zipball/c705bee03ade5b47c087807dd9ffaaec8dda2722",
|
||||
"reference": "c705bee03ade5b47c087807dd9ffaaec8dda2722",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -657,14 +619,10 @@
|
|||
"psr-4": {
|
||||
"Symfony\\Component\\DomCrawler\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
"exclude-from-classmap": ["/Tests/"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
|
@ -689,7 +647,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
|
||||
"url":
|
||||
"https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
|
||||
"reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -709,14 +668,10 @@
|
|||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
"files": ["bootstrap.php"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
|
@ -729,12 +684,7 @@
|
|||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"ctype",
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"keywords": ["compatibility", "ctype", "polyfill", "portable"],
|
||||
"time": "2018-08-06T14:22:27+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -747,7 +697,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"url":
|
||||
"https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -767,14 +718,10 @@
|
|||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
"files": ["bootstrap.php"]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
|
@ -787,64 +734,9 @@
|
|||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"keywords": ["compatibility", "mbstring", "polyfill", "portable", "shim"],
|
||||
"time": "2018-09-21T13:07:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webignition/url",
|
||||
"version": "2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webignition/url.git",
|
||||
"reference": "d26f181c8766574c3c9e4e22b19479a4a637dde0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webignition/url/zipball/d26f181c8766574c3c9e4e22b19479a4a637dde0",
|
||||
"reference": "d26f181c8766574c3c9e4e22b19479a4a637dde0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"etechnika/idna-convert": "1.0.*",
|
||||
"php": ">=5.6.0",
|
||||
"xrstf/ip-utils": "v1.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9",
|
||||
"php-mock/php-mock-mockery": "1.1.0",
|
||||
"phpunit/phpunit": "~5.0",
|
||||
"squizlabs/php_codesniffer": "3.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"webignition\\Url\\": "src/Url",
|
||||
"webignition\\NormalisedUrl\\": "src/NormalisedUrl"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jon Cram",
|
||||
"email": "jon@webignition.net"
|
||||
}
|
||||
],
|
||||
"description": "Represents a URL, a library to be used in many other places. Applies semantically-lossless normalisation for comparisons.",
|
||||
"homepage": "https://github.com/webignition/url",
|
||||
"keywords": [
|
||||
"url"
|
||||
],
|
||||
"time": "2018-10-09T17:17:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "xrstf/ip-utils",
|
||||
"version": "v1.0.0",
|
||||
|
@ -855,7 +747,8 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://bitbucket.org/xrstf/ip-utils/get/d7469bb0c407e423c9d1b49ff2e8980c800871e2.zip",
|
||||
"url":
|
||||
"https://bitbucket.org/xrstf/ip-utils/get/d7469bb0c407e423c9d1b49ff2e8980c800871e2.zip",
|
||||
"reference": "d7469bb0c407e423c9d1b49ff2e8980c800871e2",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -874,23 +767,16 @@
|
|||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"license": ["MIT"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christoph Mewes",
|
||||
"homepage": "http://www.xrstf.de/"
|
||||
}
|
||||
],
|
||||
"description": "small library to deal with IPv4 & IPv6 addresses and subnets",
|
||||
"keywords": [
|
||||
"IP",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
"matching",
|
||||
"subnet"
|
||||
],
|
||||
"description":
|
||||
"small library to deal with IPv4 & IPv6 addresses and subnets",
|
||||
"keywords": ["IP", "ipv4", "ipv6", "matching", "subnet"],
|
||||
"time": "2013-02-27T03:27:30+00:00"
|
||||
}
|
||||
],
|
||||
|
|
|
@ -1,11 +1,30 @@
|
|||
<?php
|
||||
namespace OCA\Bookmarks\Controller\Lib;
|
||||
|
||||
use \webignition\NormalisedUrl\NormalisedUrl;
|
||||
|
||||
class UrlNormalizer {
|
||||
private $normalizer;
|
||||
|
||||
|
||||
const SCHEMES = ['http', 'https', 'ftp', 'sftp', 'file', 'gopher', 'imap', 'mms',
|
||||
'news', 'nntp', 'telnet', 'prospero', 'rsync', 'rtsp', 'rtspu',
|
||||
'svn', 'git', 'ws', 'wss'];
|
||||
const SCHEME_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const IP_CHARS = '0123456789.:';
|
||||
const DEFAULT_PORT = [
|
||||
'http'=> '80',
|
||||
'https'=> '443',
|
||||
'ws'=> '80',
|
||||
'wss'=> '443',
|
||||
'ftp'=> '21',
|
||||
'sftp'=> '22',
|
||||
'ldap'=> '389'
|
||||
];
|
||||
const QUOTE_EXCEPTIONS = [
|
||||
'path'=> ' /?+#',
|
||||
'query'=> ' &=+#',
|
||||
'fragment'=> ' +#'
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
$this->normalizer = new NormalisedUrl();
|
||||
}
|
||||
|
@ -16,7 +35,258 @@ class UrlNormalizer {
|
|||
* @return string Normalized url;
|
||||
*/
|
||||
public function normalize($url) {
|
||||
$this->normalizer->init($url);
|
||||
return (string) $this->normalizer;
|
||||
$url = trim($url);
|
||||
if ($url === '') {
|
||||
return '';
|
||||
}
|
||||
$parts = self::split($url);
|
||||
if ($parts['scheme']) {
|
||||
$netloc = $parts['netloc'];
|
||||
if (in_array($parts['scheme'], self::SCHEMES)) {
|
||||
$path = self::normalize_path($parts['path']);
|
||||
} else {
|
||||
$path = $parts['path'];
|
||||
}
|
||||
# url is relative, netloc (if present) is part of path
|
||||
} else {
|
||||
$netloc = $parts['path'];
|
||||
$path = '';
|
||||
if (strpos($netloc, '/') !== false) {
|
||||
$netloc = substr(netloc, 0, strpos($netloc, '/'));
|
||||
$path_raw = substr($netloc, strpos($netloc, '/')+1);
|
||||
$path = self::normalize_path('/' + $path_raw);
|
||||
}
|
||||
}
|
||||
list($username, $password, $host, $port) = self::split_netloc($netloc);
|
||||
$host = self::normalize_host($host);
|
||||
$port = self::normalize_port($parts['scheme'], $port);
|
||||
$query = self::normalize_query($parts['query']);
|
||||
$fragment = self::normalize_fragment($parts['fragment']);
|
||||
return self::construct(['scheme' => $parts['scheme'], 'username' => $username, 'password' => $password, 'host' => $host, 'port' => $port, 'path' => $path, 'query' => $query, 'fragment' => $fragment]);
|
||||
}
|
||||
|
||||
public static function construct($parts) {
|
||||
$url = '';
|
||||
if ($parts['scheme']) {
|
||||
if (in_array($parts['scheme'], self::SCHEMES)) {
|
||||
$url .= $parts['scheme'] . '://';
|
||||
} else {
|
||||
$url .= $parts['scheme'] . ':';
|
||||
}
|
||||
}
|
||||
if ($parts['username'] && $parts['password']) {
|
||||
$url .= $parts['username'] . ':' . $parts['password'] . '@';
|
||||
} elseif ($parts['username']) {
|
||||
$url .= $parts['username'] . '@';
|
||||
}
|
||||
$url .= $parts['host'];
|
||||
if ($parts['port']) {
|
||||
$url .= ':' . $parts['port'];
|
||||
}
|
||||
if ($parts['path']) {
|
||||
$url .= $parts['path'];
|
||||
}
|
||||
if ($parts['query']) {
|
||||
$url .= '?' . $parts['query'];
|
||||
}
|
||||
if ($parts['fragment']) {
|
||||
$url .= '#' . $parts['fragment'];
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
public static function normalize_host($host) {
|
||||
if (strpos($host, 'xn--') === false) {
|
||||
return $host;
|
||||
}
|
||||
return idn_to_ascii($host);
|
||||
}
|
||||
|
||||
public static function normalize_port($scheme, $port) {
|
||||
if (!isset($scheme)) {
|
||||
return $port;
|
||||
}
|
||||
if (isset($port) && $port != self::DEFAULT_PORT[$scheme]) {
|
||||
return $port;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function normalize_path($path) {
|
||||
if (in_array($path, ['//', '/', ''])) {
|
||||
return '/';
|
||||
}
|
||||
$npath = self::get_absolute_path(self::unquote($path, self::QUOTE_EXCEPTIONS['path']));
|
||||
if ($path[count($path)-1] === '/' && $npath != '/') {
|
||||
$npath .= '/';
|
||||
}
|
||||
return $npath;
|
||||
}
|
||||
|
||||
public static function get_absolute_path($path) {
|
||||
$parts = array_filter(explode('/', $path), 'strlen');
|
||||
$absolutes = [];
|
||||
foreach ($parts as $part) {
|
||||
if ('.' == $part) {
|
||||
continue;
|
||||
}
|
||||
if ('..' == $part) {
|
||||
array_pop($absolutes);
|
||||
} else {
|
||||
$absolutes[] = $part;
|
||||
}
|
||||
}
|
||||
return implode('/', $absolutes);
|
||||
}
|
||||
|
||||
public static function normalize_query($query) {
|
||||
if ($query === '' || count($query) <= 2) {
|
||||
return '';
|
||||
}
|
||||
$nquery = self::unquote($query, self::QUOTE_EXCEPTIONS['query']);
|
||||
$params = explode('&', $nquery);
|
||||
$nparams = [];
|
||||
foreach ($params as $param) {
|
||||
if (strpos($param, '=') !== false) {
|
||||
$k = substr($param, 0, strpos($param, '='));
|
||||
$v = substr($param, strpos($param, '=')+1);
|
||||
array_push($nparams, $k.'='.$v);
|
||||
}
|
||||
}
|
||||
sort($nparams);
|
||||
return implode('&', $nparams);
|
||||
}
|
||||
|
||||
public static function normalize_fragment($fragment) {
|
||||
return self::unquote($fragment, self::QUOTE_EXCEPTIONS['fragment']);
|
||||
}
|
||||
|
||||
|
||||
public static function unquote($text, $exceptions=[]) {
|
||||
$_hextochr = [];
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
$_hextochr[dechex($i)] = chr($i);
|
||||
$_hextochr[strtoupper(dechex($i))] = chr($i);
|
||||
}
|
||||
if (strlen($text) == 0) {
|
||||
return $text;
|
||||
}
|
||||
if (!isset($text)) {
|
||||
throw new Exception('text is not set and thus cannot be unquoted');
|
||||
}
|
||||
if (strpos($text, '%') === false) {
|
||||
return $text;
|
||||
}
|
||||
$s = explode('%', $text);
|
||||
$res = $s[0];
|
||||
for ($i=1; $i < count($s); $i++) {
|
||||
$h = $s[$i];
|
||||
$c = _hextochr.get(substr($h, 0, 2));
|
||||
if ($c && false === strpos($exceptions, $c)) {
|
||||
if (strlen(h) > 2) {
|
||||
$res .= $c . substr($h, 2);
|
||||
} else {
|
||||
$res .= $c;
|
||||
}
|
||||
} else {
|
||||
$res .= '%' . $h;
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
public static function split($url) {
|
||||
$scheme = $netloc = $path = $query = $fragment = '';
|
||||
$ip6_start = strpos($url, '[');
|
||||
$scheme_end = strpos($url, ':');
|
||||
if ($ip6_start !== false && $scheme_end !== false && $ip6_start < $scheme_end) {
|
||||
$scheme_end = -1;
|
||||
}
|
||||
if ($scheme_end > 0) {
|
||||
for ($i = 0; $i < $scheme_end; $i++) {
|
||||
$c = $url[$i];
|
||||
if (strpos(self::SCHEME_CHARS, $c) === false) {
|
||||
break;
|
||||
} else {
|
||||
$scheme = strtolower(substr(url, 0, $scheme_end));
|
||||
$rest = ltrim(substr($url, $scheme_end), ':/');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$scheme) {
|
||||
$rest = $url;
|
||||
}
|
||||
$l_path = strpos($rest, '/');
|
||||
$l_query = strpos($rest, '?');
|
||||
$l_frag = strpos($rest, '#');
|
||||
if ($l_path > 0) {
|
||||
if ($l_query > 0 && $l_frag > 0) {
|
||||
$netloc = substr(rest, 0, $l_path);
|
||||
$path = substr($rest, $l_path, min($l_query, $l_frag));
|
||||
} elseif ($l_query > 0) {
|
||||
if ($l_query > $l_path) {
|
||||
$netloc = substr($rest, 0, $l_path);
|
||||
$path = substr($rest, $l_path, $l_query);
|
||||
} else {
|
||||
$netloc = substr($rest, 0, $l_query);
|
||||
$path = '';
|
||||
}
|
||||
} elseif ($l_frag > 0) {
|
||||
$netloc = substr($rest, 0, $l_path);
|
||||
$path = substr($rest, $l_path, $l_frag);
|
||||
} else {
|
||||
$netloc = substr($rest, 0, $l_path);
|
||||
$path = substr($rest, $l_path);
|
||||
}
|
||||
} else {
|
||||
if ($l_query > 0) {
|
||||
$netloc = substr($rest, 0, $l_query);
|
||||
} elseif ($l_frag > 0) {
|
||||
$netloc = substr($rest, 0, $l_frag);
|
||||
} else {
|
||||
$netloc = $rest;
|
||||
}
|
||||
}
|
||||
if ($l_query > 0) {
|
||||
if ($l_frag > 0) {
|
||||
$query = substr($rest, $l_query+1, $l_frag);
|
||||
} else {
|
||||
$query = subtr($rest, $l_query+1);
|
||||
}
|
||||
}
|
||||
if ($l_frag > 0) {
|
||||
$fragment = substr($rest, $l_frag+1);
|
||||
}
|
||||
if (!$scheme) {
|
||||
$path = $netloc . $path;
|
||||
$netloc = '';
|
||||
}
|
||||
return [$scheme, $netloc, $path, $query, $fragment];
|
||||
}
|
||||
|
||||
public static function _clean_netloc($netloc) {
|
||||
return strtolower(rtrim($netloc, '.:'));
|
||||
}
|
||||
|
||||
public static function split_netloc($netloc) {
|
||||
$username = $password = $host = $port = '';
|
||||
if (strpos($netloc, '@') !== false) {
|
||||
$user_pw = substr($netloc, 0, strpos($netloc, '@'));
|
||||
$netloc = substr($netloc, strpos($netloc, '@')+1);
|
||||
if (strpos($user_pw, ':') !== false) {
|
||||
$username = substr($user_pw, 0, strpos($user_pw, ':'));
|
||||
$password = substr($user_pw, strpos($user_pw, ':')+1);
|
||||
} else {
|
||||
$username = $user_pw;
|
||||
}
|
||||
}
|
||||
$netloc = self::_clean_netloc($netloc);
|
||||
if (strpos($netloc, ':') !== false && $netloc[count($netloc)-1] !== ']') {
|
||||
$host = substr($netloc, 0, strpos($netloc, ':'));
|
||||
$port = substr($netloc, strpos($netloc, ':')+1);
|
||||
} else {
|
||||
$host = $netloc;
|
||||
}
|
||||
return [$username, $password, $host, $port];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue