Support from Acquia helps fund testing for Drupal Acquia logo

Comments

quicksketch’s picture

I'm not sure whether you mean Webform tokens (%username, etc.) or Token module tokens ([user], [nid], etc.). If the latter, the confirmation message is already run through the Drupal input format system, meaning that you can install any generic token filter module and get token functionality there. If wanting to use Token module tokens throughout Webform, this should be consolidated with #428982: New hooks for additional token replacements.

If you're referring to using Webform tokens in the confirmation message and redirect URL, I would be open to accepting a patch for this functionality. Adding tokens like %nid and %sid would also be useful for these purposes.

chriscalip’s picture

@quicksketch

sorry about the ambiguity, yes I was referring to webform tokens.

Thanks I would be happy to submit a patch, will start working on it tomorrow.

quicksketch’s picture

Title: token support on confirmation message and redirect url » Token support on confirmation message and redirect url
Category: support » feature

Sounds great, I'd be happy to review a patch. I'm moving this to a feature request.

chriscalip’s picture

FileSize
731 bytes

patch

chriscalip’s picture

FileSize
644 bytes

whoops previous patch was git based please ignore. This new patch is per http://drupal.org/patch/create diff example.

Well it looks like I walked into a minefield here :) and I might have to tone down my patch goal to just the give webform token support to the redirect url. Here's why on file webform.module function webform_client_form_submit we still have lots of contextual information (post variables,node,submission stuff) from the submit. While the function that renders the confirmation message on file webform.module function _webform_confirmation only has the node. Not to mention this feature request might have to deal with the filter descriptions popups for both redirect_url and confirmation message (heh) like the one found in the email template fieldset.

I hope this at least helps initially get the ball rolling..

chriscalip’s picture

FileSize
592 bytes

forgot to watch my directories.

quicksketch’s picture

Status: Active » Needs work

I would suggest _webform_filter_values() be applied on the entire URL, not just on the query string. Say you wanted to have a redirect to "node/%nid" for example, %nid is not part of the query string.

chriscalip’s picture

FileSize
722 bytes

Thats a good point there so here's what I did scrapped the previous patches and remade with this patch.

chriscalip’s picture

FileSize
604 bytes

whoops forgot my manners, here's a patch per http://drupal.org/patch/create instructions.

chriscalip’s picture

Status: Needs work » Needs review
chriscalip’s picture

Title: Token support on confirmation message and redirect url » Token support on redirect url
chriscalip’s picture

Title: Token support on redirect url » Webform Token support on redirect url
chriscalip’s picture

FileSize
603 bytes

updated patch .. the loop didn't look right.

danmed’s picture

I have updated my current Webform version (6.x-3.1) with this patch and it is working fine. I had spent hours on that, trying using custom module, hook_form_alter, ...
The solution brought about by this patch suits me fine (I am but a "beginner" with Drupal).
Do you intend to include this in a future "recommended" release for Webform?

Thanks for all.

danmed’s picture

Ouch, I did not follow this up, but current recommended release does not seems to include the enhancements provided by this patch. I guess that I should not try to patch the current version (6.x-3.4) with this...
I do need this feature, which way should I go please?
thanks

silurius’s picture

Subscribing.

EDIT: Forgot to ask for clarification, would this patch (in a nutshell) allow us to show a basic submission summary in the confirmation message? E.g. use tokens to spit out most recent submission, or something along those lines.

quicksketch’s picture

Title: Webform Token support on redirect url » Webform Token support on confirmation message and redirect url

Yes, even though the title just says redirect URL, the original issue also describes working on the confirmation message. I've marked #712060: Allow tokens in the redirect URL field duplicate. This issue may also be of interest as an alternative of a summary page: #435232: Summary/review/preview page before final submission in multistep forms

sabrawy’s picture

i wish we can use token modules with webform ([user], [nid], etc.)
we always use webform block to get the webform with the content such as quotation form and payment
if webform can use token module we can pass a cck field as price for example or anything else

xevious’s picture

Version: 6.x-3.0-beta5 » 6.x-3.4

