03/03/08

Permalink 11:37:49 pm, by robertc Email , 846 words, 1904 views   English (UK)
Categories: Server Side Web Development Share on reddit Share on digg Share on del.icio.us Share on ma.gnolia.com Share on StumbleUpon

Fixing Jack's formmail.php for register_globals = off

For many years now, I've used various versions of Jack's FormMail.php to handle simple form submissions on various websites, mostly 'contact us' forms. The script has gotten a little more sophisticated with time, but it's still one of the simpler ways of making a website 'interactive.'

The website at work uses it to send the marketing department emails when someone fills in the contact us form. The form is somewhat sophisticated, in that it presents different information depending on a few parameters in the URL, and passes formmail.php a different subject for the email depending on what configuration it's in. It also passes a redirect URL in a hidden field, so the user is redirected to a 'thanks for contacting us' page after submitting the form. Google Analytics is set up so that any hits on the 'thanks' page after viewing the contact page counts as a Goal. And this is where I spotted the problem - as I checked through the Analytics stats I noticed we hadn't achieved any goals since the middle of last week, although a day or two here and there without any is fairly common five on the trot is pretty rare.

My first step was to go to the contact form and try submitting it, the email duly arrived in the correct mailbox but the script didn't redirect to the thanks page. So first mystery solved, no hits on the thanks page means no goals on Analytics, but the marketing department hadn't noticed because they were still getting emails. I messed around with some of the different configurations of the contact page but none of them redirected as intended. Then I realised that all the emails had the same subject, and that was the default one given by formmail.php when it doesn't get passed a subject, though the values in the form fields were appearing in the email correctly, so it wasn't like the information wasn't getting passed though.

I checked the web host's page and discovered that they had recently updated the PHP config on the server, this in order to support PHP v5. There was a new option in CPanel to select the default version of PHP, so I went and set it to v4 in case formmail was incompatible with the newer release. It didn't make any difference though, so I started looking at formmail.php itself in detail.

The first thing I noticed was that the redirect functionality required register_globals to be enabled. Although my PHP configuration page claimed that register_globals was enabled, the behaviour of the script indicated that it wasn't. Unsurprisingly, the subject field also expected register_globals to be enabled, as did several other fields which I wasn't using, but the code which builds the email uses $HTTP_POST_VARS so works fine without.

If you've managed to read this far without falling asleep and you know what register_globals is, then you now have enough information to fix the problem yourself and there's no need to torture yourself any further. If you currently have no idea what I'm on about, I'm now going to try and explain and then show you how to edit your script to fix the problem. register_globals is a configuration setting for the PHP interpreter, if it's set to on then PHP will helpfully make any parameters passed into the script global variables. Parameters are the bits in the URL after the question mark, or fields in a form. This can be quite handy when you're slapping together a quick script, but is also very dangerous because, if you're not careful, you can create easy opportunities for hackers to do nasty things. For this reason, register_globals = on has long been discouraged in the PHP community, unfortunately many useful scripts were written in the days before anyone realised it was an issue, so web hosts usually provide a way turn it back on even if it's not enabled by default.

However, today we're going to make formmail.php work properly with register_globals = off. You're going to need to open the formmail.php script in a text editor - Notepad will do fine. First we shall fix the redirect issue, find the following lines near the end of the file:

