Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
If you try to pass a file entity as a validated context in a context-aware plugin, it will fail. I've tracked this down to PrimitiveTypeConstraintValidator::validate() under the following conditions:
$typed_data = Drupal\Core\TypedData\Plugin\DataType\Uri::__set_state(array(
'value' => 'public://field/image/Photo on 4-28-14 at 12.01 PM.jpg',
'definition' =>
Drupal\Core\TypedData\DataDefinition::__set_state(array(
'definition' =>
array (
'type' => 'uri',
'label' => 'URI value',
),
)),
'name' => 'value',
...
))
$value = 'public://field/image/Photo on 4-28-14 at 12.01 PM.jpg';
Where this specifically fails in PrimitiveTypeConstraintValidator::validate():
if ($typed_data instanceof UriInterface && filter_var($value, FILTER_VALIDATE_URL) === FALSE) {
$valid = FALSE;
}
This is due to the fact that the file URI has spaces in it. If this were URL-encoded then it would pass.
Comment | File | Size | Author |
---|---|---|---|
#29 | it-is-no-uri-2278073-29.patch | 870 bytes | jonathan_hunt |
#24 | it-is-no-uri-2278073-24.patch | 1.77 KB | garphy |
Comments
Comment #1
Dave ReidComment #2
Dave ReidComment #3
Dave ReidComment #4
cbr CreditAttribution: cbr commentedWill start to work on this.
Comment #5
slashrsm CreditAttribution: slashrsm commentedThis will also fail if uri contains non-ASCII characters. Do we wanto to fix that also?
See: http://php.net/manual/en/filter.filters.validate.php (FILTER_VALIDATE_URL row)
Comment #6
cbr CreditAttribution: cbr commentedReplaced filter validation url with a regular expression match.
Reference to regex: http://www.ietf.org/rfc/rfc3986.txt (Page 50)
Comment #7
cbr CreditAttribution: cbr commentedPatch now contains both the test and the validation.
Comment #8
BerdirI suggest you put the actual regex string in a constant on this class (const URI_VALIDATION_REGEX = ... and add the reference to the RFC standard to the docblock.
Now you *replaced* the invalid validation, don't do that, add yours instead, we still want to make sure that invalid strings don't validate.
As we replace the API function with our own, I think we should considerably extend our test coverage here to test a list of valid and invalid strings. You could set up an array of $uri => 1/2 and then loop over that and validate it, making sure the value is as expected.
Comment #12
cbr CreditAttribution: cbr commentedWell I did my best but cannot completely figured out how the validation should be handled.
What I did do is write a test with a list of valid and invalid URI's according to several references.
For the test see my TEST-ONLY patch.
If you'd like the test including some regular expressions I tried (but which failed) then download my full patch file.
What I do notice is that FILTER_VALIDATE_URL comes quite close to a solution, there are only a few problems with FILTER_VALIDATE_INT it does not validate correctly on white spaces in the filename, some special characters in filename and IDN characters in domain names.
I'll follow this issue and will help wherever I can.
For my references check out:
http://www.ietf.org/rfc/rfc3986.txt
http://en.wikipedia.org/wiki/Filename
http://www.domainnameshop.com/faq.cgi?id=8&session=106ee5e67d523298
http://en.wikipedia.org/wiki/Filename
Comment #15
slashrsm CreditAttribution: slashrsm commentedThank you @ChrisjuhB. Having an extensive test suite for this will help us a lot!
I went through http://www.ietf.org/rfc/rfc3986.txt a bit and as far as I understand it it does not allow URIs with spaces at all. It says spaces (and other stuff like unicode, ...) should always be %-encoded. This kind of makes sense. Let's say we allow spaces in URIs. That would also make "http://exam ple.com" valid, which is obviously wrong. Is it possible that we're going a bit against the specs when it comes to handling URIs?
Taking what I wrote above into consideration it seems that the only option we have here is %-encoding URIs before we send then to filter_var.
Any thoughts?
Comment #16
BerdirWell, we're calling it uri, but doesn't that simply mean that $file->uri is *not* a valid URI? What if we just don't claim it is? Should possibly have custom validation instead that does things like checking for matching stream wrapper and if possible, check for existence of that file?
Changing the validation would affect validation of URI's that actually *are* valid, we can't just change it for $file->uri.
Comment #17
slashrsm CreditAttribution: slashrsm commentedYes, this probably makes sense. I wouldn't check if file exists though as that might bring to much performance overhead.
Comment #18
Dave ReidWe should have *some* sort of validation for the uri property: is it using a valid stream wrapper, does a file exist at that location, etc?
Comment #22
garphy CreditAttribution: garphy commentedComment #23
garphy CreditAttribution: garphy commentedRerolled the patch.
Comment #24
garphy CreditAttribution: garphy commentedTaking another way to fix this : sticking with "uri" datatype and perform URI validation through file_create_url().
Comment #25
Dave ReidGarphy and I discussed several different options that we thought about trying:
1. Attempting to decode and then re-encode the URI before validation.
2. Creating a new TypedData type for an 'Drupal URI' that would perform different validation.
3. Using file_create_url()
4. Using Symfony's Url Constraint validation, which uses a regex
I think this solution offers us the best path forward, to make sure file entities and the various stream wrappers provided by Drupal or contrib would be compatible with the validation, which this does, since it is assumed that the file_create_url() for each stream wrapper is responsible for provided a valid fully-qualified URI. We will file a follow-up to replace the filter_var() validation with something better, likely with the Symfony validation which seems to use a much better regex, but we would still need the file_create_url() part, so this is a positive change anyway. It might also make sense for a different typed data type since this file_create_url() call really should happen higher in the typed data value itself. Both of those could be left in our follow-up.
Comment #26
jhedstromNeeds a reroll.
Also removing the 'needs tests' tag as the patch above has a test (although it would be nice to upload separately to illustrate the current failing behavior).
Comment #27
cafuego CreditAttribution: cafuego commentedComment #28
jonathan_hunt CreditAttribution: jonathan_hunt commentedDrupalSouth code sprint "reroll" to come
Comment #29
jonathan_hunt CreditAttribution: jonathan_hunt commentedRe-rolled
Comment #30
jonathan_hunt CreditAttribution: jonathan_hunt commentedComment #31
garphy CreditAttribution: garphy commentedIt seems that changes introduced in #2412509: Change LinkItem.uri to type 'uri' rather than 'string' and introduce user-path: scheme fixed the original issue as the last patch only adds the related unit test which passes.
I'm not setting this RTBC as I contributed to the issue several months ago.
Comment #32
cafuego CreditAttribution: cafuego commentedRTBCing, I had alook at this with Jonathan yesterday. Original issue fixed, but no test coverage; this patch adds it.
Comment #33
slashrsm CreditAttribution: slashrsm commentedNice. +1 for RTBC
Comment #34
alexpottThis is only adding test code therefore permitted under beta evaluation rules. Committed 3363c81 and pushed to 8.0.x. Thanks!
Adding a link to the issue is not necessary. Fixed on commit.