Is there a plan to add this patch back into the module? I'm on 6x-3.4 and need to display the submission number on the confirmation page. The $_GET['sid'] hack does not work if the webform has a page break.

Alexander Matveev’s picture

subscribing,
that's a very useful feature

wilgrace’s picture

I'm still looking for some way to either display submission info on the confirmation page, or redirect users to their submission page. Is there any progress on this?

mstrelan’s picture

For confirmation messages the following patch should apply to 6.x-3.4 however this doesn't address tokens in the URL

mstrelan’s picture

Reroll of #22 with support for confirmation messages using either drupal_set_message() or template_preprocess_webform_confirmation()

Clint Eagar’s picture

When will this thread be rolled into the module?

I'm hoping for some functionality that will allow me to use Webform tokens in the redirect URL, like this:
http://www.example.com?email=%value[email]

quicksketch’s picture

Status: Needs review » Needs work

It'll be included when:

A) A complete patch has been written and uploaded.
B) It has been tested and approved.

Right now our current path is good but only accomplishes 1/2 the task (it supports confirmation message but not URL).

charlie-s’s picture

Subscribing to this topic.

I've just had a thought... What about using template.php to hijack the confirmation page and resend the user to a new page with the SID and NID now in hand?

ikeigenwijs’s picture

following

quicksketch’s picture

I've just had a thought... What about using template.php to hijack the confirmation page and resend the user to a new page with the SID and NID now in hand?

If you wanted to do this in a correct way you'd use a module to set $form_state['redirect'] after the submission is finished processing. template.php is for changing the display of your site, not the functionality.

charlie-s’s picture

Thanks for the note, quicksketch. You are correct, it definitely belongs in a module.

jaymallison’s picture

Just thought I'd drop a note to say that I got webform tokens working against the redirect_url in webform 6x-3.9.

I had to add this line to webform.module:

    $redirect_url = _webform_filter_values($redirect_url, $node, $submission, NULL, FALSE, TRUE);

I added it in the final elseif block in the function webform_client_form_submit().

  elseif ($redirect_url && strpos($redirect_url, 'http') !== 0) {
    $redirect_url = _webform_filter_values($redirect_url, $node, $submission, NULL, FALSE, TRUE);
    $parts = parse_url($redirect_url);
    $query = $parts['query'] ? ($parts['query'] . '&sid=' . $sid) : ('sid=' . $sid);
    $redirect = array($parts['path'], $query, $parts['fragment']);
  }

I'm no patch maker, I just fiddle with code till it works. Hopefully this helps someone out. Maybe a savvy patcher can patch this and get it committed?

quicksketch’s picture

Title: Webform Token support on confirmation message and redirect url » Webform Token support on confirmation message

Sorry after looking over this issue again it looks like I really should have kept these patches separate. @jaymallison's patch works just fine but the code in #23 could have some pretty nasty side-effects of showing other user's submission information just by changing the URL.

What I've done is reopen #712060 for the redirect URL and this one can be for the confirmation message.

quicksketch’s picture

This particular issue is dependent upon #810160: On confirmation page, use a hash parameter for SID. to prevent access problems. We need to somehow make it so that users can only view their own submission confirmation pages if they're going to contain sensitive information.

mstrelan’s picture

I would have thought that webform_get_submission would do an access check. Then the patch in #23 would work, although would need a fallback for if webform_get_submission returned FALSE.

But I guess this doesn't help with anonymous submissions...

quicksketch’s picture

I would have thought that webform_get_submission would do an access check.

Nope, no access check here. You don't access check things like node_load() either, the only check is on if the user can actually *view* that content. Since you might have any number of reasons for loading a node (or a submission in this case), even if you don't have access to view it. Usually in fact, loading a piece of content is necessary before checking if access is even available.

sunshinee’s picture

subscribing

rbrownell’s picture

+1

jaymallison’s picture

I don't know if this is just too obvious, but it's easy to have node token support on the page, at least in D7 (yes I know this is a D6 thread). I imagine a minor change to this line will make it work in 6 as well.

