Hi,
I was tempted to submit this as a bug report but I just tried to reproduce the error on the live demo and it handles it fine, so I assume there is something I haven't set up right. I just installed drupal for the first time today so this might be an idiot question.
If I try to request a new pasword using a username or an email address that doesn't exist in the database I get thrown the following error:
----------
user error: Duplicate entry '' for key 2
query: INSERT INTO users (pass, created, changed, uid) VALUES ('c98fc7385d06288c78d1d0e9ed505364', '1129921504', '1129921504', '6') in /home/*******/public_html/drupal/includes/database.mysql.inc on line 66.
warning: Invalid argument supplied for foreach() in /home/*******/public_html/drupal/modules/user.module on line 174.
warning: Cannot modify header information - headers already sent by (output started at /home/*******/public_html/drupal/includes/common.inc:384) in /home/*******/public_html/drupal/includes/common.inc on line 192.
----------
On the live demo it handles it with a "Sorry. The username/email address whatever is not recognized".
I had a quick look at the code but couldn't easily identify the origin of the call to _db_query() (database.mysql.inc - line 66) so I thought I'd ask the experts. Any thoughts?
Comments
Perhaps this is a bug after all
The problem is occurring inside the user_pass() function in user.module. It's easier to describe if you break the function up.
Part 1
First, the POST variables are tested. I think the code is supposed to function such that the conditional tests should only load a user into the $account variable if a corresponding username or email address is found in the database.
Part 2
That way the following conditional should only result in a mail being sent if the correct information is available.
Part 3
This is the code that runs if the test fails and there is insufficient correct data to change the password and inform the user.
The problem is that user_load() will always return an object, so $account will always be instantiated in Part 1, rendering the second part of each conditional test redundant. An empty user gets assigned if a real user cannot be found in the database. The net effect is that execution will always pass into Part 2 and not into Part 3 if the data supplied in the form is wrong rather than just empty.
The MySQL error is generated because user_save() is called in Part 2 on an empty user, which tries to insert a new record into users with the default username (an empty string), clashing with the username of the null user (uid=0) and violating the constraint requiring usernames to be unique.
I have fixed the problem by changing Part 1 to look like this:
And the start of Part 2 to this:
Based on this bug report I suspect that the problem may be limited to php 5 (I'm using php 5.0.4 with drupal 4.6.3). I have never looked at the drupal codebase before today so I haven't tested it with php 4. All I know is that the demo site doesn't manifest this problem. I also don't know whether my workaround is a good fix or not as I don't know the code well enough to know whether there are any hidden implications. But it seems to work for me.
Can someone let me know whether I should submit this as a proper bug with the fix?
thanks - this patch works
and this is still not fixed in 4.6.9 tarball