%profile default values broken
antix - October 15, 2009 - 02:52
| Project: | Webform |
| Version: | 6.x-2.9 |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs work |
Description
Default values (for example, profile data pulled with %profile_) don't work as of this update. The fields auto-populate with the %profile_ code.

#1
I can confirm this with both Drupal 5 and 6, though from looking at the code this isn't immediately clear why this has occurred. Patches would be appreciated here, as I'm unable to afford much time to Webform currently.
#2
Same issue here after updating. Subscribing...
#3
Unfortunately, I got the same problem.
#4
Me too. Subscribing.
#5
Same here, unfortunately. Subscribing
#6
Here's a quick and mostly untested fix. Just posting code for now. I can roll a patch later if this looks good.
Apologies for the pseudo patch.
Starting with line 2140 in webform.module
<?php
// Provide a list of candidates for token replacement.
// Note these tokens are not cached as they may change frequently.
if ($user->uid && module_exists('profile')) { //Added
profile_load_profile($user); //Added
} //Added
$special_tokens = array(
'safe' => array(
'%get' => $_GET,
),
'unsafe' => array(
'%cookie' => $_COOKIE,
'%session' => $_SESSION,
'%post' => $_POST,
'%request' => $_REQUEST,
'%profile' => $user, //Added
),
);
// User replacements.
if (!array_key_exists('%username', $replacements['unsafe'])) {
$replacements['unsafe']['%username'] = isset($user->name) ? $user->name : '';
$replacements['unsafe']['%useremail'] = isset($user->mail) ? $user->mail : '';
$replacements['unsafe']['%ip_address'] = ip_address();
if ($user->uid && module_exists('profile')) { //Removed
profile_load_profile($user); //Removed
} //Removed
// $special_tokens['unsafe']['%profile'] = $user; //Removed
// Doesn't really belong here with user things, but works.
$special_tokens['unsafe']['%server'] = $_SERVER;
}
?>
#7
Same thing as awolfey... not a patch, because it's not a fix, but a way around :)
The problem is that it will only pass the if statement the first time:
// User replacements.if (!array_key_exists('%username', $replacements['unsafe'])) {
Therefor, only the first time the $special_tokens will be added.... and only the first $string will be checked in
if (strpos($string, $token) !== FALSE) {I'm not really sure what the design was of this code, so wouldn't know what the proper fix would be :)
<?php foreach ($special_tokens as $safe_state => $tokens) {foreach ($tokens as $token => $variable) {
// if (strpos($string, $token) !== FALSE) { /* Comment this rule */
foreach ($variable as $key => $value) {
// This special case for profile module dates.
if ($token == '%profile' && is_array($value) && isset($value['year'])) {
$replacement = format_date(strtotime($value['month'] .'/'. $value['day'] .'/'. $value['year']), 'custom', 'F j, Y', '0');
}
else {
$replacement = (string) $value;
}
$replacements[$safe_state][$token .'['. $key .']'] = $replacement;
}
// } /* Comment this rule */
}
}?>
Commenting the if statement does get the profile fields working.
#8
Subscribing.
#9
I've been using my solution in #6 in a development site with no problems. I have not tested it with the new security improvements in mind.
#10
Subscribing.
#11
While #6 works, and #7 probably does too, #6 over does it. To fix the issue, simply move the 'profile' functions outside of the User replacements logic.
Change this:
// User replacements.
if (!array_key_exists('%username', $replacements['unsafe'])) {
$replacements['unsafe']['%username'] = isset($user->name) ? $user->name : '';
$replacements['unsafe']['%useremail'] = isset($user->mail) ? $user->mail : '';
$replacements['unsafe']['%ip_address'] = ip_address();
if ($user->uid && module_exists('profile')) {
profile_load_profile($user);
}
$special_tokens['unsafe']['%profile'] = $user;
// Doesn't really belong here with user things, but works.
$special_tokens['unsafe']['%server'] = $_SERVER;
}
To this:
// User replacements.
if (!array_key_exists('%username', $replacements['unsafe'])) {
$replacements['unsafe']['%username'] = isset($user->name) ? $user->name : '';
$replacements['unsafe']['%useremail'] = isset($user->mail) ? $user->mail : '';
$replacements['unsafe']['%ip_address'] = ip_address();
// Doesn't really belong here with user things, but works.
$special_tokens['unsafe']['%server'] = $_SERVER;
}
if ($user->uid && module_exists('profile')) {
profile_load_profile($user);
}
$special_tokens['unsafe']['%profile'] = $user;
This is due to $replacements being a static array, '%username' isn't in the array the first time, so the 'profile' replacements gets loaded the first loop, but never gets loaded again.
Edit: Changed slightly,
$special_tokens['unsafe']['%profile'] = $user;now outside of the$user->uidlogic to prevent an issue that arose, causing unused %profile tokens to not be removed.Cheers,
Deciphered.
#12
While #11 is working and more probably 'right' then #6 or #7, it does do the profile_load_profile($user) each time a string gets passed through.
Again, I don't know if this is by design, but that doesn't feel right.
#13
@ #12,
The problem that was occurring was that it wasn't being run every time. So to solve that, you make it run every time.
Three options I can see are:
- Make $special_tokens a static array, but I don't know enough about static arrays.
- Wrap some extra logic around the code so that it only runs if there is a %profile token in the string for replacement.
- Replace the the replacement code section with tokens module support.
While all three options are valid, the fix I posted works for me at this stage and I have no time, nor I suspect does quicksketch, so if you have the itch, feel free to scratch it.
Cheers,
Deciphered.
#14
Subscribing.
#15
Subscribing.
#16
#17
Slight modification to #11
<?php
// User replacements.
if (!array_key_exists('%username', $replacements['unsafe'])) { $replacements['unsafe']['%username'] = isset($user->name) ? $user->name : '';
$replacements['unsafe']['%useremail'] = isset($user->mail) ? $user->mail : '';
$replacements['unsafe']['%ip_address'] = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
// Doesn't really belong here with user things, but works.
$special_tokens['unsafe']['%server'] = $_SERVER;
}
// if we have a user and module profile and the %profile key doesn't exist
if ( $user->uid && module_exists('profile') && !array_key_exists('%profile', $replacements['unsafe']) ) {
profile_load_profile($user);
$special_tokens['safe']['%profile'] = $user;
}
?>
#18
Same issue here. Thanks for the work on this issue so far. Subscribing.
#19
Subscribing.
#20
Subscribing.
#21
#17 worked for me.
#22
Actually, #17 doesn't work.
If you have a %profile token as a default for a field, the non-existent default won't be removed, that is the exact reason why I edited my code in #11.
$special_tokens['safe']['%profile'] = $user;has to be run whether or not there is a $user->uid.#23
subscribe
#24
subscribing
#25
Subscribing
#26
subscribing
#27
seeing this also with the 5.x version
#28
suggested change in #11 or #17 makes it work - BUT then profile_load_profile() is executed many times for each webform
#29
Here's a 5.x patch that seems to fix the issue and the code is only executed once - it relies on the fact that uid is always a $user field.
Should be essentially the same for 6.x
#30
Above patch still seems to break for anonymous users.
This works, but not sure if it's really right... populates profile fields also for anonymous
#31
no, this one is better
#32
Thanks pwolanin, #31 looks good to me.
#33
subscribing. #11 worked for me BTW.
seems to me the bug was introduced in 6.x.2.8 as I had a slightly older copy of the same site at my localhost which had Webform 6.x.2.7, where all was fine.
#34
Whilst I appreciate everyone's efforts to provide patches, I am concerned that there has been no official fix for this in 2 weeks. We now have a choice between production sites running 6.x-2.7 which is not secure, and 6.x-2.8 where there is a choice of unconfirmed patches. This is a pretty serious problem and I feel it deserves time from the module maintainers, and a 6.x-2.9 to correct this.
#35
We are running #31 in production.
#36
chris.cohen: I would like to say that I've offered co-maintainership of this module to 4 different people over the last 6 months, only one has accepted and it hasn't been enough to handle the massive amount of requests that come through the Webform issue queue. There's an open issue for exactly this problem #604930: Webform Needs Another Maintainer. Hopefully some other developers will step forward to help with the project, until then we can expect long response times and limited release cycles.
#37
Patch in #31 is broken
Change
if (!isset($replacements['unsafe']['%profile[uid]'])) {
to
if (!isset($replacements['unsafe']['%profile'])) {
--glen
#38
#35 and #37 go quite some way to establish the perils of deploying patches in a production enviroment, although I am sure the patch in #31 was created in good faith and does work in some situations. Passing a good set of simpletests would go a long way to assuring robust patches, as is the way now in core.
#39
@glen -
#13#31 is a D5 version patch, so may be slightly different for D6#40
@pwolanin... Dyslexic much? :) I'm guessing that was meant to be #31, not #13.
#41
Subscribing.
#42
#31 converted to 6.x works for me too. I did not need to do #37. Here is the same patch, but for 6.x.
#43
subscribe
#44
It looks like patches in #31 and #42 are correct. #37 will work but it doesn't server the purpose of preventing multiple profile loading. %profile is never set as a key in the $replacements variable, so it would always return FALSE and load the profile again for every replacement. I've committed #31 to the 2.x branch for D5/6 and the 3.x branch for D6.
As I'm sure this is a problem for a lot of users I'll be putting out 2.9 shortly with the fix.
#45
hm, just tried the new 2.9 branch. The %profile - default tokens now are working fine for authenticated users, however still appear as token-code for anonymous users accessing the webform (instead just displaying clean form fields).
Any chance to fix that soon?
#46
I have also experienced this behavior in 2.9
#47
I put this patch together based on several others found on this page. It fixes both anonymous and authenticated user profile tokens on my site. This patch is based on the 6.x-3.x webform module as of today.
#48
I just noticed comment #37 ... that is a much better way to handle the token issue with anonymous users than adding to the special_tokens array. Please find a new patch attached.
#49
Sorry I thought I had committed #42 to 3.x but I had not. Comment #37 is incorrect and does not do any static caching at all (see my comment in #44). I've now committed #42 to 3.x (HEAD).
#50
Reverted back to my patch at #11 as the committed patch still shows '%profile[field]' if the field hasn't got a value.
May not be the best patch, but it just works.
#51
Agreed, the committed patch still shows '%profile[field]' if the field hasn't got a value.
#52
This looks to be permission related somehow.
When I log in under User 1 the field defaults correctly from the users profile entries. When I use an 'administrator' log in credentials it still works. When I use an ordinary authenticated user it's broken. I've tried changing the permission settings but can't seem to get the authenticated user details to pass over.
For what it's worth. Might help someone figure it out.
#53
Well, looks like I spoke too soon. #11 works fine for logged in users but not for anon users (I thought I had checked that, but apparently not). To get it to work for anon users as well, I had to do the modification in #37. Now everything works OK (tested by me and the client now).