1) Copy the webform-confirmation.tpl.php file to your theme's directory.
2) Change print $confirmation_message; to print token_replace($confirmation_message,array('node'=>$node));
3) Clear cache
4) Profit

jjjames’s picture

Following

vernond’s picture

I independently arrived at the same place as the patch in #23 (@mstrelan - either we're in the 'great minds' category, or it's the other thing...). What I did do differently was put a 20 second time limit on the token replacement, so that any submission requested more than 20 server seconds after the original submission will get the default confirmation message of 'Thank you, your submission has been received'.

This measure does not bullet-proof the potential snooping by folk clever enough to play with the sid in the URL, but it should curtail their success rate:
- A busy site with several Webforms would have a certain amount of randomity due to sid's not being sequential for a particular Webform node;
- A site with a single Webform that experiences a fairly low volume of traffic would have some insurance due to the large amount of time between submissions;
- The highest risk is faced by a site hosting an excessively popular single Webform.

In short, I am not certain that sufficient risk is mitigated by the time limit. What do you guys think?

The other alternative I thought of (and was waaayyyyy too lazy to even try implement) was additionally storing a session token on the webform_submissions table and using that as the criteria for deciding whether to do the token replacements or show the default.

vernond’s picture

@myself in #39 - why would we need 20 seconds... surely 1 second would be more than enough? Submission is saved, then confirmation is generated. Is there really a hosting solution that would require 20 seconds between those two steps? Doubtful.

bayousoft’s picture

Patch in #39 works for me.

vernond’s picture

@bayousoft: did you bring the 20 seconds window down to maybe 2 or so? I cannot explain why/how I arrived at that large an interval.

vernond’s picture

Status: Needs work » Needs review
vernond’s picture

@quicksketch: do you have any thoughts (negative or otherwise) on the patches in [#39] (apart from the silly 20 second window which needs to decrease), or may I tidy up and commit?

quicksketch’s picture

Status: Needs review » Needs work

I think as a general approach this looks pretty good. However I'd feel much better about it if we did a "real" check such as comparing the global $user->uid and the submission UID. And in the case that it's anonymous, use our cookie that we set also. I think that in addition to the short window is probably okay. The short window allows for anonymous visitors without a cookie to operate properly after all so I think it's a nice safety check, but I'd prefer it weren't our only check.

joelrosen’s picture

Quick question: Is there any reason why this couldn't be properly solved by storing submission data in $_SESSION, and writing a separate menu callback that then grabs the data from $_SESSION to populate a template? This way there's no lookup using the stored SID, and none of this arbitrary time-limit stuff. I figure this ought to be possible by saving the session data using hook_webform_submission_insert in a submodule. I'm going to go ahead and try this for my site but please let me know if it won't work or there's a better way to do it. Thanks.

quicksketch’s picture

@joelrosen: I suppose we could put the information in a $_SESSION, or at least the submission IDs in a session so that we could reliably and securely know the available SIDs. Storing the whole submission in session seems like its excessive since it's already stored in one place, and things could get messy if a user is allowed to edit their submissions or worse yet, someone *else* edits their submission (like an administrator), but only the copy in the database gets updated, not the one in the $_SESSION variable.

That said, I think there's substantial merit in just using $_SESSION to store SIDs for anonymous users. I'd like to give it some testing to figure out how well it works with the anonymous page caching.

joelrosen’s picture

Well, I got it working on my site using this method. Also got it integrated with webform_tokens. I'll look into posting the submodule code somewhere if you're interested. It didn't require any modifications to webform's code. Not sure yet if I will run into issues with anonymous page caching...

joelrosen’s picture

Ok I set up a sandbox project here: http://drupal.org/sandbox/joelrosen/1490388

Comments are welcome. If other people think this looks like a reasonable solution, I think it might be a nice replacement to what seems to me to be a somewhat hacky and insecure answer here: http://drupal.org/node/1245298

Liam Morland’s picture

I know this opens a bigger issue, but why does a regular form submission result in a redirect? Why not take the POST of the form data and serve a 200 status with the confirmation page?

quicksketch’s picture

I know this opens a bigger issue, but why does a regular form submission result in a redirect? Why not take the POST of the form data and serve a 200 status with the confirmation page?

This is to prevent users from accidentally re-submitting the form by using the back button.

Liam Morland’s picture

I tried the module in #49 and it works unless the anonymous user has cookies disabled, in which case they get "Access denied" instead of the confirmation page. There needs to be a better solution for that case.

Another suggestion: When the form is submitted, instead of redirecting to done?sid=#, redirect to done?session=#, where # is the PHP session ID. Webform can look up the sid from that and do the appropriate token replacement. Session IDs are so long that guessing them is not really feasible.

Liam Morland’s picture

If you agree with my suggestion in #52, I will work on coding a patch.

quicksketch’s picture

Thanks for the offer Liam. :)

There have been a number of requests to *remove* the SID from the URL for a variety of reasons (Analytics code and "it looks ugly" have mostly been the requests), but neither of those complaints are entirely valid. Something that could be problem however is that anonymous users don't even *have* sessions when using Pressflow or Drupal 7. Starting a session for anonymous users could have a performance impact on sites with a lot of anonymous users who are completing Webforms.

That said, I do think the session ID is a good identifier. I would encourage the session ID to be combined with some other information (such as the submission ID) so that users who submit multiple submissions are ensured to get different confirmation pages while within the same session. Usually just about all caching is disabled when a session ID is present, but in the event that some cache *is* enabled, you'd want to make sure that you don't serve up a cached copy of a previous submission.

On most of my sites, any time the user submits a form, I disable caching at the CDN and Varnish layers for 5 minutes (or however long the Drupal page cache lifetime is). I don't think starting a session is such a bad thing either, as long as the session has a short lifetime.

Session IDs are so long that guessing them is not really feasible.

So the question I have here is whether validation of the URL will be done by checking against the user's session cookie (in which case the user will have a limited amount of time in which the URL will work, based on the lifetime of their session), or if we'll simply "confirm" the session ID matches the submission. In which case users could copy/paste links and send them to other users who don't have the same session. If we take the latter route, we'd need to store the session ID in the database. At that point, the point of using the Session ID is lost, since you could just as easily generate a random hash and save that in the database and not use sessions at all, thus circumventing the whole caching problem.

Liam Morland’s picture

Version: 6.x-3.4 » 7.x-4.x-dev
Status: Needs work » Needs review
FileSize
3.99 KB

Something that could be problem however is that anonymous users don't even *have* sessions when using Pressflow or Drupal 7.

I did not know this. Now knowing this, I took a different approach.

The attached patch is to Webform 4.x-dev. It applies token replacement to confirmation messages and puts an access callback on the confirmation page. For logged-in users, those with results access and those accessing their own submissions are allowed. Anonymous users are allowed if the requested submission is by an anonymous user form the same IP address in the last 5 seconds. I think this removes any practical ability to view someone else's confirmation message. If this is not good enough, webform_confirmation_page_access() can be adjusted to fix it. I am interested to hear your thoughts.

Liam Morland’s picture

This version is the same as #55, but has a better display for the token list.

quicksketch’s picture

IP Address sometimes isn't the best indicator either. Say you're in a university classroom filling out a survey, *everyone* in the room has the same ip address because they're going through the same router at the front of the classroom. That's the main reason why #246470: Allow cookies as sole voter validation needs to be addressed, because limiting by IP address only is causing grief for a lot of users.

I don't think the session approach would be a bad idea. You can *give* anonymous users a session just by putting something in the $_SESSION variable. http://api.drupal.org/drupal_set_message is a good example of how sessions can work for anonymous users, though I think it cleans up the $_SESSION in drupal_get_messages(), so maybe a real session isn't being used there at all.

Liam Morland’s picture

OK, if it is not too hard to start a session, then I'll work on that approach. It would be a relatively minor change to what is there in the patch already.

The IP address is used as an easy extra check. Security is still reasonable. To see someone else's submission, you would have to share their IP address, then just after they submit their form, submit yours and change the sid to match theirs; you must do this within 5 seconds.

Liam Morland’s picture

As I was working on this, I had another idea. Anything that uses sessions will have a problem with users with cookies disabled. This will probably become a bigger issue with the new EU privacy laws. So, I came up with a no-cookie, no-session solution for anonymous users.

The solution uses a hash. Anonymous users get a hash of their submission data added to the query string of their confirmation page along with sid. When checking access for the confirmation page, the hash of the submission data is recalculated and has to match the hash in the query string. To view someone else's confirmation page, an attacker would have to guess the md5 hash. If brute force is a concern, a maximum age for confirmation pages could be used, like in the previous patch.

quicksketch’s picture

This looks pretty good. I was thinking about something like this also over in #810160: On confirmation page, use a hash parameter for SID.. Using the approach you've set out seems pretty effective, though we should add the site-specific "drupal_private_key" into the hash so that other sites can't generate the same hash by building a similar form and then md5ing the values.

+      $query['hash'] = md5(serialize($submission->data));

Another pseudo-problem is that after the submission has been edited by an administrator the previous token becomes invalid. This probably isn't a huge concern but it's not expected behavior. I'd suggest a complete token similar to this:

+      $query['hash'] = md5(serialize($submission->submitted . $submission->sid . drupal_get_private_key()));

The combination of submission ID and submission time are difficult get exactly correct (though not impossible for someone determined), but the addition of the Drupal private key (which is site-specific) makes guessing pretty well impossible. Better yet, all these keys stay permanent, so they won't be affected by edits to the data.

Liam Morland’s picture

Updated as you suggest.

flexgrip’s picture

It seems like this family of patch removes the %webform tokens and uses token.module for all the replacement. Which is cool. But in terms of the confirmation message, this actually removes the ability to use %email_values to print out all submitted values for the form.

That may be what you guys were shooting for. So I don't mean to criticize. I just noticed this because I was using this patch to provide a pdf link to download the submitted form. The issue with that was that now the generated pdf doesn't have these values in it. Just %email_values printed in plain text.

I can get around this using [submission:values:?] as the token. However, with a form that has 50 questions on it. You have to go and find the field key for each individual field submitted. So this does not work when you get into multiple large forms.

Like I said, I am not commenting to say there is an error or bug in the patch. I just wanted others to read this, as this is a common issue.

This issue of making a [submission:values:ALL] token, would need a separate ticket.

quicksketch’s picture

We switched the 4.x version of the module to use normal Drupal 7 tokens in #1001798: Rewrite token replacement system to use D7 tokens.

This issue of making a [submission:values:ALL] token, would need a separate ticket.

You can already use simply [submission:values] and it will print out all the values, just like the previous %email_values. See http://drupal.org/node/1609324#tokens for conversions. :)

quicksketch’s picture

@Liam Morland: This patch looks great!

+      $hash = md5(serialize($submission->submitted . $submission->sid . drupal_get_private_key()));

Sorry this recommendation was a little dumb. There's no need to include serialize() in there since these things are all strings.

In webform_confirmation_page_access(), what's the need for this bit?

+      // User has results access to this submission.
+      elseif (webform_submission_access($node, $submission)) {
+        return TRUE;
+      }

Is that needed in the event that an administrator is editing some one else's submission?

It'd be good to add PHPdocs to webform_confirmation_page_access(), and also webform_submission_access() even though I realize that's not new code added by this patch.

Liam Morland’s picture

There's no need to include serialize() in there since these things are all strings.

Yes, I should have caught that. I can roll another patch Friday.

The bit with webform_submission_access() allows an administrator to look at anyone's confirmation message if they want to.

I'll add documentation.

Liam Morland’s picture

New version attached.

quicksketch’s picture

This looks great. I'll apply and test when I get a chance. Thanks Liam!

quicksketch’s picture

