1: <?php
2:
3: /*
4: * This file is part of the Symfony package.
5: *
6: * (c) Fabien Potencier <fabien@symfony.com>
7: *
8: * For the full copyright and license information, please view the LICENSE
9: * file that was distributed with this source code.
10: */
11:
12: namespace Symfony\Component\HttpFoundation;
13:
14: /**
15: * RequestMatcher compares a pre-defined set of checks against a Request instance.
16: *
17: * @author Fabien Potencier <fabien@symfony.com>
18: *
19: * @api
20: */
21: class RequestMatcher implements RequestMatcherInterface
22: {
23: /**
24: * @var string
25: */
26: private $path;
27:
28: /**
29: * @var string
30: */
31: private $host;
32:
33: /**
34: * @var array
35: */
36: private $methods = array();
37:
38: /**
39: * @var string
40: */
41: private $ips = array();
42:
43: /**
44: * @var array
45: */
46: private $attributes = array();
47:
48: /**
49: * @var string[]
50: */
51: private $schemes = array();
52:
53: /**
54: * @param string|null $path
55: * @param string|null $host
56: * @param string|string[]|null $methods
57: * @param string|string[]|null $ips
58: * @param array $attributes
59: * @param string|string[]|null $schemes
60: */
61: public function __construct($path = null, $host = null, $methods = null, $ips = null, array $attributes = array(), $schemes = null)
62: {
63: $this->matchPath($path);
64: $this->matchHost($host);
65: $this->matchMethod($methods);
66: $this->matchIps($ips);
67: $this->matchScheme($schemes);
68:
69: foreach ($attributes as $k => $v) {
70: $this->matchAttribute($k, $v);
71: }
72: }
73:
74: /**
75: * Adds a check for the HTTP scheme.
76: *
77: * @param string|string[]|null $scheme An HTTP scheme or an array of HTTP schemes
78: */
79: public function matchScheme($scheme)
80: {
81: $this->schemes = array_map('strtolower', (array) $scheme);
82: }
83:
84: /**
85: * Adds a check for the URL host name.
86: *
87: * @param string $regexp A Regexp
88: */
89: public function matchHost($regexp)
90: {
91: $this->host = $regexp;
92: }
93:
94: /**
95: * Adds a check for the URL path info.
96: *
97: * @param string $regexp A Regexp
98: */
99: public function matchPath($regexp)
100: {
101: $this->path = $regexp;
102: }
103:
104: /**
105: * Adds a check for the client IP.
106: *
107: * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
108: */
109: public function matchIp($ip)
110: {
111: $this->matchIps($ip);
112: }
113:
114: /**
115: * Adds a check for the client IP.
116: *
117: * @param string|string[] $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
118: */
119: public function matchIps($ips)
120: {
121: $this->ips = (array) $ips;
122: }
123:
124: /**
125: * Adds a check for the HTTP method.
126: *
127: * @param string|string[] $method An HTTP method or an array of HTTP methods
128: */
129: public function matchMethod($method)
130: {
131: $this->methods = array_map('strtoupper', (array) $method);
132: }
133:
134: /**
135: * Adds a check for request attribute.
136: *
137: * @param string $key The request attribute name
138: * @param string $regexp A Regexp
139: */
140: public function matchAttribute($key, $regexp)
141: {
142: $this->attributes[$key] = $regexp;
143: }
144:
145: /**
146: * {@inheritdoc}
147: *
148: * @api
149: */
150: public function matches(Request $request)
151: {
152: if ($this->schemes && !in_array($request->getScheme(), $this->schemes)) {
153: return false;
154: }
155:
156: if ($this->methods && !in_array($request->getMethod(), $this->methods)) {
157: return false;
158: }
159:
160: foreach ($this->attributes as $key => $pattern) {
161: if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) {
162: return false;
163: }
164: }
165:
166: if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) {
167: return false;
168: }
169:
170: if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) {
171: return false;
172: }
173:
174: if (IpUtils::checkIp($request->getClientIp(), $this->ips)) {
175: return true;
176: }
177:
178: // Note to future implementors: add additional checks above the
179: // foreach above or else your check might not be run!
180: return count($this->ips) === 0;
181: }
182: }
183: