This is tagged as duplicate of #139670: skip duplicate form submits the second.

Original issue description

So apparently it's quite easy in Drupal to post duplicate content. Simply press the "submit" button twice, whether creating a node, replying to a comment, etc...

While it's not easy to reproduce this on a clean install (since the site is so lightweight and fast) it's easy to reproduce this on any real site.

This is quite a problem and I've been encountering this for quite sometime.

So bad in fact that Robert created a module to prevent this: http://drupal.org/project/issues/formsingle

It's a rather simple module and this was before the concept of form tokens were introduced into Drupal. I imagine now it would be rather trivial to write a patch that checks to make a sure a token is only submitted and processed once.

So how about it? Any takers, unfort I have to run right now and can't look into this for a few days, but just wanted to post this to get this out there.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

m3avrck’s picture

See this? It's a duplicate comment. Just proving my point :-)

m3avrck’s picture

See this? It's a duplicate comment. Just proving my point :-)

m3avrck’s picture

Hmm, can I get it more than twice? Depends on how fast the servers are at processing the request, on some very slow sites I've seen things duplicated up to 20 times.

m3avrck’s picture

Hmm, can I get it more than twice? Depends on how fast the servers are at processing the request, on some very slow sites I've seen things duplicated up to 20 times.

m3avrck’s picture

Hmm, can I get it more than twice? Depends on how fast the servers are at processing the request, on some very slow sites I've seen things duplicated up to 20 times.

m3avrck’s picture

Hmm, can I get it more than twice? Depends on how fast the servers are at processing the request, on some very slow sites I've seen things duplicated up to 20 times.

m3avrck’s picture

Hmm, can I get it more than twice? Depends on how fast the servers are at processing the request, on some very slow sites I've seen things duplicated up to 20 times.

m3avrck’s picture

Hmm, can I get it more than twice? Depends on how fast the servers are at processing the request, on some very slow sites I've seen things duplicated up to 20 times.

Caleb G2’s picture

I don't get it. What's the problem?

Caleb G2’s picture

I don't get it. What's the problem?

RobRoy’s picture

You guys, come on! Stop double posting! :P

RobRoy’s picture

Dang. I even suck a double posting. What's the secret?

m3avrck’s picture

Have to a wait a split sec -- so that the web server gets the request, but hasn't responded yet -- then you can nail it, it would not be hard to get up to 100, albeit a bit boring :-)

m3avrck’s picture

Now that Drupal.org has been upgrade to 5, just showing that this duplicate problem still persists :-)

m3avrck’s picture

Now that Drupal.org has been upgrade to 5, just showing that this duplicate problem still persists :-)

m3avrck’s picture

Now that Drupal.org has been upgrade to 5, just showing that this duplicate problem still persists :-)

m3avrck’s picture

Now that Drupal.org has been upgrade to 5, just showing that this duplicate problem still persists :-)

m3avrck’s picture

Now that Drupal.org has been upgrade to 5, just showing that this duplicate problem still persists :-)

m3avrck’s picture

Now that Drupal.org has been upgrade to 5, just showing that this duplicate problem still persists :-)

m3avrck’s picture

Now that Drupal.org has been upgrade to 5, just showing that this duplicate problem still persists :-)

Caleb G2’s picture

If paired with something critical like, an ecommerce 'submit payment' function, couldn't this be considered critical? The time to address for 5.0 is quickly falling away (if not already gone).

m3avrck’s picture

Yes, IMO this is a critical issue. But in the sense of critical for drupal it doesn't break your site. But it opens up a whole other can of worms...

chx’s picture

I have doubts. I have seen many, many systems saying 'do no press this button twice' , payment systems using JavaScript to change the submit button to 'Please wait' and pressing it again does nothing. Of course, just because everyone else is wrong we can be right... can we?

If you try to solve this on core levels then you will soon hit fun problems with multiple tabs.

I believe ecommerce and anyone else aspiring can easily solve this by storing foo in session and removing it on submit. I do not mark this won't fix yet, let's discuss.

m3avrck’s picture

chx, I agree with said points, here are a few more.

This solution *cannot* use some sort of JS/disable the button on submit. I've tried this and it won't work with Drupal. Reason because is because we rely on the value of the submit button (preview, delete, submit) and having it disabled doesn't send the value. I confirmed this with John Resig. Plus, it's too easy to have JS turned off, so that solution is out.

Yes, next up is the fact that you can have multiple buttons per node, but I don't feel this is a hindrance at all.

And your proposal of a SESSION variable is exactly on target with how Robert solved this issue in the form single module: http://drupal.org/project/issues/formsingle

However, this module was written before tokens were in core, so all of that logic could be removed. And when you remove a bit more because this functionality *could* live in core, you end up with relatively small patch that solves a relatively huge and annoying problem.

Going the route of $_SESSION and storing the form token and making sure it's only set once seems like the most logical route.

I tried looking at form.inc and doing this but my head soon exploded and I had quite an awful mess to clean up on my desk... :-p

robertDouglass’s picture

I can't promise that this will be *easy* to do, but storing the token in $_SESSION and removing it on submit seems the best solution. This is on my list of things to look at but not my top priority atm. I do want this in D6, though.

moshe weitzman’s picture

Um, I don't see *significant* problems with disabling or hiding the button with JS. Natuarally the form is messed up if it gets submitted in this disabled state. Thats explicitly not allowed. Further, I know that this is not a solution for non js browsers. Thats OK too. A solution does not need to be 100% to be very useful. I see this as simpler than a session based solution, and thus more likely to get into core.

Caleb G2’s picture

Please post a patch and mark this critical so that it has a snowball's chance of making it in D5. :)

m3avrck’s picture

Well I wrote in my blog about the JS approach which is working *extremely* well for a high traffic site of mine:

http://tedserbinski.com/2007/01/11/how_to_prevent_duplicate_posts

Caleb G2’s picture

I see the blog post which contains part of what is needed to implement this and talk about the other part, but I think the problem is that with out an actual patch for people to test and see it working on their own install - it's just theory.

Stefan Nagtegaal’s picture

*subscribing*

robertDouglass’s picture

FileSize
4.97 KB

Uses a slight variation of the $_SESSION strategy where every form gets a unique random token (which is not the same as #token or #build_id), and upon first submission this gets saved into $_SESSION, along with a timestamp. When the second request to submit that form comes along, it fails (form error "This form has already been submitted") because it matches the token with the token in the session.

There are ways to subvert this (using firebug to change the hidden value, for example), but users can no longer play the game of clicking the Submit button as often as possible and seeing who can submit the most times.

I tested opening a form in multiple tab; not only does this patch not conflict with that in any way, it successfully prevents multiple submissions from each tab.

My two questions are, does the first chunk of the patch hurt multipart forms in any way, and can this be done any more efficiently (fewer if clauses, less data in $_SESSION)?

robertDouglass’s picture

Status: Active » Needs review
robertDouglass’s picture

I should add that this doesn't apply to any form out of the box. You need to add this to a form in order to have it prevent multiple submissions:

$form['#prevent_multiple'] = TRUE;

I've added this to node and comment forms for testing. We need to decide whether other forms should have it too. The reason I didn't apply it to all forms is because some forms are designed for multiple submission (ajaxy forms, for example). Suggestions welcome.

robertDouglass’s picture

Status: Needs review » Needs work

So I screwed up when I changed strategy from putting the token into the session at first build time to putting it in at first submit time. Now, if you take the hidden token out of your form (using firebug, for example), you can still submit multiple times. I'll update the patch to the previous strategy.

robertDouglass’s picture

Eaton pointed out that this should not be set if #programmed is TRUE. I'll add that to the next patch.

robertDouglass’s picture

Steef suggests that #prevent_multiple should be TRUE for all forms by default and those forms (like ajax forms) that need it turned off should do so explicitely. Opinions?

Stefan Nagtegaal’s picture

Title: duplication of nodes/users if submitted twice » Prevent multiple form processing: causing duplication of nodes/users

This is getting somewhere...

testing atm..

Zen’s picture

Title: Prevent multiple form processing: causing duplication of nodes/users » duplication of nodes/users if submitted twice

Disable submit buttons after clicking, using JS = +1.

Preventing abuse / edge cases / non JS solution = solve with a contrib module. IMO, this should be handled with flood control using the flood table (that is what it's there for). The current patch appears to handle this similarly, but in a round-about way.

Obscure code = -1.

My 10p.

Thanks,
-K

Zen’s picture

Title: duplication of nodes/users if submitted twice » Prevent multiple form processing: causing duplication of nodes/users
Category: bug » feature

Resetting title. I also don't believe that this is a bug. Setting to feature.

Thanks,
-K

robertDouglass’s picture

Category: feature » bug

I disagree that it is a feature (it is a bug... unless you consider multiple submissions of the same form a feature?), and experience in the field shows that the JS solution does not work well enough.

There is a contrib module which solves this problem. I wrote it. But it requires doing a form_alter on every single form and keeping track of the cases where you want the protection and where you don't want the protection is impossible. Using my proposed solution form authors can turn it on or off, and contrib modules can do the same if they feel the need.

The code that I have written is nowhere near as obscure as the code surrounding it. If you want to -1 obscure code you'll probably want to delete the form_builder function from your Drupal installation right now.

Zen’s picture

This is like calling spam a bug. Nothing is broken. You are introducing a new feature to combat click abuse, that's it.

Your website is just facing momentary click abuse from obnoxious users. This is hardly a common problem. Moreover, as mentioned in my previous post, this can also be adequately controlled by something along the lines of a comment_control module that restricts users to say, 1 comment/node etc. a minute using the flood table. The infrastructure for this is already built into Drupal. Consequently, IMO, the solution being presented in this patch is redundant, overcomplicated and unnecessary.

As for obscurity, mea culpa.. s/obscure code/more obscure code/.

The real world problem is "double clicking" where (usually windows) users are so inured to their OS, that they double click everything. This is solved reasonably successfully via JS. The above mentioned flood control modules can, I believe, also be used in tandem to good benefit.

Thanks,
-K
P.S. Please respond to why you believe a flood control module will not work. In theory, it should be a simple and reasonably sound way to solve this.

m3avrck’s picture

I agree that this is indeed a bug. Submitting a form twice for processing causes adverse effects--duplicate entries, potentially duplicate credit card entries so forth. Drupal should be smart to know if a form has been submitted once, that if it's submitted again it shouldn't do anything since it's already in the middle of processing the data.

A JS solution isn't full proof--easy enough to have JS off.

robertDouglass’s picture

@Zen: Your proposed solution to this problem creates two extra database queries per form submission. Nobody will consider this as a viable option.

chx’s picture

I am not entering the debate whether this is a bug or a feature. I comment on http://drupal.org/files/issues/prevent_multiple.patch instead. First of all, you must not call such a clean up everytime drupal_get_form is called. Make it dependent on your attribute otherwise login form and search box suffers. Second, time is not enough, I beleive. Use microtime.

robertDouglass’s picture

note to self: fix the security hole in this line (thanks chx):

+ '#value' => isset($form['#post']['prevent_multiple']) ? $form['#post']['prevent_multiple'] : md5(mt_rand()),

Zen’s picture

@rDouglass - Fair enough. I don't believe Drupal core needs this, but it appears that I'm in the minority. Also, if this does go in, I think the contact form will also need it.

/me crawls back into his hole.

Thanks,
-K

m3avrck’s picture

// Protect against multiple submissions for an hour.

What if a user needs to create a bunch of nodes and is creating 1 every few minutes? I think a safer route would be a time limit of 1 minute -- enough to prevent duplicate submissions, but short enough to allow multiple postings.

Stefan Nagtegaal’s picture

Isn't 8 till 10 sec. long enough??

robertDouglass’s picture

@m3avrck, @Steef, that number only governs garbage collection. It is a compromise between a bloated $_SESSIONS table and the realization that a user could press submit, and before the page reloads, press the browsers "Stop" button, leaving the form open. With the 1 hour time for gc, they'd have to leave the window open for an hour, and browse with the same session in another window, before they'd be able to double submit. It is not a limit on how many form submissions they can make.

robertDouglass’s picture

Version: 5.x-dev » 5.1
FileSize
4.76 KB

Better version. Harder to subvert (if at all possible). Now I save a token in the session when the form is first created, and when it gets submitted, that token has to be there for submission to succeed. When submission succeeds, I also save the destination of the form to the session (using the token as the key). This way, if the user multiple submits, instead of giving an ugly form error, I can redirect them to the destination of that form.

I also addressed eatons #programmed and chx's xss concerns.

Some common misunderstandings about this patch:

  1. It does not prevent you from submitting multiple similar forms. If you open 5 windows with the node/add/page form, you can submit all 5 at once and it won't care. This is because every instance of each form gets its own token.
  2. The timestamp that gets saved in the session with each token id is for garbage collection only. It is not a throttle that controls a time period for multiple submissions. That is the domain of flood, and I'm not touching that here at all. The timestamp is only there so that we can get rid of the tokens from the session at some point.

Problems:

  • Garbage collection is a mess. I don't know the best way to call the garbage collection routine and I don't know the best time period to keep the tokens.
  • Related to garbage collection, and a potentially serious issue, is the session bloat that this patch will cause. Each rendered form will stick a new array in the session. So if the garbage collection limit is 2 hours, then a person will have an array in their session for each form they've viewed in those 2 hours. Considering that we can have 2-4 forms on each page for a typical site, this could be a big session.
  • Testing with complex forms. Are there cases where the patch breaks things? In particular with AJAX and multi-step forms, what can go wrong?
  • Are there forms in core to which this functionality should not be applied? Whenever possible we should prevent multiple submissions, even if no "bad" things happen otherwise. Why? Because this gets the hell out of there before the submit functions are called. That alone makes multiple submit requests more lightweight than normal. Take the modules administration page, for example. If you multiple submit that in D5, it calls cache_clear_all every time. With this patch it does it only once, even if you accidentally (or intentionally) click submit 20 times.
robertDouglass’s picture

FileSize
4.74 KB

small cleanup

robertDouglass’s picture

FileSize
4.89 KB

rerolled with -F^f so chx can see what functions are affected =)

The first two hunks are garbage collection and can/should be completely rewritten. The rest (3 chunks) are the actual functionality.

robertDouglass’s picture

The "need more choices" bit on Poll.module doesn't work. I'm investigating to confirm that this patch is the cause.

robertDouglass’s picture

No, I was just using poll wrongly. You have to press "Preview" to get more choice fields.

m3avrck’s picture

Tested patch, works as advertised :-D

A few notes:

  • If you hit submit multiple times, you lose the drupal message "your node has been created", seems like that is wiped from the session
  • For cleanup, I suggest we do:
    if (isset($form['#multistep']) || isset($form['#prevent_multiple']) {  /// }
    

    The rand isn't really needed, since you only need cleanup if either of those are true. Either that, or move that function call to system_cron() -- perhaps that is the best place.

  • Why generate a new form token when #token is already set for you? That whole chunk of code seems to be redundant to what line 344 or so in form.inc is already doing for each form.

Otherwise this is shaping up very nicely, great job Robert!

robertDouglass’s picture

@m3avrck: The reason for the rand (soon to be mt_rand as per chx) is simply the overhead of doing this every time a form is built. The only reason to do garbage collection at all is to keep the session variable reasonably small, so it isn't a high priority to take care of every time we run this code. The test you propose would do the garbage collection every time any form was built.... which is too often imo. Still looking for a better gc algorithm.

The reason I don't use the #token in the form is because it is the same for every instance of a type of form. For example, every node/add/blog form would have the same token. Furthermore, whole classes of forms don't get this token at all. So unfortunately, it serves a totally different purpose and doesn't help us here.

robertDouglass’s picture

There's nothing that can be done about the message. If people care about their messages they won't submit more than once.

m3avrck’s picture

^^ Hahah, ok.

As for cleanup, perhaps cleanup is run *only* when there are more than 10 entries or so in their $_SESSION? Wouldn't count() be faster than a mt_rand()?

Potentially the rand() might not run and it could get out of control, having it run when it reaches a limit might make more sense.

robertDouglass’s picture

Well a limit would be like saying we're willing to always tote around X entries, even if we don't need them. Plus, for active users who look at a lot of forms, it would make it so that they quickly exceed their limit and the gc code would get run every form build (multiple times per request in most cases). So eventually, rand will run the code, and by adjusting the number (1 out of 10, 1 out of 100, 1 out of 1000) we can tune it to what seems to work best. That was my thinking, anyway.

m3avrck’s picture

Or, having it so 3 < rand(0,4) to run 20% of the time or something to that affect if we don't want to use the count() approach.

robertDouglass’s picture

Version: 5.1 » 6.x-dev
Status: Needs work » Needs review

Marking this D6 and needs review.

Dries’s picture

This sounds like a complex solution.

Rather than setting a token on creation, why don't we flatten the $form_values and compute a md5() hash on submit? (i.e. md5(print_r($form_values, TRUE))). We keep the last md5 hash in a $_SESSION variable. When the user submits a new form, we compute the md5 hash and compare it to the last md5-hash stored in a session variable. If they match, we don't call the submit handler. With this solution, we wouldn't need a garbage collection scheme ...

robertDouglass’s picture

I like the suggestion and will try it.

chx’s picture

As usual Dries comes to the rescue. With this we only spend time on submit. And you really can store just one MD5 submit hash in your session because it's not a realistic situation that you have two tabs open, you click submit in one, switch, click submit there too, come back to the first and click submit quick enough again to create a duplicated post. Or, if you want to do this, have fun. The burden of processing falls on submit time not render time. Very nice solution.

m3avrck’s picture

That's a great idea!

Robert, any update on the patch?

robertDouglass’s picture

FileSize
1.13 KB

It works. Almost. I can't get a duplicate submission on the comment form, but it doesn't have any affect on the Page or Story forms. Maybe someone can help figure out why.

robertDouglass’s picture

Status: Needs review » Needs work
m3avrck’s picture

!isset() will be faster than !empty()

Anonymous’s picture

Coming in late to the conversation obviously. Has anyone thunk of a theme modification to disable the submit after the click? Please forgive me if this is a stupid idea, just say so and I'll shut up.

chx’s picture

theme is not harry potter to say 'disappearatio!' it's HTML and we discussed that JS is no good solution.

moshe weitzman’s picture

@Earnie - your idea isn't stupid, so no forgiveness necessary there. But ...

You can answer your own question if you just read this web page. Is that so hard? If you can't even be bothered to that, search for the word javascript and you will get to the exact posts where this is discussed. Your unwillingness to do this and your past similar behavior indicate that you value your own time more than the time of others. Now all of us had to read your repetitive question. And such questions are even more wasteful on the development mail list where over 1000 people are reading. Please be respectful by doing adequate research before posting.

BioALIEN’s picture

Well put moshe. Back on topic, the webform.module uses a few methods to prevent multiple submits, but I believe Dries's suggestion is ultimately the best solution so far.

Just curious, how would this be handled if FAPI3 goes into D6?

Anonymous’s picture

Yea I did that a little later in the night. I missed the JS discussion in the first pass of the thread. Sorry for the noise.

Robert's solution on the surface looks like it should work. I'll have to give it a try. It'll be a while later before I get back to this with results.

m3avrck’s picture

FileSize
1.15 KB

Here's an updated patch. Changes:

  • Working now in all my tests! What changes everytime you submit a node? Well it's timestamp, so we can't hash the entire $form, that won't work. So I changed that to only has over the $form['form_id']['#post'] -- a lot less data to hash over too so it's much faster. Forms API gurus correct me if I'm wrong
  • #programmed is not set for node creation, so remove that check
  • !empty() was a backwards checkt, should be empty() -- but I switched this to isset() which is much faster
  • Cleaned up some if logic to be faster
m3avrck’s picture

Status: Needs work » Needs review
jonfhancock’s picture

subscribing

chx’s picture

Status: Needs review » Needs work

well, empty and isset are the same speed (they are both handled by ZEND_ISSET_ISEMPTY_VAR and only the return values differ). #programmed must be checked because if it's a programmed submit, no such check should occur.

m3avrck’s picture

Status: Needs work » Needs review
FileSize
1.17 KB

Ok updated with the !#programmed check -- I took this out because I didn't think it would matter because $_SESSION wouldn't be set in that case for programmed forms? Or maybe not...

m3avrck’s picture

FileSize
1.77 KB

Updated patch after talking with chx on IRC that $redirect more often than not will be NULL but the form is still submitted so we need to keep track of that for this patch to work in all cases.

m3avrck’s picture

FileSize
1.75 KB

Ok, let's do the submit check correctly, shall we? Thanks to chx for explaining this to me :-)

m3avrck’s picture

FileSize
1.77 KB

Fix a possible notice as well, thanks chx again.

chx’s picture

At this time, I would call this RTBC but I really would like two more people to look at it before this gets in: Adrian and Eaton. I do not want to end up with forms that do not get submitted...

webchick’s picture

subscribing

eaton’s picture

Status: Needs review » Needs work

I just took a slow look over the code and tested it on a number of forms. It seems to be working well and the logic appears sound; bailing out of the check when #programmed is true means that we won't accidentally kill automated programmed forms, and hashing the #post values means that multiple *different* submissions won't cause problems.

chx mentioned wanting two other opinions -- I'll defer to that 'Additional input from Adrian or another guru' and not RTBC it yet, but the patch has my +1.

eaton’s picture

Status: Needs work » Needs review

Yeah, that should've stayed at 'needs review', not 'needs work.' I think it's RTBC but I too wouldn't mind another set of form eyes on it.

Adrian? Someone, activate th Vertice-Signal. :-)

m3avrck’s picture

FileSize
2.05 KB

After talking with Heine and chx on IRC, we need a new flag so you can skip duplicate checking in your forms if you want to turn this feature off for whatever reason.

eaton’s picture

Status: Needs review » Reviewed & tested by the community

With the presence of that flag, I think it's officially a must-have.

webchick’s picture

I actually would -1 the introduction of "yet another form API property" for some kind of theoretical 'someday developers might need to use this' kind of thing.

If a legitimate use case comes up, we can always add in the property later. For now, I'd keep it simple.

Heine’s picture

Legitimate use cases:

- Searching twice for the same term.

From the comment_mover promotion block form:

    $form['type'] = array(
      '#type' => 'select',
      '#title' => t('Convert to'),
      '#default_value' => 'forum',
      '#options' => $options,
    );
    $form['submit'] = array('#type' => 'submit', '#value' => t('Convert'));
  }

Now, with this patch, one can't promote comments to the same node type in succession.

m3avrck’s picture

From IRC:

Heine: I was replying to webchick, but I should've indicated that better.
robertDouglass’s picture

Status: Reviewed & tested by the community » Needs review

Heine, are you sure you can't submit that form twice? It doesn't get rebuilt in between requests? If it gets rebuilt, and you can't resubmit it, then there is a flaw in the patch. Let me know if this is the case, and how to recreate, and I'll see if there is a workaround. As long as a form gets newly built, it should be able to be submitted.

m3avrck’s picture

Status: Needs review » Reviewed & tested by the community

This patch does not break search from what I can tell. And bonus, it works with poll module :-p

Talked with Robert and he set this to "needs review" because the above wasn't tested--now it appears to be good.

Heine’s picture

Right. I'll retract my comments above.

Dries’s picture

Status: Reviewed & tested by the community » Fixed

Looks great! Job well done. Committed to CVS HEAD. Thanks all.

m3avrck’s picture

Version: 6.x-dev » 5.x-dev
Status: Fixed » Reviewed & tested by the community

I think this should be committed to 5.x too...

webchick’s picture

Status: Reviewed & tested by the community » Patch (to be ported)

Doesn't apply to 5.

m3avrck’s picture

Status: Patch (to be ported) » Reviewed & tested by the community
FileSize
2.2 KB

Now it applies to 5 :-) I left out the $goto = NULL part since we don't have that notice checking in 5 and that is why the hunk failed because of the extra isset checks.