An interesting support/feature request that this issue may help with: #1712378: Allow Anonymous User to delete own entry. With adding permanent hashes that map to the submission, we could also use this hash for editing/viewing/deleting the actual submission itself.

finkdb’s picture

Subscribing

Liam Morland’s picture

quicksketch’s picture

Yep yep, this is high on my priority list Liam. The current patch looks great I just haven't had time to get it reviewed yet.

quicksketch’s picture

Status: Needs review » Fixed
FileSize
6.54 KB

Thanks again Liam, this (and many others you've done) is a great patch!

I've committed this patch with a few changes:
- Removed the "type" of each @param and @return statement, though reading through the doc standards, I see this is now out of date: http://drupal.org/node/1354#param-return-data-type, We'll probably need to clean up Webform across the board for that documentation change.
- Switched your manual call to theme('token_tree') with the theme('webform_token_help') used throughout Webform for those looking to theme Webform's token replacement globally.
- Removed sid=x from *internal redirects*. We'd been doing this to assist in users wanting to replace tokens on pages other than the confirmation page URL, but unless we add the hash to those pages also, I think that method of token replacement should be discouraged since it's not secure. This annoyed people more than it helped anyway.
- Renamed "hash" in the URL to the more typical "token". This is the same string used in Flag and Fivestar modules, it's nice to maintain consistency.

Let me know if you find any problems with these changes. Committed to the 7.x-4.x branch.

Liam Morland’s picture

Looks good. Thanks!

chriscalip’s picture

This brought a smile to me. Thanks for the little pleasures and victory. good job everyone.

bayousoft’s picture

Woohoo!

mstrelan’s picture

Guessing this won't be ported back to Drupal 6?

quicksketch’s picture

@mstrelan: No unfortunately. We're done adding features to Drupal 6 and the 3.x branch.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

adam_b’s picture

Did this make it into 7.x-3.19? I'm still unable to use any %tokens in the confirmation field.

quicksketch’s picture

Did this make it into 7.x-3.19? I'm still unable to use any %tokens in the confirmation field.

No, it's only in the 4.x branch.

astrosa530’s picture

Is it possible to reference the hash token in webform confirmation emails? I'd like to be able to email anonymous users with a link that includes the token, so they can access the confirmation page later on.

Something like this:
http://testurl/node/webform/done?sid=%sid&token=%token or http://testurl/node/webform/done?sid=%sid&token=%get[token]

(noting that the tokens for the hash 'token' don't work right now).

Liam Morland’s picture

The hash could be made available as a token. This should be requested as a new feature request issue.

arondeparon’s picture

Please note that a "simpler" fix is also possible by implementing hook_template_preprocess on the webform confirmation:

/**
 * Implements hook_template_preprocess
 *
 * @param  [type] $vars       [description]
 * @return [type]             [description]
 */
function my_module_preprocess_webform_confirmation(&$vars) {

	$confirmation = check_markup($vars['node']->webform['confirmation'], $vars['node']->webform['confirmation_format'], '', TRUE);
	module_load_include('inc', 'webform', 'includes/webform.submissions');
	$submission = webform_get_submission($vars['node']->nid, $vars['sid']);
	$confirmation = _webform_filter_values($confirmation, $vars['node'], $submission, NULL, FALSE, TRUE);

   // Strip out empty tags added by WYSIWYG editors if needed.
   $vars['confirmation_message'] = strlen(trim(strip_tags($confirmation))) ? $confirmation : '';

}
beertie’s picture

Issue summary: View changes
raj45’s picture

You can already use simply [submission:values] and it will print out all the values, just like the previous %email_values.

I was looking for exactly this option ([submission:values]), after clicking on "Available tokens", but could only see [submission:values:?], where it seemed like I had to define specific fields. Perhaps the [submission:values] token could be included in the list of avaliable tokens?

Liam Morland’s picture

@raj45: That should be a follow-up issue.

raj45’s picture

Anybody’s picture

It would have been nice to have a patch or mini-module available for the webform 3.x branch. Some projects decided not to upgrade because of customizations. If someone has a good solution, please post it here.