** SOLVED **
I had failed to require Wordpress in the form processor. Adding this line at the top fixed it (always the simplest thing, right!?):
require_once( explode( "wp-content" , __FILE__ )[0] . "wp-load.php" );
I've created a custom front-end profile for a client's site, and I'm adding a way for other users to favorite that profile. (Please don't suggest anything like BuddyPress or another plugin -- I've tried about a dozen, and none of them have all of the capabilities I need. Thanks.) :)
Anyway.... here is the overview. I hope it's clear. Let's say that USER 1 is viewing the profile of USER 10.
In the database, user 1 has a field called favorite_10 which can be set to "yes" or "no" (or null)
When someone clicks the "Favorite" button in another user's profile, it will run a simple script to change the value from "yes" to "no" or vice-versa
That's it. I think it's a pretty good solution, but the form processing script is breaking at the update_user_meta line.
Here we go.
foreach($sitterlist as $sitteritem) {
$code = 'favorite_'.(esc_html($sitteritem->ID));
$key = esc_html($sitteritem->ID);
$favorite[$key] = get_the_author_meta( $code, $currentuser);
}
$is_favorite=null;
if ($favorite[$usertosearch]=='yes') {
$is_favorite = true;
} else {
$is_favorite = false;
}
?>
<form method="post" action="updatefavorite.php">
<input type="hidden" value="<?php echo $usertosearch; ?>" name="usertosearch" id="usertosearch">
<input type="hidden" value="<?php echo $currentuser; ?>" name="currentuser" id="currentuser">
<input type="hidden" value="<?php echo $is_favorite; ?>" name="is_favorite" id="is_favorite">
<button type="submit" id="favoritebutton" name="favoritebutton"><span>Favorite</span></button>
</form>
And here is updatefavorite.php
<?php
if(isset($_POST['favoritebutton'])) {
$currentuserid = $_POST['currentuser'];
$currentprofileid = $_POST['usertosearch'];
$currentfavorite = $_POST['is_favorite'];
$code = 'favorite_'.$currentprofileid;
if ($currentfavorite) {
$currentfavorite = 'no';
} else {
$currentfavorite = 'yes';
}
update_user_meta($currentuserid,$code,$currentfavorite);
}
header('Location: ' . $_SERVER['HTTP_REFERER']);
?>
After a lot of testing and debugging, I've figured out that it's breaking at update_user_meta ... but I don't know why.
Thank you!
** SOLVED ** I had failed to require Wordpress in the form processor. Adding this line at the top fixed it (always the simplest thing, right!?): require_once( explode( "wp-content" , __FILE__ )[0] . "wp-load.php" );
Related
UPDATE: sorry, thanks for the solutions offered... not really clear how to implement, I think ive not been too clear... if I can understand how to implement the solutions thatd be neat...
Ive also successfully managed to get code working to create a new database table and insert test data but ommited that so its not so complex....
I REALLY want to be able to...
display some content that I can put in success.php (or else where) when the message is sent successfully
that content would say Message Sent - YAY! and then Id like to be able to add, exisiting wp content - some services or products you might be interested in and display them on that same success result page after the message is sent...
maybe there is a better way to redirect users after the message is sent...
then....I also need to save the form data (not yet done) to the new table that I have created (got the table created via plugin), and then display a table of all form submission records in admin panel (not done)
I replaced the content of my main.php file (the plugin's main php file in plugin-name root.
<?php
/** template info etc...
**/
// Find all .php files in the includes dir of my plug in folder.
foreach ( glob( plugin_dir_path( __FILE__ ) . "includes/*.php" ) as $file ) {
include_once $file;
}
?>
and all my files except the main one (which is in the plugin root) are in plugins/plugin-name/includes and are being found - YAY
so my includes/webform.php displays the form nicely it sends an email but I can't get this error or success message via success.php or error.php thing to work.
includes/success.php now looks like this... as per DK's suggestion
<?Php
$Errors = implode(' ', $_SESSION['errMsg']);
echo $Errors; ?>
includes/webform.php now looks like this...
<?php
function d6s_opp_html_form() {
echo '<form action="' . esc_url( $_SERVER['REQUEST_URI'] ) . '" method="post">';
//Form action page is the current url. the form is called by a shortcode that will run functions that are written within this plugin's files, they can be in different files in different folders within the plug in because we have told the plug in to load them in the main plug in file.php horray thay is working..
// other form fields removed to shorten this stakoverflow post
echo '<p>';
echo 'Your Name* <br />';
echo '<input type="text" name="d6s-opp-name" pattern="[a-zA-Z0-9 ]+" value="' . ( isset( $_POST["d6s-opp-name"] ) ? esc_attr( $_POST["d6s-opp-name"] ) : '' ) . '" size="40" placeholder="First & Last name" required />';
// Now using required - is that better than having to check if not empty in success or fail bit????
echo '<p><input type="submit" name="d6s-submitted" value="Send"/></p>';
echo '</form>';
}
//Short code function is here and works GREAT
Then below that in the same file this is the function i figured DK meant that I should put the first part of his solution 1
I Guess this is where I have it wrong still
function deliver_opp_mail() {
// if the submit button is clicked, send the email
if ( isset( $_POST['d6s-submitted'] ) ) {
//sanitise form values so that form data is readable... eg/ if users enter code/script or formatting symbols, it is not missinterpretted as code and is seen as all text.
$name = sanitize_text_field( $_POST["d6s-opp-name"] );
$email = sanitize_email( $_POST["d6s-opp-email"] );
$messagesubject = sanitize_text_field( $_POST["d6s-opp-subject"] );
$messagecontent = esc_textarea( $_POST["d6s-opp-message"] );
$phone = ( $_POST["d6s-opp-phone"] );
// Would like to consider calling form values via global Variables.
$subject = "NEW OPPURTUNITY: $messagesubject";
$d6sdir = plugin_dir_path( __FILE__ );
//Create the Email Body Message using free text and data from the form.
$message = "New Message From: $name \n MESSAGE: $messagecontent \n Return Email: $email \n Return Phone $phone ";
// get the blog administrator's email address, form data is emailed to this email address.
$to = get_option( 'admin_email' );
// Look into setting a to: Email address in WP Admin Console.
$headers = "From: $name <$email>" . "\r\n";
if ( wp_mail( $to, $subject, $message, $headers ) ) {
//maybe this is in the wrong spot, or perhaps this is not the solution I need, but I have tried this in a few different places and can't get it to work..
$Msg = array(
"You have an error",
"Your mail sent succesfully"
);
$_SESSION['errMsg'] = $Msg;
//this take the user to www.mydomain.com/.....wp-content/plugins/my-plugin/includes/success.php - the file is there, but WP theme not found is displayed.
header("Location: $d6sdir/success.php");
exit;
}
}
}
?>
*Dont want to display a message above the form on success or error... future plans for workflow need to take users to a page with no form and other content after they hit submit.
*also using error reporting - seems like something happen or flashes up before the not found from the theme bit is displayed and no other error are reported...
<?Php error_reporting(E_ALL); ini_set('display_errors', 1);
************************** FROM INITAL POST....
Really keen to learn. First post, thanks for help
Purpose of plug in: Create a plugin that I can eventually build into a custom CRM tool for my small business and Learn to code.
*Why is this so not simple...
Solution 1 passing messages to success.php
$Msg = array(
"You have an error",
"Your mail sent succesfully"
);
$_SESSION['errMsg'] = $Msg;
success.php
$Errors = implode(' ', $_SESSION['errMsg']);
echo $Errors;
Solution 2 :
$_SESSION["errMsg"] = "Your mail sent succesfully";
if(isset($_SESSION['errMsg']) AND !empty($_SESSION['errMsg']) ):
echo "<div class='alert danger'>".$_SESSION['errMsg']."</div>";
endif;
Not found solution :
You can use $_SERVER['DOCUMENT_ROOT']; to find root D:/wamp/www
and then full url to page like so :
echo $_SERVER['DOCUMENT_ROOT']."/yourFolder/test.php";
output :D:/wamp/www/yourFolder/test.php
Note : will be nice if you use exit(); right after header("Location:");
I have a problem with SESSIONs in wordpress. I have looked around but could not find any answer. A similar question has been asked in another post on stackaoverflow, but no answer yet.
I have followed this tutorial to build my own FORM:build your own wordpress contact form in 5 minutes.
The problem
To make my form more secure, I decided to generate a session string, and store this string in a SESSION global array (to prevent form hijacking). I send this same string as hidden field when the form is posted. And than I compare this 2 values. However, it seems to me that when the form is submitted, the SESSION is not the same as the one i stored in the SESSION array before submission.
function myfunction() {
ob_start();
$errors = array();
//deliver_mail();
if(isset( $_POST['cf-submitted'] ) ) {
if( $_POST['formtoken1'] !== $_SESSION['formtoken1'] ) {
$errors['token'] = '<div>The form submited is not valid.</div>';
//debug
echo $_SESSION['formtoken1'];//At this point, SESSION[formtoken1] should be same as the one we generated before FORM submit, but it is not!
}
if(empty($errors)) {
//No Errors! Send Email
}
}
$_SESSION['formtoken1'] = md5(uniqid(rand(), true));
$_SESSION['formtoken1'] = htmlspecialchars($_SESSION['formtoken1']);
echo '<form action="' . esc_url( $_SERVER['REQUEST_URI'] ) . '" method="post">';
echo '<input type="text" name="formtoken1" id="formtoken1" value="'. (isset($_SESSION['formtoken1']) ? $_SESSION['formtoken1'] : '') . '" />';
echo '<p><input type="submit" name="cf-submitted" value="Send"></p>';
echo '</form>';
return ob_get_clean();
}
add_shortcode( 'my_contact_form', 'myfunction' );//Create shortcode
When this form is submitted, it always creates error because SESSION variable is not same as the POST variable. When I test this same code outside wordpress on my local xampp server, it works. I will be greatful if anyone can help me. I have also tried session_start() at top of script, but still the same problem.
After some trials, I realized that the post title was displaying on top of the page. I was starting ob_start() inside myfunction(). So, title was outputting before SESSION was started. I changed the code as below, and it works for now. The only problem with this solution is that wordpress is calling ob_start() at every page load. it would be better if it worked inside the myfunction() because it would mean ob_start() is executed only when the short-code is called within a post.
`
//Plugin Name: test form
ob_start(); //put this outside the myfunction()
if(!session_id() ) {
session_start();
}
function myfunction() {
$errors = array();
//deliver_mail();
if(isset( $_POST['cf-submitted'] ) ) {
if( $_POST['formtoken1'] !== $_SESSION['formtoken1'] ) {
$errors['token'] = '<div>The form submited is not valid.</div>';
//debug
echo $_SESSION['formtoken1'];//At this point, SESSION[formtoken1] should be same as the one we generated before FORM submit, but it is not!
}
if(empty($errors)) {
//No Errors! Send Email
}
}
$_SESSION['formtoken1'] = md5(uniqid(rand(), true));
$_SESSION['formtoken1'] = htmlspecialchars($_SESSION['formtoken1']);
echo '<form action="' . esc_url( $_SERVER['REQUEST_URI'] ) . '" method="post">';
echo '<input type="text" name="formtoken1" id="formtoken1" value="'. (isset($_SESSION['formtoken1']) ? $_SESSION['formtoken1'] : '') . '" />';
echo '<p><input type="submit" name="cf-submitted" value="Send"></p>';
echo '</form>';
return ob_get_clean();
}
add_shortcode( 'my_contact_form', 'myfunction' );//Create shortcode`
I am using Screets Wordpress Sessions plugin and it works really well. The problem I am having is this, I am going to manage my site users out of wordpress through a different table and etc. I have my signup form working, were it sends out confirmation emails to stop spam. The issue I am having is that my simple form:
mysql_connect("localhost", "%username%", "%password%") or die(mysql_error()); // Connect to database server(localhost) with username and password.
mysql_select_db("%database%") or die(mysql_error()); // Select registration database.
if(isset($_POST['name']) && !empty($_POST['name']) AND isset($_POST['password']) && !empty($_POST['password']) AND isset($_POST['name']) && !empty($_POST['name'])){
$username = mysql_escape_string($_POST['name']);
$password = mysql_escape_string(md5($_POST['password']));
$search = mysql_query("SELECT username, password, active FROM %table% WHERE username='".$username."' AND password='".$password."' AND active='1'") or die(mysql_error());
$match = mysql_num_rows($search);
if($match = 1){
$msg = 'Login Complete! Thanks';
//$email = $row['EmailAddress'];
//;
//$_SESSION['EmailAddress'] = $email;
//$_SESSION['LoggedIn'] = 1;
$session->set_userdata( 'username', $username);
header ("Location: /");
}else{
$msg = 'Login Failed!<br /> Please make sure that you enter the correct details and that you have activated your account.';
}
}
?>
<!-- stop PHP Code -->
<!-- title and description -->
<h2>Login Form</h2>
<p>Please enter your name and password to login</p>
<?php
if(isset($msg)){ // Check if $msg is not empty
echo '<div class="statusmsg">'.$msg.'</div>'; // Display our message and add a div around it with the class statusmsg
} ?>
<!-- start sign up form -->
<form action="" method="post">
<label for="name">Username:</label>
<input type="text" name="name" value="" />
<label for="password">Password:</label>
<input type="password" name="password" value="" />
<input type="submit" class="submit_button" value="login" />
</form>
auto redirects to my wordpress login which is not what I want. I have been told before to use wp_users but I really don't want to use that or a plugin. Any ideas to get it to work the way I need to?
EDIT: To better clarify the question, anyone who clicks submit is redirected to wp-login.php. The page is not even following my SQL connect to check and actually create a session. Any ideas?
The better way is using Ajax to send and sava your data. First, include these codes below into your functions.php:
/**
* User Log in
*/
function sc_login( $params ){
global $wpdb;
// You can check user here
$sql = $wpdb->prepare(
'
SELECT COUNT(*) FROM ' . $wpdb->prefix . ' users
WHERE `email` = %d
AND `password` = %s
',
$params['user_login'], $params['user_password']
);
$auth = $wpdb->get_var( $sql );
if( $auth ) {
// Log in system
} else {
// Username or password is wrong
}
}
/**
* Ajax Submit
*/
function sc_ajax_callback() {
// run function
$response = call_user_func($_POST['func'], $_POST);
// response output
header( "Content-Type: application/json" );
echo json_encode($response);
exit;
}
// Ajax Requests
add_action( 'wp_ajax_nopriv_sc_ajax_callback', 'sc_ajax_callback' );
add_action( 'wp_ajax_sc_ajax_callback', 'sc_ajax_callback' );
Create an Ajax.js file into your theme and add these codes:
(function ( $ ) {
jQuery(document).ready(function() {
/**
* Log in
*/
$('#sc_login_form').submit(function() {
jQuery.ajax({
type: 'POST',
url: sc_ajax.ajaxurl,
data: $('#sc_login_form').serialize(),
dataType: 'json',
success: function(response, textStatus) {
// Show errors?
if( response.errors ){
// YOU CAN SHOW ERRORS HERE IF YOU WANT
// for instance, "Email is required!"
// successful log in
} else {
// refresh page (HERE IS THE POINT)
window.location.href = sc_ajax.REDIRECT_URL;
}
console.log(response);
}
});
return false;
});
});
}( jQuery ));
Now we need to localize Ajax script. Open header.php and add these codes before wp_head(); function. Don't forget to change REDIRECT_URL variable below:
// insert jquery
wp_enqueue_script( 'jquery' );
// ajax requests
wp_enqueue_script( 'sc-ajax-request', get_template_directory_uri() . '/Ajax.js', array( 'jquery' ) );
// prepare your ajax custom vars
$ajax_vars = array(
'REDIRECT_URL' => '', // (!) CHANGE THIS WITH URL WHERE YOU WANT TO GO
'ajaxurl' => admin_url( 'admin-ajax.php' )
);
wp_localize_script( 'sc-ajax-request', 'sc_ajax', $ajax_vars );
And last step is edit your form like this:
<form id="sc_login_form">
<input type="hidden" name="action" value="sc_ajax_callback" />
<input type="hidden" name="func" value="sc_login" />
Email:
<input type="text" name="user_login" />
Password:
<input type="password" name="user_password"/>
<input type="submit" value="Log in" />
</form>
I hope this helps.
Ah yes. WordPress's Rewrite API is stepping on you. When you submit your form, the script attempts to post back to itself. WordPress takes http://your-site.com/login and rewrites
it to http://your-site.com/wp-login.php.
Here's how to fix it.
Create a page in WordPress, name it login, then assign the custom page template to it you'll create in this next step.
Now you'll need to create a custom page template, place it in your currently active theme folder, and put the following code in it:
<?php
/*
* Template Name: Login
*/
// Put the code for your login here.
?>
Finally, add this next line to your theme's functions.php:
add_rewrite_rule( '^login/?$', 'index.php?page_name=$matches[1]', 'top' );
That should do the trick nicely. :)
ive written a php function that displays a random equation. if the correct answer is not provided, the submission fails. the equation is like so:
[ random digit or text number ] [ randomly selects +,-,x ] [ random digit or text number ]= ?
so you might see:
8+2=?, or seven - 4 = ?, etc
ive tested this manually and it seems to work beautifully. i cannot get around answering the CAPTCHA correctly. yet something or someone IS posting spam despite this CAPTCHA. so my question is, are there programs out there that can solve this problem?
here is my form:
<form action="scripts/handler_post.php" method="post" id="gb_form">
<h3>Leave us a comment:</h3><br />
<div id="form_msg"><?php echo $msg; ?></div>
<input type="text" name="name" value="Your Name" />
<textarea name="message">Your Message</textarea>
<?php include('includes/bmw_captcha.php'); ?>
<div style="color:red; font-size:90%;">*What does <?php echo $array_num1[1] . " " . $array_calculation[0] . " " . $array_num2[1] . " = "; ?>
<input type='text' maxlength='2' name='captcha' style="color:#640513; width:25px;" />?</div>
<div><span style="font:italic 90% Arial; color:#666;">(For security purposes, please answer this CAPTCHA problem.)</span></div>
<input type="hidden" name="captcha_answer" value="<?php echo $array_calculation[1]; ?>" />
<input type="submit" name="submit_button" value="Post" />
</form>
here is the script that handles the form:
// submitted values
$name = clean_string( $_POST['name'] );
$message = clean_string( $_POST['message'] );
$captcha = clean_string( $_POST['captcha'] );
$captcha_ans= clean_string( $_POST['captcha_answer'] );
// check if name var is empty or contains digits
if( empty($name) || (strcspn( $name, '0123456789' ) != strlen( $name )) )
{ header( 'Location: /guestbook.php?msg=n' ); }
else if( empty($message) )
{ header( 'Location: /guestbook.php?msg=m' ); }
else if( empty($captcha) || $captcha != $captcha_ans )
{ header( 'Location: /guestbook.php?msg=cap' ); }
else
{
$query = "
INSERT INTO $table_posts ( id, name, message, timestamp )
VALUES( 0, \"$name\", \"$message\", now() )
";
$result = $db_connect->query( $query ); // execute the query
if( $result )
{
header('Location: ../guestbook.php?msg=1');
}
else
header('Location: ../guestbook.php?msg=2');
}
You should store the answer to the captcha in a session variable instead. Sending it in clear text through the form makes it possible for a robot to just set the field to whatever value it wants. Bots are usually setting all unknown fields to some string, like ijhsg87dfb34 so if it sets both the captcha and the captcha_answer field to the same value it will succeed!
A very simple approach is to use a hidden field, and in the script that handles the POST you check if that field was filled in, if it was then it was a BOT etc as a normal user would never see that field but BOTs etc just blindly fill in every field.
You can try non-captcha secure form. Check this
http://docs.jquery.com/Tutorials:Safer_Contact_Forms_Without_CAPTCHAs
I'm still relatively new to PHP. I'm trying to build a privacy settings page for members to opt out of automatic emails for triggered events (i.e. private message notification). I want the checkbox set automatically based on the database setting. As of now, the form does update the database correctly, but the checkbox status does not show the correct setting unless the Submit button is pressed twice, or the page is reloaded. Setting would be '0' for unchecked, '1' for checked. I'd love to use Ajax or jQuery to handle this, but I don't know those at all.
privacysettings.php
<?php
$id = "";
$pm_mail_able = "";
$pm_email = "";
if (isset($_GET['id'])) {
$id = preg_replace('#[^0-9]#i', '', $_GET['id']); // filter everything but numbers
} else if (isset($_SESSION['idx'])) {
$id = $logOptions_id;
} else {
header("location: index.php");
exit();
}
//query to get checkbox status
$sql = mysql_query("SELECT * FROM members WHERE id='$id'");
while($row = mysql_fetch_array($sql)){
$pm_mail_able = $row['pm_mail_able'];
}
switch ($pm_mail_able) {
case 0:
$pm_setting = NULL;
break;
case 1:
$pm_setting = "checked=\"checked\"";
break;
}
if(isset($_GET['pm_email']) && !empty($_GET['pm_email'])) {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='1' WHERE id='$id'");
} else {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='0' WHERE id='$id'");
}
?>
<html>
Email Notifications<br />
<form name="testform" method="get" action="PvResult.php">
When a friend sends me a private message
<input type="checkbox" name="pm_email" value="on"<?php echo $pm_setting;?> />
<br /><br />
<input type="submit" value="Submit" />
</form>
</html>
PvResult.php
<?php
$url = 'http://www.mywebsite.com';
//If the form isn't submitted, redirect to the form
if(!isset($_GET['Submit']))
header('Location: '.$url.'/privacysettings.php');
//Redirect to the correct location based on form input
$pm_email = $_GET['pm_email'];
$url .= '/privacysettings.php?pm_email='.$pm_email;
header('Location: '.$url);
?>
Okay, hopefully this won't just answer your question, but give you a few best practices you might want to consider.
You can combine these two scripts into one relatively easily. Also, I'd highly suggest using a POST instead of GET; GET is very limited and is not intended to submit data like you're using it. If you're going to be changing data in a back-end store, using GET will bite you. Maybe not today, maybe not tomorrow, but it will, trust me.
You really should consider moving to PDO instead of the mysql_ functions. PDO is a lot better in handling parameterized queries, which you really should have here for better security, and it's more portable if someday you want to move to a different database system.
I'm still a little hazy on how your app is getting the $id. Most apps get it from a $_SESSION variable, making sure that the user has successfully validated a login. If you're not doing that, please do. You might want to thoroughly digest this article, it's got a lot of juicy best practices regarding authentication and "remember me"-type functionality.
Here's a bit of a rewrite. I haven't actually tested it, but it should give you a pretty good idea on where to go with your immediate needs. If it throws any errors (remember the disclaimer: I haven't actually tested it!), let me know and I'll try to debug it.
<?php
$message = '';
$pm_setting = '';
$id = 0;
// Put your $id retrieval logic here. It should look something like:
if (isset($_SESSION['id'])) {
$id = $_SESSION['id'];
if (!preg_match('/^\\d{1,10}$/', $id) > 0) {
// Someone is trying to hack your site.
header("location: scum.php");
exit();
}
$id = intval($id);
}
// Quick security note: You might want to read up on a topic called
// session hijacking if you want to ensure your site is secure and
// this $id isn't spoofed.
if (isset($_POST['Submit'])) {
// The form is being submitted. We don't need to read the current
// pm_mail_able setting from the database because we're going to
// overwrite it anyway.
if ($id > 0) {
$pm_mail_able = 0;
if (isset($_POST['pm_email']) && $_POST['pm_email'] === 'on') {
$pm_mail_able = 1;
$pm_setting = 'checked ';
}
$query = 'UPDATE members SET pm_mail_able='.$pm_mail_able.
' WHERE id = '.$id;
mysql_query($query);
// Another quick security note: You REALLY need to consider
// updating to PDO so that you can bind these parameters
// instead. The mysql_ functions are probably going to be
// deprecated soon anyway.
if (mysql_affected_rows($query) > 0)
$message = '<p style="color: #00a000;">Settings saved!</p>';
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else {
// This is the first load of the form, we need to just display it
// with the existing setting.
if ($id > 0) {
$query = mysql_query('SELECT * FROM members WHERE id = '.$id);
if (($row = mysql_fetch_array($query, MYSQL_ASSOC)) !== FALSE)
if ($row['pm_mail_able'] === 1) $pm_setting = 'checked ';
}
}
?>
<html>
<body>
<?= $message ?>
<!-- Without action parameter, form submitted to this script. -->
<form name="testform" method="post">
E-mail notifications<br />
<input type="checkbox" name="pm_email" value="on" <?= $pm_setting ?>/>
When a friend sends me a private message
<br /><br />
<input type="submit" value="Submit" />
</form>
</body>
</html>
Try to do these settings and see if it will work:
1) You need to add an space between "on" and "checked=checked"
<input type="checkbox" name="pm_email" value="on" <?php echo $pm_setting;?> />
2) You have to reference the submit button by its name, not its value
<input type="submit" name="Submit" value="Send" />
3) When the setting is "0", set $pm_setting as a empty string, instead of NULL
case 0:
$pm_setting = '';
4) Maybe there is some problem with $_GET['pm_email'] and the else is always being executed
5) If the things work when you press the Submit button twice, it means that the form is passing some GET var that make the code work, so try to discover what var is this