%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

quicksketch - October 15, 2009 - 05:27
Title:Default values broken» %profile default values broken

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

digidoo - October 15, 2009 - 13:24

Same issue here after updating. Subscribing...

#3

pvasener - October 15, 2009 - 15:02

Unfortunately, I got the same problem.

#4

hardfocus - October 15, 2009 - 16:24

Me too. Subscribing.

#5

ricardohdz - October 15, 2009 - 19:34
Version:5.x-2.8» 6.x-2.8

Same here, unfortunately. Subscribing

#6

awolfey - October 16, 2009 - 00:10

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

thijsvdanker - October 16, 2009 - 13:50

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

jimmynash - October 16, 2009 - 19:44

Subscribing.

#9

awolfey - October 16, 2009 - 23:20

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

jtrividi - October 18, 2009 - 18:30

Subscribing.

#11

Deciphered - October 19, 2009 - 03:26

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->uid logic to prevent an issue that arose, causing unused %profile tokens to not be removed.

Cheers,
Deciphered.

#12

thijsvdanker - October 19, 2009 - 06:54

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

Deciphered - October 19, 2009 - 21:21

@ #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

collideous - October 20, 2009 - 09:13

Subscribing.

#15

girishkamath - October 20, 2009 - 16:02
Version:6.x-2.8» 6.x-2.2

Subscribing.

#16

Deciphered - October 20, 2009 - 23:46
Version:6.x-2.2» 6.x-2.8

#17

jhm - October 21, 2009 - 02:25

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

chris.cohen - October 21, 2009 - 11:23

Same issue here. Thanks for the work on this issue so far. Subscribing.

#19

iivvoo - October 21, 2009 - 13:59

Subscribing.

#20

lgb - October 21, 2009 - 19:17

Subscribing.

#21

kratib - October 21, 2009 - 22:51

#17 worked for me.

#22

Deciphered - October 22, 2009 - 04:48

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

dugnap - October 22, 2009 - 05:38

subscribe

#24

philsnipes - October 22, 2009 - 23:06

subscribing

#25

beeroll - October 23, 2009 - 00:34

Subscribing

#26

mkdo - October 29, 2009 - 13:28

subscribing

#27

pwolanin - October 29, 2009 - 14:18

seeing this also with the 5.x version

#28

pwolanin - October 29, 2009 - 14:59

suggested change in #11 or #17 makes it work - BUT then profile_load_profile() is executed many times for each webform

#29

pwolanin - October 29, 2009 - 15:13
Version:6.x-2.8» 6.x-2.x-dev
Status:active» needs review

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

AttachmentSize
webform-profile-tokens-604958-28-5x.patch 1.32 KB

#30

pwolanin - October 29, 2009 - 16:05

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

AttachmentSize
webform-profile-tokens-604958-29-5x.patch 1.31 KB

#31

pwolanin - October 29, 2009 - 16:09

no, this one is better

AttachmentSize
webform-profile-tokens-604958-30-5x.patch 1.22 KB

#32

quicksketch - October 29, 2009 - 16:46

Thanks pwolanin, #31 looks good to me.

#33

vegardjo - November 3, 2009 - 14:30

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

chris.cohen - November 3, 2009 - 15:09

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

pwolanin - November 3, 2009 - 18:10

We are running #31 in production.

#36

quicksketch - November 4, 2009 - 00:09

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

glen201 - November 4, 2009 - 03:07

Patch in #31 is broken

Change


if (!isset($replacements['unsafe']['%profile[uid]'])) {

to


if (!isset($replacements['unsafe']['%profile'])) {

--glen

#38

chris.cohen - November 4, 2009 - 04:40

#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

pwolanin - November 4, 2009 - 13:55

@glen - #13 #31 is a D5 version patch, so may be slightly different for D6

#40

Deciphered - November 4, 2009 - 21:11

@pwolanin... Dyslexic much? :) I'm guessing that was meant to be #31, not #13.

#41

Justin Hopkins - November 4, 2009 - 23:06

Subscribing.

#42

incrn8 - November 5, 2009 - 11:25

#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.

AttachmentSize
webform-profile-tokens-604958-42-6x.patch 922 bytes

#43

ianchan - November 5, 2009 - 23:32

subscribe

#44

quicksketch - November 6, 2009 - 00:07
Status:needs review» fixed

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

danielnolde - November 10, 2009 - 15:27
Status:fixed» needs work

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

ao5357 - November 10, 2009 - 20:14

I have also experienced this behavior in 2.9

#47

leprechau - November 10, 2009 - 20:59

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.

AttachmentSize
webform-profile-tokens-20091101-6.x-3.x.patch 1.01 KB

#48

leprechau - November 10, 2009 - 21:10

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.

AttachmentSize
webform-profile-tokens-2009110102-6.x-3.x.patch 877 bytes

#49

quicksketch - November 11, 2009 - 00:07

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

Deciphered - November 17, 2009 - 02:17

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

Branjawn - November 19, 2009 - 20:23

Agreed, the committed patch still shows '%profile[field]' if the field hasn't got a value.

#52

drunkencelt - November 21, 2009 - 20:44
Version:6.x-2.x-dev» 6.x-2.9

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

incrn8 - November 22, 2009 - 03:47

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).

 
 

Drupal is a registered trademark of Dries Buytaert.