Skip to content

Commit 6cb53f2

Browse files
committed
Refactoring
1 parent 37f2714 commit 6cb53f2

9 files changed

Lines changed: 129 additions & 52 deletions

File tree

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vipnytt/cleanparam-url-filter",
33
"description": "Clean-Param URL filtering class - Find and remove any duplicate URL",
4-
"version": "0.1-beta",
4+
"version": "0.1",
55
"keywords": [
66
"Clean-Param",
77
"CleanParam",
@@ -35,8 +35,8 @@
3535
}
3636
],
3737
"autoload": {
38-
"classmap": [
39-
"source/CleanParamFilter.php"
40-
]
38+
"psr-4": {
39+
"vipnytt\\": "src/"
40+
}
4141
}
4242
}

phpunit.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
<phpunit bootstrap="test/bootstrap.php">
33
<filter>
44
<whitelist>
5-
<directory>source</directory>
5+
<directory>src</directory>
66
</whitelist>
77
</filter>
88
<logging>
99
<log type="coverage-clover" target="build/logs/clover.xml"/>
1010
</logging>
1111
<testsuites>
1212
<testsuite name="">
13-
<directory>test</directory>
13+
<directory>test/cases</directory>
1414
</testsuite>
1515
</testsuites>
1616
</phpunit>
Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
namespace vipnytt;
1717

18+
use vipnytt\CleanParamFilter\URLParser;
19+
1820
class CleanParamFilter
1921
{
2022
// Clean-Param set
@@ -43,53 +45,16 @@ public function __construct($urls)
4345
// Parse URLs
4446
sort($urls);
4547
foreach ($urls as $url) {
46-
$url = $this->urlEncode($url);
47-
$parsed = parse_url($url);
48-
if ($parsed === false
49-
|| !isset($parsed['scheme'])
50-
|| !isset($parsed['host'])
51-
) {
48+
$urlParser = new URLParser(trim($url));
49+
if (!$urlParser->isValid()) {
5250
$this->invalid[] = $url;
5351
continue;
5452
}
55-
$this->urls[$parsed['host']][] = $url;
53+
$url = $urlParser->encode();
54+
$this->urls[parse_url($url, PHP_URL_HOST)][] = $url;
5655
}
5756
}
5857

59-
/**
60-
* URL encoder according to RFC 3986
61-
* Returns a string containing the encoded URL with disallowed characters converted to their percentage encodings.
62-
* @link http://publicmind.in/blog/url-encoding/
63-
*
64-
* @param string $url
65-
* @return string
66-
*/
67-
private static function urlEncode($url)
68-
{
69-
$reserved = array(
70-
":" => '!%3A!ui',
71-
"/" => '!%2F!ui',
72-
"?" => '!%3F!ui',
73-
"#" => '!%23!ui',
74-
"[" => '!%5B!ui',
75-
"]" => '!%5D!ui',
76-
"@" => '!%40!ui',
77-
"!" => '!%21!ui',
78-
"$" => '!%24!ui',
79-
"&" => '!%26!ui',
80-
"'" => '!%27!ui',
81-
"(" => '!%28!ui',
82-
")" => '!%29!ui',
83-
"*" => '!%2A!ui',
84-
"+" => '!%2B!ui',
85-
"," => '!%2C!ui',
86-
";" => '!%3B!ui',
87-
"=" => '!%3D!ui',
88-
"%" => '!%25!ui'
89-
);
90-
return preg_replace(array_values($reserved), array_keys($reserved), rawurlencode($url));
91-
}
92-
9358
/**
9459
* Lists all approved URLs
9560
*
@@ -255,7 +220,8 @@ private function findCleanParam($url, $host)
255220
*/
256221
private function checkPath($path, $prefix)
257222
{
258-
$path = $this->urlEncode($path);
223+
$pathParser = new URLParser($path);
224+
$path = $pathParser->encode();
259225
// change @ to \@
260226
$escaped = strtr($path, ["@" => '\@']);
261227
// match result
@@ -354,10 +320,11 @@ public function addCleanParam($param, $path = '/', $host = null)
354320
// use host from URLs
355321
$host = key($this->urls);
356322
}
357-
$encodedURL = $this->urlEncode($path);
323+
$urlParser = new URLParser($path);
324+
$encodedPath = $urlParser->encode();
358325
$paramArray = explode('&', $param);
359326
foreach ($paramArray as $parameter) {
360-
$this->cleanParam[$host][$encodedURL][$parameter] = $parameter;
327+
$this->cleanParam[$host][$encodedPath][$parameter] = $parameter;
361328
}
362329
$this->filtered = false;
363330
}

