UrlRule.php
4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Form\Rule;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormRule;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Uri\UriHelper;
/**
* Form Rule class for the Joomla Platform.
*
* @since 1.7.0
*/
class UrlRule extends FormRule
{
/**
* Method to test an external or internal url for all valid parts.
*
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control value. This acts as an array container for the field.
* For example if the field has name="foo" and the group value is set to "bar" then the
* full field name would end up being "bar[foo]".
* @param Registry $input An optional Registry object with the entire data set to validate against the entire form.
* @param Form $form The form object for which the field is being tested.
*
* @return boolean True if the value is valid, false otherwise.
*
* @since 1.7.0
* @link http://www.w3.org/Addressing/URL/url-spec.txt
* @see JString
*/
public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null)
{
// If the field is empty and not required, the field is valid.
$required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required');
if (!$required && empty($value))
{
return true;
}
$urlParts = UriHelper::parse_url($value);
// See http://www.w3.org/Addressing/URL/url-spec.txt
// Use the full list or optionally specify a list of permitted schemes.
if ($element['schemes'] == '')
{
$scheme = array('http', 'https', 'ftp', 'ftps', 'gopher', 'mailto', 'news', 'prospero', 'telnet', 'rlogin', 'sftp', 'tn3270', 'wais',
'mid', 'cid', 'nntp', 'tel', 'urn', 'ldap', 'file', 'fax', 'modem', 'git');
}
else
{
$scheme = explode(',', $element['schemes']);
}
/*
* Note that parse_url() does not always parse accurately without a scheme,
* but at least the path should be set always. Note also that parse_url()
* returns False for seriously malformed URLs instead of an associative array.
* @link https://www.php.net/manual/en/function.parse-url.php
*/
if ($urlParts === false || !array_key_exists('scheme', $urlParts))
{
/*
* The function parse_url() returned false (seriously malformed URL) or no scheme
* was found and the relative option is not set: in both cases the field is not valid.
*/
if ($urlParts === false || !$element['relative'])
{
$element->addAttribute('message', \JText::sprintf('JLIB_FORM_VALIDATE_FIELD_URL_SCHEMA_MISSING', $value, implode(', ', $scheme)));
return false;
}
// The best we can do for the rest is make sure that the path exists and is valid UTF-8.
if (!array_key_exists('path', $urlParts) || !StringHelper::valid((string) $urlParts['path']))
{
return false;
}
// The internal URL seems to be good.
return true;
}
// Scheme found, check all parts found.
$urlScheme = (string) $urlParts['scheme'];
$urlScheme = strtolower($urlScheme);
if (in_array($urlScheme, $scheme) == false)
{
return false;
}
// For some schemes here must be two slashes.
$scheme = array('http', 'https', 'ftp', 'ftps', 'gopher', 'wais', 'prospero', 'sftp', 'telnet', 'git');
if (in_array($urlScheme, $scheme) && substr($value, strlen($urlScheme), 3) !== '://')
{
return false;
}
// The best we can do for the rest is make sure that the strings are valid UTF-8
// and the port is an integer.
if (array_key_exists('host', $urlParts) && !StringHelper::valid((string) $urlParts['host']))
{
return false;
}
if (array_key_exists('port', $urlParts) && !is_int((int) $urlParts['port']))
{
return false;
}
if (array_key_exists('path', $urlParts) && !StringHelper::valid((string) $urlParts['path']))
{
return false;
}
return true;
}
}