UrlCheckerService   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 56
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 16
c 1
b 0
f 0
dl 0
loc 56
rs 10
wmc 9

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getSafeUrl() 0 3 2
A isSafeUrl() 0 13 4
A __construct() 0 14 3
1
<?php
2
/**
3
 * @copyright Zicht Online <http://www.zicht.nl>
4
 */
5
6
namespace Zicht\Bundle\FrameworkExtraBundle\Url;
7
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Component\HttpFoundation\RequestStack;
10
use Zicht\Bundle\ConcSroBundle\Exception\UrlFlowException;
0 ignored issues
show
Bug introduced by
The type Zicht\Bundle\ConcSroBund...eption\UrlFlowException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
12
/**
13
 * Provides a checker to determine if a url is safe
14
 *
15
 * By default the service will consider url's safe when they are either:
16
 * a) relative urls, or
17
 * b) absolute urls within the same domain, i.e. zicht.nl and www.zicht.nl are in the same domain.
18
 *
19
 * Alternatively the user can specify their own array with regular expressions to
20
 * determine whether a url is safe.
21
 *
22
 * Example:
23
 * ```php
24
 * // Redirect to success_url when the user is already logged in
25
 * if ($this->isUserLoggedIn()) {
26
 *    throw new UrlFlowException(
27
 *       'User is already logged in',
28
 *       $this->get(UrlCheckerService::class)->getSafeUrl($request->get('success_url'), '/fallback-url')
29
 *    );
30
 * }
31
 */
32
class UrlCheckerService
33
{
34
    /** @var string[] */
35
    protected $safeUrlMatches;
36
37
    /** @var Request|null */
38
    private $masterRequest;
39
40
    /**
41
     * @param RequestStack $requestStack
42
     * @param string[] $safeUrlMatches
43
     */
44
    public function __construct(RequestStack $requestStack, array $safeUrlMatches = [])
45
    {
46
        $this->masterRequest = $requestStack->getMasterRequest();
47
        $this->safeUrlMatches = $safeUrlMatches;
48
49
        if ($this->masterRequest && empty($this->safeUrlMatches)) {
50
            // When no matches are configured we will accept relative urls
51
            // Do *not* tweak this matcher without running the unit tests
52
            $this->safeUrlMatches [] = '#^/([^/]|$)#';
53
54
            // When no matches are configured we will accept absolute urls to the same domain
55
            // Do *not* tweak this matcher without running the unit tests
56
            $hostParts = array_slice(explode('.', $this->masterRequest->getHost()), -2);
57
            $this->safeUrlMatches [] = sprintf('#^((https?://)|(/{0,2}))?([a-z0-9.]+[.])?%s(/|$)#i', join('[.]', $hostParts));
58
        }
59
    }
60
61
    /**
62
     * @param string|null $url
63
     * @return bool
64
     */
65
    public function isSafeUrl($url)
66
    {
67
        if (empty($url)) {
68
            return false;
69
        }
70
71
        foreach ($this->safeUrlMatches as $safeUrlMatch) {
72
            if (preg_match($safeUrlMatch, $url)) {
73
                return true;
74
            }
75
        }
76
77
        return false;
78
    }
79
80
    /**
81
     * @param string|null $url
82
     * @param string|null $default
83
     * @return string|null
84
     */
85
    public function getSafeUrl($url, $default = null)
86
    {
87
        return $this->isSafeUrl($url) ? $url : $default;
88
    }
89
}
90