drumm’s picture

Status: Reviewed & tested by the community » Needs work

Drupal 5 isn't an excuse for sloppy coding. Define your $goto variable.

m3avrck’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
2.21 KB

Ok.

drumm’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 5.

Anonymous’s picture

Status: Fixed » Closed (fixed)
fago’s picture

people interested on this, please have a look at this issue, which tries to further improve this

Crimson’s picture

Component: base system » forms system
Status: Closed (fixed) » Active

The code works well but I didn't see it in Drupal 5.5? Was this scrapped for something else? Or was it not fully committed?

Heine’s picture

Heine’s picture

Status: Active » Closed (fixed)

http://drupal.org/node/139670 is the second attempt to prevent duplicate submissions.

Crimson’s picture

Thanks. It's such a bummer that this isn't solved yet.

How about we implement a time period enforcement between form processes or something like that?

mrgoltra’s picture

subscribing

m3avrck’s picture

Best bet is still the JS method: http://drupal.org/node/107358#comment-487851

This will automatically be built into my new theme that is due out early Feb: http://drupal.org/project/blueprint

Fanaile’s picture

Okay, please forgive me. I'm new to drupal and some of this goes completely over my head.

However, I have just spent a couple of hours reading every comment and visiting every link on this page.

A) I downloaded the formsingle module; it does stop users from submitting duplicate posts. However, when I was testing it out on one test site, (using the aforementioned 'click as many times as you can' method) it also prevented me from even seeing the page (or the comment) until after I left the page and clicked back to it. This, I fear, will just frustrate users and they'll retype their comment/blog post and submit again anyway - which negates the entire use of having the module.