src/robot/URLParser.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
/**
3+
* URL parser
4+
*
5+
* @author Jan-Petter Gundersen (europe.jpg@gmail.com)
6+
*/
7+
8+
namespace vipnytt\CleanParamFilter;
9+
10+
final class URLParser
11+
{
12+
private $url;
13+
14+
/**
15+
* Constructor
16+
*
17+
* @param string $url
18+
*/
19+
public function __construct($url)
20+
{
21+
$this->url = $url;
22+
}
23+
24+
/**
25+
* Validate URL
26+
*
27+
* @return bool
28+
*/
29+
public function isValid()
30+
{
31+
$this->encode();
32+
$parsed = parse_url($this->url);
33+
if ($parsed === false
34+
|| !$this->isHostValid()
35+
|| !$this->isSchemeValid()
36+
) {
37+
return false;
38+
}
39+
return true;
40+
}
41+
42+
/**
43+
* URL encoder according to RFC 3986
44+
* Returns a string containing the encoded URL with disallowed characters converted to their percentage encodings.
45+
* @link http://publicmind.in/blog/url-encoding/
46+
*
47+
* @return string string
48+
*/
49+
public function encode()
50+
{
51+
$reserved = [
52+
":" => '!%3A!ui',
53+
"/" => '!%2F!ui',
54+
"?" => '!%3F!ui',
55+
"#" => '!%23!ui',
56+
"[" => '!%5B!ui',
57+
"]" => '!%5D!ui',
58+
"@" => '!%40!ui',
59+
"!" => '!%21!ui',
60+
"$" => '!%24!ui',
61+
"&" => '!%26!ui',
62+
"'" => '!%27!ui',
63+
"(" => '!%28!ui',
64+
")" => '!%29!ui',
65+
"*" => '!%2A!ui',
66+
"+" => '!%2B!ui',
67+
"," => '!%2C!ui',
68+
";" => '!%3B!ui',
69+
"=" => '!%3D!ui',
70+
"%" => '!%25!ui'
71+
];
72+
return $this->url = preg_replace(array_values($reserved), array_keys($reserved), rawurlencode($this->url));
73+
}
74+
75+
/**
76+
* Validate host name
77+
*
78+
* @link http://stackoverflow.com/questions/1755144/how-to-validate-domain-name-in-php
79+
* @return bool
80+
*/
81+
public function isHostValid()
82+
{
83+
$host = parse_url($this->url, PHP_URL_HOST);
84+
return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $host) //valid chars check
85+
&& preg_match("/^.{1,253}$/", $host) //overall length check
86+
&& preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $host) //length of each label
87+
&& !filter_var($host, FILTER_VALIDATE_IP)); //is not an IP address
88+
}
89+
90+
/**
91+
* Validate URL scheme
92+
*
93+
* @return bool
94+
*/
95+
public function isSchemeValid()
96+
{
97+
return in_array(parse_url($this->url, PHP_URL_SCHEME), [
98+
'http', 'https',
99+
'ftp', 'sftp'
100+
]);
101+
}
102+
}

test/bootstrap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<?php
2-
require_once(dirname(__FILE__) . "/../source/CleanParamFilter.php");
2+
require_once(dirname(__FILE__) . "/../vendor/autoload.php");
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
namespace vipnytt\CleanParamFilter\tests;
4+
35
use vipnytt\CleanParamFilter;
46

57
class CleanParamTest extends \PHPUnit_Framework_TestCase
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
namespace vipnytt\CleanParamFilter\tests;
4+
35
use vipnytt\CleanParamFilter;
46

57
class InvalidURLTest extends \PHPUnit_Framework_TestCase
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
namespace vipnytt\CleanParamFilter\tests;
4+
35
use vipnytt\CleanParamFilter;
46

57
class MultiHostTest extends \PHPUnit_Framework_TestCase
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
namespace vipnytt\CleanParamFilter\tests;
4+
35
use vipnytt\CleanParamFilter;
46

57
class UndefinedHostTest extends \PHPUnit_Framework_TestCase
@@ -9,7 +11,7 @@ class UndefinedHostTest extends \PHPUnit_Framework_TestCase
911
*
1012
* @dataProvider generateDataForTest
1113
* @param array $urls
12-
* @expectedException PHPUnit_Framework_Error_WARNING
14+
* @expectedException \PHPUnit_Framework_Error_WARNING
1315
* @return void
1416
*/
1517
public function testUndefinedHost($urls)

0 commit comments

Comments
 (0)