Problem
- Form handlers and API code manually calls
trim()
on values too many times. - It's unclear who is responsible for trimming text values / user input.
- The lack of custom
trim()
calls can trigger error messages that are hard to recognize and resolve by a user, in case a submitted form value contains leading or trailing white-space (which is not visible/apparent).
Proposed solution
- Introduce a generic
#trim
property for all form elements that accept#input
. - Make
#trim
default to TRUE for all form element types that accept text as user input. - Process
#trim
directly inform_handle_input_element()
. If the resulting #value is an empty string, trigger the regular processing flow that would be triggered for no user input - including #required validation. - Allow code that does not want this behavior to opt-out by setting #trim to FALSE. (There's no use-case for that in core, but still...)
- Remove all manual calls into
trim()
from API code. Whoever is calling into APIs is expected to provide proper (trimmed) values.
Original summary:
If the user registers and by mistake includes and extra space before or after their email address, the system will reject the email address with an error message that is difficult to understand (as there is nothing obvious wrong with the email address). I have seen this several times when I paste my email address into the email address box and mistakenly include a trailing space. I just tried it on the Drupal.org site and got the error:
"The e-mail address testaccount@test.org is not valid."
My guess is that this problem might affect 2-3% of all users who ever try to set up Drupal accounts and leave them a bit frustrated.
It would be very easy to have the form on the page user/register trim the spaces off of the email address, to solve this problem.
Comment | File | Size | Author |
---|---|---|---|
#73 | drupal8.form-trim.73.patch | 28.51 KB | sun |
#70 | drupal8-form-trim-70.patch | 26.5 KB | aaron |
#65 | drupal8.form-trim.65.patch | 27.34 KB | sun |
#59 | drupal8.form-trim.59.patch | 24.2 KB | sun |
#56 | drupal8.form-trim.56.patch | 26.43 KB | sun |
Comments
Comment #1
Jax CreditAttribution: Jax commentedI also think that it would be more user-friendly to trim the email address before the validation. This patch trims the email address field before the validation.
Comment #2
beginner CreditAttribution: beginner commentedtested.
1) there is a little problem: the validation works with the trimmed email, but the UNtrimmed email is saved in the DB (have a look at user/$uid/edit: the leading/trailing space is still there.
2) the problem exists in cvs: please give a patch for cvs first and it will be backported.
3) provide a patch from the Drupal root directory. see: http://drupal.org/patch
Comment #3
Jax CreditAttribution: Jax commentedStrange, when you submit the user form the modifications to the $edit in the user_user function are not kept between calls.
If I submit this with email address " person@example.com" the first dump shows the same. After the validation (with the trim patch applied) it's "person@example.com" (good) but once you come back in the 'submit' part it's again " person@example.com" (not good).
Shouldn't the modifications in the validate part go to the submit part? Or should the modifications applied in the validate part be applied again in the submit part? The latter seems somewhat strange to me.
Comment #4
Jax CreditAttribution: Jax commentedOk, one cannot modify the form data in the validate step (http://drupal.org/node/22218#node_hook_order). The doc is for node submits but I guess this is also true for user data submits.
So there is the 'prepare' and 'form' step left to make the change. The user_user function does not get a 'prepare' step, so the only possible place is 'form'. But when you make changes to the $edit array they are not reflected in the subsequent steps! When you make changes in the 'form' step, shouldn't the 'submit' step see those changes?
Comment #5
bdragon CreditAttribution: bdragon commentedStill an issue.
Comment #6
marcingy CreditAttribution: marcingy commentedAs we now have form_state we can modify during the validate.
Patch provided to tirm the email address.
Comment #7
Rowanw CreditAttribution: Rowanw commentedCarriage returns were stripped during the patch, but it works for me. However, should it be used for all email fields in Drupal or is the registration page a special case? I also noticed that the request new password form already ignores any surrounding spaces.
Comment #8
robertgarrigos CreditAttribution: robertgarrigos commentedIt should be checked, also, the email while installing and in the contact form
Comment #9
alasda CreditAttribution: alasda commentedVerified issue
installed patch
now receive 404 errors on /user/password and /user/register
Comment #10
alasda CreditAttribution: alasda commentedVerified issue
installed patch
now receive 404 errors on /user/password and /user/register
Comment #11
marcingy CreditAttribution: marcingy commentedHave just applied this patch to the current cvs version of drupal and I can not replicate this issue.
Please roll back the patch and confirm that the issue goes away.
Also please try a fresh install of drupal 6.
This patch doesn't touch the menu system so there is no reason for a 404 to occur.
Comment #12
dropcube CreditAttribution: dropcube commentedYes, I think this is very confusing for final users. the system will reject the email address with an error message that is contradictory and confusing since there is nothing apparently wrong with the email address.
It does not apply only to the user registration form. There are many forms throughout Drupal where an email address is requested.
The patch trim the spaces off of the email address in all the forms that currently requires an email address. The email is modified over the $form_state variable (or a reference) such that the submit handler saves the trimmed version to the database.
Affected files are:
user.module
comment.module
contact.pages.inc
system.module
system.admin.inc
install.php
Take a look to the screen shots for details.
Please test, This is a bug that would be good to fix for the next release of Drupal.
Comment #13
marcingy CreditAttribution: marcingy commentedI agree that we need to patch all areas in drupal where the email is an issue. If we don't I think the situation could end up being even more confusing for users.
I suppose the question now is whether or not the the version number for this issue should be set to 7.x-dev. This approach will allow a better discussion to take place about the issue.
Comment #14
Matt V. CreditAttribution: Matt V. commentedI installed dropcube's patch to Drupal 6 RC2 and I verified the fix on the following pages:
My account
Site information
Configure site
Add user
Contact Form
Comments
Comment #15
Freso CreditAttribution: Freso commentedThis should go against HEAD first, before being backported.
Also, the patch introduces trailing white-space (which is kind of ironic, I think :)) on line 1495 of user.module.
Comment #16
WorldFallz CreditAttribution: WorldFallz commentedRerolled against head.
Comment #17
Dries CreditAttribution: Dries commentedI wonder if trimming should simply be part of the Form API; i.e an get applied to all fields?
Comment #18
WorldFallz CreditAttribution: WorldFallz commented@Dries -- that's an interesting point. I'm trying to think of a valid use case for not trimming text and I can't think of any. Any one else think of one?
Comment #19
tic2000 CreditAttribution: tic2000 commentedThe fact that we can't think of one it doesn't mean there can't be one. But apart that, I think trimming should be done on all fields.
Comment #20
Dries CreditAttribution: Dries commentedIf we trim on all fields, I think we might be able to remove quite a few trims. :-)
Comment #21
catchWorks for me too. At least a couple of times I've looked for a node title direct in the database and not found it because of a leading space, or it's messed up a views alpha listing.
Let's try it at least. Changing issue scope.
Comment #22
WorldFallz CreditAttribution: WorldFallz commentedI took at look at form.inc (which is still pretty much a black hole to me), but what about something like (from _form_validate):
don't laugh too hard if it's totally off ;-)
Comment #23
tic2000 CreditAttribution: tic2000 commented@WorldFallz
Why not just a trim()? Anyway, a proper patch file is needed.
Comment #24
WorldFallz CreditAttribution: WorldFallz commentedi didn't use trim, because there could be valid reasons for white space in the middle of a string depending on the input format and i didn't realize trim() only touches the beginning/end, lol.
And I didn't want to waste time on a patch that was completely off-base. If this is the correct way to handle it, i'll roll a proper patch (including removal of any existing trim()'s where necessary).
Comment #25
Frando CreditAttribution: Frando commented_form_validate
and valdiation handlers aren't supposed to change an element's value. The correct place to perform thetrim()
is infunction form_type_textfield_value()
.Comment #26
Frando CreditAttribution: Frando commentedOne-line patch attached.
Comment #27
Frando CreditAttribution: Frando commentedComment #28
Damien Tournoud CreditAttribution: Damien Tournoud commentedMakes a lot of sense, but let's add a little test for that.
Comment #29
Frando CreditAttribution: Frando commentedSure.
Comment #30
Damien Tournoud CreditAttribution: Damien Tournoud commentedThe doxygens are a little bit off. Also, I would feel more comfortable if we made a request to a real form on the child site instead of using FAPI internal functions for this.
Comment #31
Frando CreditAttribution: Frando commentedBetter spelling and docs. No time right now to write another test that uses the browser. If anyone wants to have a go, great! Otherwise, IMO the test as it stands is enough. We test that submitting forms via the browser works in many many places..
Comment #32
Dries CreditAttribution: Dries commentedThanks for taking this for a test drive -- I think it might work. One thing we should do is try to figure out if there are some trims() that can be removed from submit handlers now. Candidates:
Comment #33
tic2000 CreditAttribution: tic2000 commentedFirst try to remove all trim(). I don't know if passwords are affected by the trim patch, so I didn't remove those that were in password validations.
Comment #34
Jax CreditAttribution: Jax commentedThe Zend_Form components let's you specify filters on form fields:
So maybe the filter functionality can be added to the form API in stead of trimming all strings by default? This patch doesn't even allow people to not trim a text field...
Zend Framework also lets you apply filters to all the elements on a form which might also be an option for the Drupal form api.
Comment #35
Frando CreditAttribution: Frando commentedIt does allow not to trim a textfield by setting a custom #value_callback on the element.
Implementing multiple value filters is still a nice idea. This could maybe be achieved by making #value_callback an array and passing the value through all #value_calback functions. Let's keep that for a seperate issue, though.
Comment #36
Dries CreditAttribution: Dries commentedI agree with Frando in #35 but it is something which can be left for a future patch. We could add a TODO to the code if desirable, but it shouldn't hold up this patch.
It looks like this patch has another patch embedded into it. Somehow that does not bother the test bot so we might be alright here. Given that the test bot is happy, I think it is safe to proceed with this patch.
Comment #37
tic2000 CreditAttribution: tic2000 commentedThis one should be better and incorporates Frando's patch too.
Comment #39
Frando CreditAttribution: Frando commentedtic2000, the patch you submitted is malformed or broken.
Proper reroll attached. Quickly skimmed the places where trim() was removed now that it's default on textfield and it looked good. Removed the changes to search.module, though (they aren't directly coming from textfield value so we better leave the trim()s in).
Let's see what testbot says.
Comment #40
Frando CreditAttribution: Frando commentedComment #42
Frando CreditAttribution: Frando commentedComment #44
Jax CreditAttribution: Jax commentedI've rerolled the patch for current head.
Comment #45
Jax CreditAttribution: Jax commentedComment #47
Freso CreditAttribution: Freso commentedBumping to 8.x (wow, that looks weird :x).
Also, I want to stress tic2000's concern in comment 33, that trimming all fields will affect passwords as well - which might have deliberate whitespace at the beginning or end.
Comment #48
Damien Tournoud CreditAttribution: Damien Tournoud commentedOnly feature requests and tasks can be assigned to D8 for now, because the Drupal 8 tree is not opened yet.
Fortunately, this is a feature request.
Comment #49
sunI think this is a fair assumption to make, but unconditionally applying trim() to all input=text field values without providing an opt-out is not a fair thing to do.
In other words: Let's turn this into a #value_trim property for textfields in system_element_info(), which defaults to TRUE.
Use-cases that re-use textfields for other applications can easily opt-out then.
Btw, this functionality is also interesting for #type textarea, though a default of FALSE might be more appropriate for them.
Comment #50
aaron CreditAttribution: aaron commentedI have taken a stab at this. It needs tests still.
Comment #51
sunThanks for reviving this, @aaron!
This topic came up very recently in a lot of config system conversions, since we're currently trimming values in entity storage controllers, too.
Personally, I think that whenever someone calls into an entity API directly, we should assume that developers know what they are doing. Contrary to that, user input supplied via forms can contain arbitrary leading and trailing white-space, and we only need to cater for that.
I like the new #trim property in #50. However, I'd almost move its processing as a generic facility into
form_handle_input_element()
, before any value callback is invoked; i.e., something along the lines of this:What do you think?
Comment #53
aaron CreditAttribution: aaron commentedok
Comment #54
aaron CreditAttribution: aaron commentedComment #56
sunSorry, my snippet was misleading/wrong. The following code checks for $input_exists instead of $input, so we need to force that to FALSE.
I've adjusted that, and additionally:
- Changed #type 'textarea' have a default #trim of TRUE.
- Actually added #trim to all text-input element types. I think that simply makes sense as a default for all text input elements in forms and results in consistency. :)
- Grepped for
'trim('
throughout core and replaced all instances that are obsolete.So let's see what the bot thinks :)
Comment #58
sunMuch better :)
AFAICS, there are two types of failures remaining:
1) ShortcutSetsTest + PageTitleFilteringTest are most likely bogus test expectations that simply need to be updated. (I didn't verify that though.)
2) The FormTest on the password_confirm field... I don't know. Perhaps we should simply remove the #trim from #type 'password' for now, and look into that later? That would mean we'd have to revert all related trim() removals from the user register/login form validation handlers. Personally, I'd be more than happy with ignoring that for now (i.e., reverting #trim on #type password). The massive simplifications elsewhere across the code base are worth to have regardless of those password-specifics. :)
Comment #59
sunReverted #trim for #type password.
Hopefully, that leaves us with #58.1) only.
Comment #60
sunAnd I can only guess that the Shortcut test is looking for this custom error message :)
However, with the new #trim behavior, the default #required message of "!name field is required." will be shown. :)
Thus, the test needs to be adjusted.
--
PageTitleFilteringTest, OTOH, is a security test, so might be doing something very spooky ;) Needs analysis.
@aaron: Can you look into those two tests? :)
Comment #61
aaron CreditAttribution: aaron commentedwhy not try the following?
Comment #63
sunWell, the purpose of this patch is to remove all the custom trim() handling that was previously required. In turn, that means that the behavior of the system is slightly changed. The (current) behavior is covered by tests though, in order to verify our current expectations.
But due to this patch, our expectations are changing. We do not expect a form validation handler to have to worry about trimming submitted form values anymore, because the operation is performed centrally already. Due to the changed expectation, existing form validation handler code that previously threw a custom error message is no longer needed and thus won't throw that custom error message anymore. As a result, the expectation in our current tests has to be changed. :)
As predicted in #58, the only two remaining failures are in ShortcutSetsTest + PageTitleFilteringTest. The first one should really just be a trivial matter of adjusting the form validation error message string that the test apparently seems to look for. The page title test OTOH might try to verify some edge-case expectation; e.g., submitting a node with a title consisting of spaces only (or similar), which we need to look into; it's also perfectly possible that it's equally a trivial expectation change though. :)
Comment #64
aaron CreditAttribution: aaron commentedIt appears to be setting the title to
<span></title><script type="text/javascript">alert("Title XSS!");</script> & < > " \'</span>
I do not know what it should be doing in regards to our trimming, so I post this for posterity.
Comment #65
sunI looked into both tests and corresponding code and adjusted them accordingly.
With that, I consider this patch ready.
Comment #66
aaron CreditAttribution: aaron commentedIt looks good to me now. Although, I wonder why you removed the assertion messages from that test. I would mark this RTBC, but I am unable to, being one of the authors of this patch.
Comment #67
dman CreditAttribution: dman commentedI wanted to test and green-light this, but sorry, a few failures to apply today. looks like HEAD is moving too fast and this touched a lot of different files.
OTOH, maybe it's just me. re-queuing against todays code..
Comment #68
dman CreditAttribution: dman commented#65: drupal8.form-trim.65.patch queued for re-testing.
Comment #70
aaron CreditAttribution: aaron commentedThis patch is a re-roll against HEAD. There were some changes to the node/content-types.inc. I couldn't find any trim statements within menu/menu-admin.inc.
Comment #72
dman CreditAttribution: dman commentedThat test fail looks like it's probably genuine. Code in point looks like
- for some reason they WANTED those trailing newlines to be hanging around. Is that by design to raise a red flag incase something like this DOES unexpectedly trim the user input?
Comment #73
sunThat's just whitespace garbage. Doesn't serve any purpose. Can we safely removed.
Done so in attached patch.
Comment #75
sun#73: drupal8.form-trim.73.patch queued for re-testing.
Comment #77
aaron CreditAttribution: aaron commented#73: drupal8.form-trim.73.patch queued for re-testing.
Comment #79
aaron CreditAttribution: aaron commentedI'm not sure what's up with the bot. I am able to apply the patch just fine, however when I install Drupal with the patch applied, it does not log me in automatically. I am not certain, but I think that the bot is being confused by this, and giving us the wrong error message for some reason.
Comment #80
tim.plunkettRemoving unrelated tags
Comment #81
mtiftLet's try again (removing those config tags, which apparently are not removable)
Comment #81.0
mtiftUpdated issue summary.
Comment #90
liquidcms CreditAttribution: liquidcms commented8 years since last update? safe to assume this issue is dead?
Comment #91
klonosJust because focus may have shifted to other priorities and/or people not having time/energy/motivation, it doesn't mean that this issue "is dead". This is a very valid request, and a nice DX improvement + existing code cleanup. So still worth pursuing.
Since D8 is now EoL, I'm assuming that this needs to go against latest 9.x, so I've updated the issue metadata accordingly.
Comment #93
bardiuk CreditAttribution: bardiuk commentedSo..... how do I trim the email at the login page, is there a way? I am googling 30 min already.
UPD: Ok, I have figured this out