B) Go ahead and call me stupid, but where would I put the code found on your blog? I've read through the post on your blog, and the comments here, and the formsingle page/s, and cannot find where it says to the code - only that to date it is the best solution for this problem? Would I place it into a settings.php file? I realize this might seem like a basic question, but I'd appreciate an answer.

Thanks.

m3avrck’s picture

You would need to place it in your theme.

Luckily, my new base/starter theme, http://drupal.org/project/blueprint which is coming out in a week or so, has this functionality, and a lot more built in, all documented. It will all be documented on my blog too: http://tedserbinski.com/ -- seeing the theme and how it is integrated would probably make the most sense.

http://cvs.drupal.org/viewvc.py/drupal/contributions/themes/blueprint/

See the template.php which includes a JS file which source is in the "scripts" directory. That is how you basically use the JS.

Fanaile’s picture

Thank you for your time and answer :)

I think I will need to wait until your theme is finished. I found the code in your JS files, but couldn't find the lines in your template.php file that called it (I was looking to see a working example). I'll keep checking and will watch for the release :)

I've also bookmarked your blog to help me follow.

Thank you, again!

Naomi

kzuser’s picture

Assigned: Unassigned » kzuser
Category: bug » support
Priority: Normal » Critical
Status: Closed (fixed) » Active