if ($redirect) {
   header("Location: $redirect");
   exit; 

We're going to replace $redirect, which is trying to access the global variable, with $_POST['redirect'], like so:

if (isset($_POST['redirect'])) {
   header("Location: ". $_POST['redirect']);
   exit;

The same trick works with the subject and email address, scroll up a few lines and find this:

mail_it(stripslashes($content), ($subject)?stripslashes($subject):"Form Submission", $email, $recipient); 

Replace it with:

mail_it(stripslashes($content), isset($_POST['subject'])?stripslashes($_POST['subject']):"Form Submission", $_POST['email'], $recipient);

Now upload your new version to the server and you should find things start working as before. As you can see the general rule is to replace $variable with $_POST['variable'], notice that I didn't change $recipient because I always hard code that value at the top of the script as a security precaution.

Technorati tags for this post:

Trackback address for this post:

http://www.boogdesign.com/b2evo/th1srv/trackback.php/222

Comments, Trackbacks, Pingbacks:

Comment from: Rebecca [Visitor] Email
You also have to replace the HTTP_POST_VARS with $_POST because HTTP_POST_VARS isn't supported.
PermalinkPermalink 22/03/08 @ 05:45
Comment from: robertc [Member] Email · http://www.boogdesign.com/
Thanks for pointing that out Rebecca - I think it is still supported in PHP5 but you have to turn it on explicitly in php.ini (see also this excellent blog post to turn it back on in .htaccess).
PermalinkPermalink 22/03/08 @ 10:03
Comment from: Clayton Moore [Visitor] Email
Thank you! I have been troubleshooting this formmail for weeks. Once I applied the above mentioned corrections, as well as the $_POST replacement, the webform transmitted the form fields, which it did not send before. I am utilizing a webhosting company running PHP version 5. I sincerely appreciate post like these, it saved a huge headache.

For reference to anyone else. My form did send email and subject - however my form fields such as customer name, phone number and comments did not come through email.

NOW IT WORKS!
PermalinkPermalink 03/04/08 @ 21:14
Comment from: robertc [Member] Email · http://www.boogdesign.com/
Hi Clayton, thanks for taking the time to make a comment, I'm glad I could help!
PermalinkPermalink 04/04/08 @ 02:02
Comment from: geekgirly [Visitor] Email
THANK YOU. FROM THE BOTTOM OF MY GEEK HEART. For those of you hosting with siteground, this is an EXCELLENT fix. You completely ROCK, Robert. My headaches are gone over this issue.
PermalinkPermalink 26/04/08 @ 00:22
Comment from: robertc [Member] Email · http://www.boogdesign.com/
No problem geekgirly, glad I could help. This blog post certainly seems to have hit on common issue :)
PermalinkPermalink 26/04/08 @ 16:50
Comment from: Jason [Visitor] Email · http://www.xltiger.com
Hey Robert,
Great stuff. That first peice of code squashed the redirect issue I was having. Many kudos to you!!!

Jason
PermalinkPermalink 28/04/08 @ 03:39
Comment from: Al [Visitor] Email
Thanks, that fixed up exactly my problem!
Moved to PHP 5 server which broke the script, and now it works. Thanks :)
PermalinkPermalink 04/05/08 @ 03:27
Comment from: Dan Wilkinson [Visitor] Email · http://wilkinsonweb.com
Thanks for these tips...they work great. I appears that the "Required Fields" functionality of the script still doesn't work though...any ideas?
PermalinkPermalink 21/05/08 @ 14:41
Comment from: robertc [Member] Email · http://www.boogdesign.com/
The required fields are a bit more complicated, because they're subject to some processing. The lines you need to worry about are these ones:
if ($required)
$require = $required;
// handle the required fields
if ($require) {
// seperate at the commas
$require = ereg_replace( " +", "", $require);
$required = split(",",$require);
I've not tested this, so beware, but I think it should look something like :
// handle the required fields
if (isset($_POST['require'])|isset($_POST['required'])) {
// seperate at the commas
$require = ereg_replace( " +", "", isset($_POST['required'])?$_POST['required']:$_POST['require']);
$required = split(",",$require);
The if logic doesn't work when $require is no longer a global variable, so you have to munge that a bit, but you don't have to replace every instance of $require and $required because the variables get re-assigned in the lines above. Give it a go and see how it works, but keep a backup of your original because, as I said above, this is just off the top of my head and I've not tried it in a working script.

Rob

PS. I've tested it now (several hours later) and updated the code above (got a few brackets wrong), seems to work OK.
PermalinkPermalink 21/05/08 @ 18:04
Comment from: Dan Wilkinson [Visitor] Email · http://wilkinsonweb.com
Awesome! Thanks!
PermalinkPermalink 28/05/08 @ 05:41
Comment from: Florian [Visitor] Email
Anyone knows how to fix the file upload? THANK YOU!
PermalinkPermalink 29/05/08 @ 09:50
Comment from: David Fulp [Visitor] Email
I'm now receiving DUPLICATE (2) emails of every submission... everything else is working great... thanks to all for your help... any ideas on fixing the dupes?

Regards,
Dave
PermalinkPermalink 10/06/08 @ 23:06
Comment from: robertc [Member] Email · http://www.boogdesign.com/
Can you get see the headers of the emails you're receiving? This might be under 'details' or 'properties' or something like that. That should indicate why you're getting two of everything, possibly you're just adding the same email address in two places.

Rob
PermalinkPermalink 10/06/08 @ 23:17
Comment from: Balitas [Visitor] Email
In my case not work the redirect only. Help please robertc I do all the things you mentioned but not work for me :( Check www.balitas.com/espanol/index.html and fill the form below. Here my php info: http://www.balitas.com/espanol/info.php
PermalinkPermalink 17/06/08 @ 23:19
Comment from: robertc [Member] Email · http://www.boogdesign.com/
Hi Balitas. Can you post what you have at in your formmail.php from the if (isset($_POST['redirect'])) { line onwards?

Rob
PermalinkPermalink 17/06/08 @ 23:36
Comment from: Balitas [Visitor] Email
Sure :)

if (isset($_POST['redirect'])) {
header("Location: ".$_POST['redirect']);
exit;
PermalinkPermalink 18/06/08 @ 16:04
Comment from: robertc [Member] Email · http://www.boogdesign.com/
Hmm, can't see anything obvious wrong. Are you getting any error messages in the logs? One thing you can try, if you don't have to redirect to different pages for different forms, is simply to hardcode the redirect. Take the whole if condition out and just end the script with:
header("Location: http://www.balitas.com/espanol/indexok.html");
exit;
Rob
PermalinkPermalink 18/06/08 @ 18:00
Comment from: Balitas [Visitor] Email
Dear robertc unfortunately not work :(

Please download the formmail.php here www.balitas.com/espanol/formmail.zip to test it.

Regards.
PermalinkPermalink 19/06/08 @ 18:46
Comment from: robertc [Member] Email · http://www.boogdesign.com/
Hi Balitas - what's happened is, you've fixed the wrong $redirect, scroll right to the bottom of the script, line 410, and make the changes with isset and $_POST['redirect'] there.

Rob
PermalinkPermalink 23/06/08 @ 23:40
Comment from: Balitas [Visitor] Email
Is still works as I mentioned.

Regards.
PermalinkPermalink 24/06/08 @ 17:43
Comment from: robertc [Member] Email · http://www.boogdesign.com/
Hi Balitas, sorry it took me so long to get round to updating my blog again. When you applied the fix to the lines further down you forget to change the if ($redirect) to if (isset($_POST['redirect'])) - everything else was correct!

Rob
PermalinkPermalink 02/07/08 @ 00:18

Leave a comment:

Your email address will not be displayed on this site.
Your URL will be displayed.

Allowed XHTML tags: <p, ul, ol, li, dl, dt, dd, address, blockquote, ins, del, span, bdo, br, em, strong, dfn, code, samp, kdb, var, cite, abbr, acronym, q, sub, sup, tt, i, b, big, small>
(Line breaks become <br />)
(Set cookies for name, email and url)
(Allow users to contact you through a message form (your email will NOT be displayed.))

Hot Topics

Popular

boogdesign posts

Longer posts on standards based web design, portable web development and Linux, intermingled with some stuff on my other nerd interests.

Search

Syndicate this blog XML

  • RSS 0.92 Posts RSS 0.92 Comments
  • RSS 1.0 Posts RSS 1.0 Comments
  • RSS 2.0 Posts RSS 2.0 Comments
  • Atom Posts Atom Comments
What is RSS?

License info

Creative Commons License
This work is licensed under a Creative Commons Attribution-Share Alike 2.5 License.

powered by
b2evolution

get hCard