PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.3.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.3.1
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / UrlHelper.php
matomo / app / core Last commit date
API 6 years ago Access 6 years ago Application 6 years ago Archive 6 years ago ArchiveProcessor 6 years ago Archiver 6 years ago AssetManager 6 years ago Auth 6 years ago Category 6 years ago CliMulti 6 years ago Columns 6 years ago Composer 6 years ago Concurrency 6 years ago Config 6 years ago Container 6 years ago CronArchive 6 years ago DataAccess 5 years ago DataFiles 6 years ago DataTable 6 years ago Db 6 years ago DeviceDetector 5 years ago Email 6 years ago Exception 6 years ago Http 6 years ago Intl 6 years ago Mail 6 years ago Measurable 6 years ago Menu 6 years ago Metrics 6 years ago Notification 6 years ago Period 6 years ago Plugin 6 years ago ProfessionalServices 6 years ago Report 6 years ago ReportRenderer 6 years ago Scheduler 6 years ago Segment 6 years ago Session 6 years ago Settings 6 years ago Tracker 5 years ago Translation 6 years ago UpdateCheck 6 years ago Updater 6 years ago Updates 6 years ago Validators 6 years ago View 6 years ago ViewDataTable 6 years ago Visualization 6 years ago Widget 6 years ago .htaccess 6 years ago Access.php 6 years ago Archive.php 6 years ago ArchiveProcessor.php 6 years ago AssetManager.php 6 years ago Auth.php 6 years ago BaseFactory.php 6 years ago Cache.php 6 years ago CacheId.php 6 years ago CliMulti.php 6 years ago Common.php 6 years ago Config.php 6 years ago Console.php 6 years ago Context.php 6 years ago Cookie.php 5 years ago CronArchive.php 5 years ago DataArray.php 6 years ago DataTable.php 6 years ago Date.php 6 years ago Db.php 6 years ago DbHelper.php 6 years ago Development.php 6 years ago DeviceDetectorFactory.php 6 years ago ErrorHandler.php 6 years ago EventDispatcher.php 6 years ago ExceptionHandler.php 6 years ago FileIntegrity.php 6 years ago Filechecks.php 6 years ago Filesystem.php 6 years ago FrontController.php 6 years ago Http.php 6 years ago IP.php 6 years ago Log.php 6 years ago LogDeleter.php 6 years ago Mail.php 6 years ago Metrics.php 6 years ago MetricsFormatter.php 6 years ago Nonce.php 5 years ago Notification.php 6 years ago NumberFormatter.php 6 years ago Option.php 5 years ago Period.php 6 years ago Piwik.php 6 years ago Plugin.php 6 years ago Profiler.php 6 years ago ProxyHeaders.php 6 years ago ProxyHttp.php 6 years ago QuickForm2.php 6 years ago RankingQuery.php 6 years ago Registry.php 6 years ago ReportRenderer.php 6 years ago ScheduledTask.php 6 years ago Segment.php 6 years ago Sequence.php 6 years ago Session.php 6 years ago SettingsPiwik.php 6 years ago SettingsServer.php 6 years ago Singleton.php 6 years ago Site.php 6 years ago TCPDF.php 6 years ago TaskScheduler.php 6 years ago Theme.php 6 years ago Timer.php 6 years ago Tracker.php 6 years ago Translate.php 6 years ago Twig.php 6 years ago Unzip.php 6 years ago UpdateCheck.php 6 years ago Updater.php 6 years ago Updates.php 6 years ago Url.php 6 years ago UrlHelper.php 6 years ago Version.php 5 years ago View.php 6 years ago bootstrap.php 6 years ago dispatch.php 6 years ago testMinimumPhpVersion.php 6 years ago
UrlHelper.php
348 lines
1 <?php
2 /**
3 * Piwik - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9 namespace Piwik;
10
11 use Piwik\Container\StaticContainer;
12 use Piwik\Intl\Data\Provider\RegionDataProvider;
13
14 /**
15 * Contains less commonly needed URL helper methods.
16 *
17 */
18 class UrlHelper
19 {
20 private static $validLinkProtocols = [
21 'http',
22 'https',
23 'tel',
24 'sms',
25 'mailto',
26 'callto',
27 ];
28
29 /**
30 * Checks if a string matches/is equal to one of the patterns/strings.
31 *
32 * @static
33 * @param $test String to test.
34 * @param $patterns Array of strings or regexs.
35 *
36 * @return true if $test matches or is equal to one of the regex/string in $patterns, false otherwise.
37 */
38 protected static function in_array_matches_regex($test, $patterns)
39 {
40 foreach($patterns as $val) {
41 if(@preg_match($val, null) === false) {
42 if( strcasecmp($val, $test) === 0 ) {
43 return true;
44 }
45 } else {
46 if( preg_match($val, $test) === 1 ) {
47 return true;
48 }
49 }
50 }
51 return false;
52 }
53
54 /**
55 * Converts an array of query parameter name/value mappings into a query string.
56 * Parameters that are in `$parametersToExclude` will not appear in the result.
57 *
58 * @static
59 * @param $queryParameters Array of query parameters, eg, `array('site' => '0', 'date' => '2012-01-01')`.
60 * @param $parametersToExclude Array of query parameter names that shouldn't be
61 * in the result query string, eg, `array('date', 'period')`.
62 * @return string A query string, eg, `"?site=0"`.
63 * @api
64 */
65 public static function getQueryStringWithExcludedParameters($queryParameters, $parametersToExclude)
66 {
67 $validQuery = '';
68 $separator = '&';
69 foreach ($queryParameters as $name => $value) {
70 // decode encoded square brackets
71 $name = str_replace(array('%5B', '%5D'), array('[', ']'), $name);
72
73 if (!self::in_array_matches_regex(strtolower($name), $parametersToExclude)) {
74 if (is_array($value)) {
75 foreach ($value as $param) {
76 if ($param === false) {
77 $validQuery .= $name . '[]' . $separator;
78 } else {
79 $validQuery .= $name . '[]=' . $param . $separator;
80 }
81 }
82 } elseif ($value === false) {
83 $validQuery .= $name . $separator;
84 } else {
85 $validQuery .= $name . '=' . $value . $separator;
86 }
87 }
88 }
89 $validQuery = substr($validQuery, 0, -strlen($separator));
90 return $validQuery;
91 }
92
93 /**
94 * Reduce URL to more minimal form. 2 letter country codes are
95 * replaced by '{}', while other parts are simply removed.
96 *
97 * Examples:
98 * www.example.com -> example.com
99 * search.example.com -> example.com
100 * m.example.com -> example.com
101 * de.example.com -> {}.example.com
102 * example.de -> example.{}
103 * example.co.uk -> example.{}
104 *
105 * @param string $url
106 * @return string
107 */
108 public static function getLossyUrl($url)
109 {
110 static $countries;
111 if (!isset($countries)) {
112 /** @var RegionDataProvider $regionDataProvider */
113 $regionDataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\RegionDataProvider');
114 $countries = implode('|', array_keys($regionDataProvider->getCountryList(true)));
115 }
116
117 return preg_replace(
118 array(
119 '/^(w+[0-9]*|search)\./',
120 '/(^|\.)m\./',
121 '/(\.(com|org|net|co|it|edu))?\.(' . $countries . ')(\/|$)/',
122 '/(^|\.)(' . $countries . ')\./',
123 ),
124 array(
125 '',
126 '$1',
127 '.{}$4',
128 '$1{}.',
129 ),
130 $url);
131 }
132
133 /**
134 * Returns true if the string passed may be a URL ie. it starts with protocol://.
135 * We don't need a precise test here because the value comes from the website
136 * tracked source code and the URLs may look very strange.
137 *
138 * @api
139 * @param string $url
140 * @return bool
141 */
142 public static function isLookLikeUrl($url)
143 {
144 return preg_match('~^(([[:alpha:]][[:alnum:]+.-]*)?:)?//(.*)$~D', $url, $matches) !== 0
145 && strlen($matches[3]) > 0
146 && !preg_match('/^(javascript:|vbscript:|data:)/i', $matches[1])
147 ;
148 }
149
150 public static function isLookLikeSafeUrl($url)
151 {
152 if (preg_match('/[\x00-\x1F\x7F]/', $url)) {
153 return false;
154 }
155
156 if (strpos($url, ':') === false) {
157 return true;
158 }
159
160 $protocol = explode(':', $url, 2)[0];
161 return preg_match('/^(' . implode('|', self::$validLinkProtocols) . ')$/i', $protocol);
162 }
163
164 /**
165 * Returns a URL created from the result of the [parse_url](http://php.net/manual/en/function.parse-url.php)
166 * function.
167 *
168 * Copied from the PHP comments at [http://php.net/parse_url](http://php.net/parse_url).
169 *
170 * @param array $parsed Result of [parse_url](http://php.net/manual/en/function.parse-url.php).
171 * @return false|string The URL or `false` if `$parsed` isn't an array.
172 * @api
173 */
174 public static function getParseUrlReverse($parsed)
175 {
176 if (!is_array($parsed)) {
177 return false;
178 }
179
180 $uri = !empty($parsed['scheme']) ? $parsed['scheme'] . ':' . (!strcasecmp($parsed['scheme'], 'mailto') ? '' : '//') : '';
181 $uri .= !empty($parsed['user']) ? $parsed['user'] . (!empty($parsed['pass']) ? ':' . $parsed['pass'] : '') . '@' : '';
182 $uri .= !empty($parsed['host']) ? $parsed['host'] : '';
183 $uri .= !empty($parsed['port']) ? ':' . $parsed['port'] : '';
184
185 if (!empty($parsed['path'])) {
186 $uri .= (!strncmp($parsed['path'], '/', 1))
187 ? $parsed['path']
188 : ((!empty($uri) ? '/' : '') . $parsed['path']);
189 }
190
191 $uri .= !empty($parsed['query']) ? '?' . $parsed['query'] : '';
192 $uri .= !empty($parsed['fragment']) ? '#' . $parsed['fragment'] : '';
193 return $uri;
194 }
195
196 /**
197 * Returns a URL query string as an array.
198 *
199 * @param string $urlQuery The query string, eg, `'?param1=value1&param2=value2'`.
200 * @return array eg, `array('param1' => 'value1', 'param2' => 'value2')`
201 * @api
202 */
203 public static function getArrayFromQueryString($urlQuery)
204 {
205 if (strlen($urlQuery) == 0) {
206 return array();
207 }
208
209 // TODO: this method should not use a cache. callers should instead have their own cache, configured through DI.
210 // one undesirable side effect of using a cache here, is that this method can now init the StaticContainer, which makes setting
211 // test environment for RequestCommand more complicated.
212 $cache = Cache::getTransientCache();
213 $cacheKey = 'arrayFromQuery' . $urlQuery;
214
215 if ($cache->contains($cacheKey)) {
216 return $cache->fetch($cacheKey);
217 }
218
219 if ($urlQuery[0] == '?') {
220 $urlQuery = substr($urlQuery, 1);
221 }
222 $separator = '&';
223
224 $urlQuery = $separator . $urlQuery;
225 // $urlQuery = str_replace(array('%20'), ' ', $urlQuery);
226 $referrerQuery = trim($urlQuery);
227
228 $values = explode($separator, $referrerQuery);
229
230 $nameToValue = array();
231
232 foreach ($values as $value) {
233 $pos = strpos($value, '=');
234 if ($pos !== false) {
235 $name = substr($value, 0, $pos);
236 $value = substr($value, $pos + 1);
237 if ($value === false) {
238 $value = '';
239 }
240 } else {
241 $name = $value;
242 $value = false;
243 }
244 if (!empty($name)) {
245 $name = Common::sanitizeInputValue($name);
246 }
247 if (!empty($value)) {
248 $value = Common::sanitizeInputValue($value);
249 }
250
251 // if array without indexes
252 $count = 0;
253 $tmp = preg_replace('/(\[|%5b)(]|%5d)$/i', '', $name, -1, $count);
254 if (!empty($tmp) && $count) {
255 $name = $tmp;
256 if (isset($nameToValue[$name]) == false || is_array($nameToValue[$name]) == false) {
257 $nameToValue[$name] = array();
258 }
259 array_push($nameToValue[$name], $value);
260 } elseif (!empty($name)) {
261 $nameToValue[$name] = $value;
262 }
263 }
264
265 $cache->save($cacheKey, $nameToValue);
266
267 return $nameToValue;
268 }
269
270 /**
271 * Returns the value of a single query parameter from the supplied query string.
272 *
273 * @param string $urlQuery The query string.
274 * @param string $parameter The query parameter name to return.
275 * @return string|null Parameter value if found (can be the empty string!), null if not found.
276 * @api
277 */
278 public static function getParameterFromQueryString($urlQuery, $parameter)
279 {
280 $nameToValue = self::getArrayFromQueryString($urlQuery);
281
282 if (isset($nameToValue[$parameter])) {
283 return $nameToValue[$parameter];
284 }
285 return null;
286 }
287
288 /**
289 * Returns the path and query string of a URL.
290 *
291 * @param string $url The URL.
292 * @return string eg, `/test/index.php?module=CoreHome` if `$url` is `http://piwik.org/test/index.php?module=CoreHome`.
293 * @api
294 */
295 public static function getPathAndQueryFromUrl($url)
296 {
297 $parsedUrl = parse_url($url);
298 $result = '';
299 if (isset($parsedUrl['path'])) {
300 if (substr($parsedUrl['path'], 0, 1) == '/') {
301 $parsedUrl['path'] = substr($parsedUrl['path'], 1);
302 }
303 $result .= $parsedUrl['path'];
304 }
305 if (isset($parsedUrl['query'])) {
306 $result .= '?' . $parsedUrl['query'];
307 }
308 return $result;
309 }
310
311 /**
312 * Returns the query part from any valid url and adds additional parameters to the query part if needed.
313 *
314 * @param string $url Any url eg `"http://example.com/piwik/?foo=bar"`
315 * @param array $additionalParamsToAdd If not empty the given parameters will be added to the query.
316 *
317 * @return string eg. `"foo=bar&foo2=bar2"`
318 * @api
319 */
320 public static function getQueryFromUrl($url, array $additionalParamsToAdd = array())
321 {
322 $url = @parse_url($url);
323 $query = '';
324
325 if (!empty($url['query'])) {
326 $query .= $url['query'];
327 }
328
329 if (!empty($additionalParamsToAdd)) {
330 if (!empty($query)) {
331 $query .= '&';
332 }
333
334 $query .= Url::getQueryStringFromParameters($additionalParamsToAdd);
335 }
336
337 return $query;
338 }
339
340 public static function getHostFromUrl($url)
341 {
342 if (!UrlHelper::isLookLikeUrl($url)) {
343 $url = "http://" . $url;
344 }
345 return parse_url($url, PHP_URL_HOST);
346 }
347 }
348