Hi, where exactly put patch code in form.inc?

VM’s picture

Assigned: kzuser » Unassigned
Category: support » bug
Priority: Critical » Normal
Status: Active » Closed (fixed)

changed status and remainder of dropdowns back to what they were before.
_____________________________________________________________________
My posts & comments are usually dripping with sarcasm.
If you ask nicely I'll give you a towel : )

kzuser’s picture

Assigned: Unassigned » kzuser
Priority: Normal » Critical
Status: Closed (fixed) » Active

yeah i read that post but again where put that code in form.inc?

VM’s picture

Assigned: kzuser » Unassigned
Priority: Critical » Normal
Status: Active » Closed (fixed)

A) there is no need to assign this issue to yourself if you aren't providing a patch

B) the method for applying patches can be found in the handbooks, do a search for applying patches. http://drupal.org/search/node/applying+patches

C) Following the links through out the threads, It seems this has been deemed a "won't fix" at core level. see: http://drupal.org/node/139670 (though this may not be the final discussion on this matter)

kzuser’s picture

Category: bug » support
Priority: Normal » Critical
Status: Closed (fixed) » Active

still not understand

same user again post that js method better than others

but i cant understand how to make it in form.inc?

VM’s picture

Category: support » bug
Priority: Critical » Normal
Status: Active » Closed (fixed)

you have two choices when it comes to applying patches:

do it by hand + means add a line - means delete a line. I don't suggest this method

To apply patches the best method is : using the handbook page I pointed you to: http://drupal.org/patch/apply
This page will explain in detail how to apply patches to your files. It is done at the command prompt on your local system. You don't explain what OS you are using. That being said I can't explain further what exactly you need to do for what you are running. There is a few videocasts explaining how to set up cygwin on windows. Which is what I use. The videocast was done by addie @ lullabot, see: http://drupal.org/node/181837

Please stop adjusting the drop downs. It's unnecessary. You can comment on this thread without changing any of the dropdowns and those involved in the issue with get emails and have this post bumped up on their tracker without you doing anything more then commenting.

kzuser’s picture

i use windows on desktop
and linux on hosting

kzuser’s picture

Status: Closed (fixed) » Active
VM’s picture

Status: Active » Closed (fixed)

Heine, closed this issue for a reason, I think you should consider respecting this fact.

You've been pointed to the proper documentation for patching on a windows system, including but not limited to a videocast showing you how to accomplish this task.

apply the patch your local system (windows) using the proper documentation and video cast, Then upload the patched files to your installation. Understand that I can't say whether the patches apply cleanly on a 5.7 drupal, if you are even using the lastest release. That being said, you may have to tweak the patch, or wait for a bonafied solution from core developers on how to avoid this type of problem. Until that time, you may choose, as others have to deal with duplicate postings as drupal.org does. By removing them when found.

kzuser’s picture

Priority: Normal » Critical
Status: Closed (fixed) » Active

im not Heine

drumm’s picture

Priority: Critical » Normal
Status: Active » Closed (duplicate)

That makes more sense without a comma:
Heine closed this issue for a reason, I think you should consider respecting this fact.

This issue is a duplicate of http://drupal.org/node/139670.

kzuser- please stop moving around this issue status. This is not a support forum for applying patches, it is a tool for Drupal contributors to collaborate. Using it improperly wastes time of contributors and could be considered spamming. As mentioned above, there is documentation for applying patches, such as http://drupal.org/patch/apply. More support options are at http://drupal.org/support.

Anonymous’s picture

Could we not prevent multiple form processing during node_save() as follows ..

function node_save(&$node) {
global $user;

$node->is_new = FALSE;

// Apply filters to some default node fields:
if (empty($node->nid)) {
// Insert a new node.
$node->is_new = TRUE;

$node->nid = db_next_id('{node}_nid');
$node->vid = db_next_id('{node_revisions}_vid');
}
else {
// We need to ensure that all node fields are filled.
$node_current = node_load($node->nid);
foreach ($node as $field => $data) {
$node_current->$field = $data;
}
$node = $node_current;

if ($node->revision) {
$node->old_vid = $node->vid;
$node->vid = db_next_id('{node_revisions}_vid');
}
}
..
$ip = $_SERVER['REMOTE_ADDR'] ;
if (!isset($_SESSION[$ip]) || ( isset($_SESSION[$ip]) && (time() - $_SESSION[$ip]['timestamp'] > TIME_INTERVAL))) {
$_SESSION[$ip] = array('timestamp' => time() , 'node' => $node->vid);
} elseif ( time() - $_SESSION[$ip]['timestamp'] < TIME_INTERVAL) {
drupal_goto('node/'.$_SESSION[$ip]['node']);
}
..
}

james2002’s picture

If an article is accessible via two paths

e.g.

http://sciencelatest.com/node/2

and

http://sciencelatest.com/gene-regulation

point to same page as I change the path via url alias.

It will not be good for SEO.

How do I make first post to disappear or is there any SEO module for this kind of duplicated content?

thanks

Web hosting sites

treksler’s picture

With the latest jquery, the javascript becomes

// don't allow users to post content more than once  
$(document).ready(function() {
  $('input:submit').click(function() {
      $(this).siblings('input:submit').hide();            
      $(this).hide();      
      $('<p class="loading">Please wait ...</p>').insertAfter(this).slideDown('fast');                 
  })  
})

what is the best way to ensure that this only gets included in pages that have forms??
i don't want to load jquery on every page if i don't have to

Optalgin’s picture

I've created a module to include this jQuery snippet on selected pages
check it out here

You can select the pages you want the script to load
the default pages are node/add/* and node/*/edit
That covers most node creation forms

Dinesh Kumar Sarangapani’s picture

Version: 5.x-dev » 7.4

yes

VM’s picture

Version: 7.4 » 5.x-dev

shifting version back from the change in #128. Not sure why Dinesh Kumar altered it.

oliverpolden’s picture

Realise this is an old post but to help others with this issue:

The Global Redirect module does this:
https://drupal.org/project/globalredirect

However I am unsure if the Redirect module, which appears to be Global Redirect's successor, will do this also. Comments?
https://drupal.org/project/redirect

oliverpolden’s picture

Issue summary: View changes

Issue summary should link to the duplicate

Tromppa’s picture

I had the same problem on my site and installed this module. https://drupal.org/project/hide_submit. Now it works perfectly!