Google Forms - Version 0.32

Version Description

No known upgrade issues.

Download this release

Release Info

Developer mpwalsh8
Plugin Icon wp plugin Google Forms
Version 0.32
Comparing to
See all releases

Code changes from version 0.30 to 0.32

Files changed (5) hide show
  1. index.php +2 -2
  2. readme.txt +24 -5
  3. wpgform-core.php +229 -87
  4. wpgform-debug.php +175 -0
  5. wpgform-options.php +44 -4
index.php CHANGED
@@ -4,8 +4,8 @@
4
  * Plugin Name: WordPress Google Form
5
  * Plugin URI: http://michaelwalsh.org/wordpress/wordpress-plugins/wpgform/
6
  * Description: Add Google Forms to a WordPress web site. Display a Google Form directly into your posts, pages or sidebar. Style the Google Form to match your existing theme and display a custom confirmation page after form submission.
7
- * Version: 0.30
8
- * Build: 0.30.$WCREV$
9
  * Last Modified: $WCDATE$
10
  * Author: Mike Walsh
11
  * Author URI: http://www.michaelwalsh.org
4
  * Plugin Name: WordPress Google Form
5
  * Plugin URI: http://michaelwalsh.org/wordpress/wordpress-plugins/wpgform/
6
  * Description: Add Google Forms to a WordPress web site. Display a Google Form directly into your posts, pages or sidebar. Style the Google Form to match your existing theme and display a custom confirmation page after form submission.
7
+ * Version: 0.31
8
+ * Build: 0.31.$WCREV$
9
  * Last Modified: $WCDATE$
10
  * Author: Mike Walsh
11
  * Author URI: http://www.michaelwalsh.org
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: mpwalsh8
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DK4MS3AA983CC
4
  Tags: Google Forms, Google Docs, Google, Spreadsheet, shortcode, forms
5
  Requires at least: 3.0
6
- Tested up to: 3.3.1
7
- Stable tag: 0.30
8
 
9
  Embeds a published, public Google Form in a WordPress post, page, or widget.
10
 
@@ -59,6 +59,18 @@ Yes, there are two ways to change the style (aka apearance) of the form.
59
 
60
  Google Forms include plenty of [CSS](http://en.wikipedia.org/wiki/Cascading_Style_Sheets) hooks. Refer to the **CSS** section for further details on styling the form. There are also some CSS solutions posted to questions users have raised in the Tips and Tricks section of [this page](http://michaelwalsh.org/wordpress/wordpress-plugins/wpgform/tips-and-tricks/).
61
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  = Do you have a demo running? =
63
  Yes, see a demo here: [Demo of WordPress Google Form plugin](http://michaelwalsh.org/wordpress/wordpress-plugins/wpgform/)
64
 
@@ -82,9 +94,6 @@ label.ss-q-title:after {
82
  }
83
  `
84
 
85
- = No matter what I do, I always get the "Unable to retrieve Google Form. Please try reloading this page." error message. Why is this? =
86
- Validate that the WordPress HTTP API is working correctly. If you are seeing HTTP API errors on the WordPress Dashboard or when you attempt to access the plugin repository through the Dashboard, the WordPress Google Form will likely fail too. It requires the WordPress HTTP API to be working. With some free hosting plans, ISPs disable the ability to access remote content.
87
-
88
  = I don't like the redirection behavior of the custom confirmation, can you change it back to the way it worked in v0.10? =
89
  Unfortunately not. I understand that the older behavior is preferable as it looks cleaner for the end user however there is no way to support multi-page Google Forms using the old model. The requirement to support multi-page Google Forms is a higher priority than the older confirmation model based on the overwhelming feedback received to support multi-page forms. In v0.26 a new confirmation behavior was introduced which uses AJAX to update the page with the content from the custom confirmation page. In v0.27 the redirection mechanism has returned to be the default behavior but if the AJAX methodology is preferred, it is available by setting the `style='ajax'` attribute within the shortcode.
90
 
@@ -183,6 +192,16 @@ No known upgrade issues.
183
 
184
  == Changelog ==
185
 
 
 
 
 
 
 
 
 
 
 
186
  = Version 0.30 =
187
  * Changed generated CSS to limit the possibility that it is affected by 'the_content' or 'wpautop' filters resulting in CSS errors. This rare situation would prevent the custom CSS from being applied correctly.
188
 
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DK4MS3AA983CC
4
  Tags: Google Forms, Google Docs, Google, Spreadsheet, shortcode, forms
5
  Requires at least: 3.0
6
+ Tested up to: 3.4.1
7
+ Stable tag: 0.32
8
 
9
  Embeds a published, public Google Form in a WordPress post, page, or widget.
10
 
59
 
60
  Google Forms include plenty of [CSS](http://en.wikipedia.org/wiki/Cascading_Style_Sheets) hooks. Refer to the **CSS** section for further details on styling the form. There are also some CSS solutions posted to questions users have raised in the Tips and Tricks section of [this page](http://michaelwalsh.org/wordpress/wordpress-plugins/wpgform/tips-and-tricks/).
61
 
62
+ = Why do I get a 403 error? =
63
+
64
+ There a number of reasons to get a 403 error but by far the most common one encountered so far is due to ModSecurity being installed by your web hosting provider. Not all providers deploy ModSecurity but enough do that it comes up every once in a while. If your provider is running ModSecurity and your version of the plugin is v0.30 or lower, you will likely see odd behavior where when the form is submitted, the page is simply rendered again and the data is never actually sent to Google. There isn't any error message to indicate what might be wrong.
65
+
66
+ Version 0.32 fixes this problem for *most* cases but there is still a chance that it could crop up. If your provider has enabled ModSecurity AND someone answers one of the questions on your form with a URL (e.g. http://www.example.com), then very likely ModSecurity will kick in an issue a 403 error. The plugin is now smart enough to detect when the error is issued and let you know what is wrong. Unfortunately there isn't currently a solution to allow URLs as responses when ModSecurity issues a 403 error.
67
+
68
+ = No matter what I do, I always get the "Unable to retrieve Google Form. Please try reloading this page." error message. Why is this? =
69
+
70
+ 1. The most common reason for this error is from pasting the Google Form URL into the WordPress WYSIWYG Editor while in "Visual" mode. When you paste the URL, the Visual Editor recognizes at a link and wraps the text in the apprpriate HTML tags so the link will work. Visually you'll trypically see the URL in a different color than the rest of the short code text. If this happens, simply click anywhere in the link and use the "Break Link" icon (broken chain) on the tool bar to remove the link. The other alternative is to toggle to HTML mode and manually remove the HTML which is wrapped around the URL.
71
+
72
+ 1. Validate that the WordPress HTTP API is working correctly. If you are seeing HTTP API errors on the WordPress Dashboard or when you attempt to access the plugin repository through the Dashboard, the WordPress Google Form will likely fail too. It requires the WordPress HTTP API to be working. With some free hosting plans, ISPs disable the ability to access remote content.
73
+
74
  = Do you have a demo running? =
75
  Yes, see a demo here: [Demo of WordPress Google Form plugin](http://michaelwalsh.org/wordpress/wordpress-plugins/wpgform/)
76
 
94
  }
95
  `
96
 
 
 
 
97
  = I don't like the redirection behavior of the custom confirmation, can you change it back to the way it worked in v0.10? =
98
  Unfortunately not. I understand that the older behavior is preferable as it looks cleaner for the end user however there is no way to support multi-page Google Forms using the old model. The requirement to support multi-page Google Forms is a higher priority than the older confirmation model based on the overwhelming feedback received to support multi-page forms. In v0.26 a new confirmation behavior was introduced which uses AJAX to update the page with the content from the custom confirmation page. In v0.27 the redirection mechanism has returned to be the default behavior but if the AJAX methodology is preferred, it is available by setting the `style='ajax'` attribute within the shortcode.
99
 
192
 
193
  == Changelog ==
194
 
195
+ = Version 0.32 =
196
+ * New option to control Bcc to blog admin when using email notification. By default this option is enabled to allow plugin to behave as it has in prior versions.
197
+ * Fixed bug in processing default plugin settings which are on by default. New options which are on by default were not recognized.
198
+ * Fixed activation bug which didn't set all of the default settings correctly.
199
+
200
+ = Version 0.31 =
201
+ * Separation of rendering and processing of the Google Form to better work with sites that make multiple calls to `do_shortcode()`.
202
+ * Added a new option to enable "debug". Enabling debug will add some hidden information to the page. The visibility of this hidden information can be toggled on an off using a link which is inserted into the page above form. This debug information is useful for chasing down odd behavior, in particular 403 errors which tend not to be real obvious.
203
+ * Significant change to better support servers which have Apache ModSecurity enabled. Sites which employ ModSecurity may result in 403 errors which are hard to determine because in most cases, the page with the form on it will simply be displayed again. The plugin now tries to detect 403 errors and when found, will issue a message as part of the form rendering.
204
+
205
  = Version 0.30 =
206
  * Changed generated CSS to limit the possibility that it is affected by 'the_content' or 'wpautop' filters resulting in CSS errors. This rare situation would prevent the custom CSS from being applied correctly.
207
 
wpgform-core.php CHANGED
@@ -24,6 +24,19 @@ define('WPGFORM_CONFIRM_AJAX', 'ajax') ;
24
  define('WPGFORM_CONFIRM_LIGHTBOX', 'lightbox') ;
25
  define('WPGFORM_CONFIRM_REDIRECT', 'redirect') ;
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  /**
28
  * wpgform_init()
29
  *
@@ -36,15 +49,17 @@ function wpgform_init()
36
  $wpgform_options = wpgform_get_plugin_options() ;
37
 
38
  if ($wpgform_options['sc_posts'] == 1)
39
- add_shortcode('wpgform', 'wpgform_shortcode') ;
40
 
41
  if ($wpgform_options['sc_widgets'] == 1)
42
  add_filter('widget_text', 'do_shortcode') ;
43
 
44
- add_action('template_redirect', 'wpgform_head') ;
45
  add_filter('the_content', 'wpautop');
 
46
  }
47
 
 
 
48
  /**
49
  * Returns the default options for wpGForm.
50
  *
@@ -61,6 +76,9 @@ function wpgform_get_default_plugin_options()
61
  ,'donation_message' => 0
62
  ,'email_format' => WPGFORM_EMAIL_FORMAT_PLAIN
63
  ,'browser_check' => 0
 
 
 
64
  ) ;
65
 
66
  return apply_filters('wpgform_default_plugin_options', $default_plugin_options) ;
@@ -139,25 +157,10 @@ function wpgform_admin_init()
139
  */
140
  function wpgform_register_activation_hook()
141
  {
142
- $default_wpgform_options = array(
143
- 'sc_posts' => 1
144
- ,'sc_widgets' => 1
145
- ,'default_css' => 1
146
- ,'custom_css' => 0
147
- ,'custom_css_styles' => ''
148
- ,'donation_message' => 0
149
- ,'email_format' => WPGFORM_EMAIL_FORMAT_PLAIN
150
- ,'browser_check' => 0
151
- ) ;
152
-
153
- add_option('wpgform_options', $default_wpgform_options) ;
154
- //add_shortcode('wpgform', 'wpgform_shortcode') ;
155
  add_filter('widget_text', 'do_shortcode') ;
156
  }
157
 
158
- add_shortcode('gform', array('wpGForm', 'RenderGForm')) ;
159
-
160
-
161
  /**
162
  * wpGForm class definition
163
  *
@@ -170,6 +173,16 @@ add_shortcode('gform', array('wpGForm', 'RenderGForm')) ;
170
  */
171
  class wpGForm
172
  {
 
 
 
 
 
 
 
 
 
 
173
  /**
174
  * Constructor
175
  */
@@ -179,7 +192,9 @@ class wpGForm
179
  }
180
 
181
  /**
182
- * Function ConstructGForm grabs CSV data from a URL and returns an HTML table.
 
 
183
  *
184
  * @param $options array Values passed from the shortcode.
185
  * @return An HTML string if successful, false otherwise.
@@ -187,6 +202,15 @@ class wpGForm
187
  */
188
  function ConstructGForm($options)
189
  {
 
 
 
 
 
 
 
 
 
190
  // If no URL then return as nothing useful can be done.
191
  if (!$options['form'])
192
  {
@@ -287,64 +311,21 @@ class wpGForm
287
  if (!is_null($confirm))
288
  $confirm = str_replace(array('&','&','&'), '&', $confirm) ;
289
 
290
- // If we arrive here as a result of a POST then the Google Form was
291
- // submitted (either completely or partially) so we need to act on
292
- // the posted data appropriately. The user "submitting" the form
293
- // doesn't actually do anything - it just tells us that the form was
294
- // submitted and now the plugin needs to "really" submit it to Google,
295
- // get the response, and display it as part of the WordPress content.
296
-
297
- if (!empty($_POST))
298
- {
299
- $posted = true ;
300
- $action = $_POST['gform-action'] ;
301
- unset($_POST['gform-action']) ;
302
-
303
- $body = '' ;
304
-
305
- // The name of the form fields are munged, they need
306
- // to be restored before the parameters can be posted
307
 
308
- $patterns = array('/^entry_([0-9]+)_(single|group)_/', '/^entry_([0-9]+)_/') ;
309
- $replacements = array('entry.\1.\2.', 'entry.\1.') ;
310
-
311
- foreach ($_POST as $key => $value)
312
- {
313
- // Need to handle parameters passed as array values
314
- // separately because of how Python (used Google)
315
- // handles array arguments differently than PHP does.
316
-
317
- if (is_array($_POST[$key]))
318
- {
319
- $pa = &$_POST[$key] ;
320
- foreach ($pa as $pv)
321
- $body .= preg_replace($patterns, $replacements, $key) . '=' . rawurlencode($pv) . '&' ;
322
- }
323
- else
324
- {
325
- $body .= preg_replace($patterns, $replacements, $key) . '=' . rawurlencode($value) . '&' ;
326
- }
327
- }
328
- // Remove the action from the form and POST it
329
-
330
- //$form = str_replace($action, 'action="' . get_permalink(get_the_ID()) . '"', $form) ;
331
- $form = str_replace($action, 'action=""', $form) ;
332
-
333
- $response = wp_remote_post($action,
334
- array('sslverify' => false, 'body' => $body)) ;
335
- }
336
- else
337
  {
338
- $posted = false ;
339
- $response = wp_remote_get($form, array('sslverify' => false)) ;
340
  }
341
 
342
  // Retrieve the HTML from the URL
343
 
344
- if (is_wp_error($response))
345
  return '<div class="gform-google-error">Unable to retrieve Google Form. Please try reloading this page.</div>' ;
346
  else
347
- $html = $response['body'] ;
348
 
349
  // Need to filter the HTML retrieved from the form and strip off the stuff
350
  // we don't want. This gets rid of the HTML wrapper from the Google page.
@@ -376,6 +357,7 @@ class wpGForm
376
  ,'option' => array('value' => array(), 'selected' => array())
377
  ,'form' => array('id' => array(), 'class' => array(), 'action' => array(), 'method' => array(), 'target' => array(), 'onsubmit' => array())
378
  ,'script' => array('type' => array())
 
379
  ,'style' => array()
380
  ,'table' => array()
381
  ,'tbody' => array()
@@ -460,18 +442,26 @@ class wpGForm
460
  $action = $matches[0][$i] ;
461
  }
462
 
463
- $html = str_replace($action, 'action="' . get_permalink(get_the_ID()) . '"', $html) ;
464
- //$html = str_replace($action, 'action=""', $html) ;
465
- $action = preg_replace('/^action/i', 'value', $action) ;
 
466
 
467
  $html = preg_replace('/<\/form>/i',
468
- "<input type=\"hidden\" {$action} name=\"gform-action\"></form>", $html) ;
469
  }
470
  else
471
  {
472
  $action = null ;
473
  }
474
 
 
 
 
 
 
 
 
475
  // Output custom CSS?
476
 
477
  $wpgform_options = wpgform_get_plugin_options() ;
@@ -504,18 +494,49 @@ jQuery(document).ready(function($) {
504
  $("div.%sss-form-container :input").attr("disabled", true);
505
  ', $prefix) ;
506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
  // Before closing the <script> tag, is this the confirmation
508
  // AND do we have a custom confirmation page or alert message?
509
 
510
- if ($posted && is_null($action) && !is_null($alert))
511
  $js .= PHP_EOL . 'alert("' . $alert . '") ;' ;
512
 
513
  // Load the confirmation URL via AJAX?
514
- if ($posted && is_null($action) && !is_null($confirm) && $style === WPGFORM_CONFIRM_AJAX)
515
  $js .= PHP_EOL . '$("body").load("' . $confirm . '") ;' ;
516
 
517
  // Load the confirmation URL via Redirect?
518
- if ($posted && is_null($action) && !is_null($confirm) && $style === WPGFORM_CONFIRM_REDIRECT)
519
  //printf('<h2>%s::%s</h2>', basename(__FILE__), __LINE__) ;
520
  $js .= PHP_EOL . 'window.location.replace("' . $confirm . '") ;' ;
521
 
@@ -525,11 +546,10 @@ jQuery(document).ready(function($) {
525
  ' ;
526
 
527
  // Tidy up Javascript to ensure it isn't affected by 'the_content' filters
528
- //$js = preg_replace('/[\r\n]+/', '', $js) . PHP_EOL ;
529
- $js = preg_replace($patterns, $replacements, $js) . PHP_EOL ;
530
 
531
  // Send email?
532
- if ($posted && is_null($action) && $email)
533
  {
534
  wpGForm::SendConfirmationEmail($wpgform_options['email_format'], $sendto) ;
535
  }
@@ -543,11 +563,11 @@ jQuery(document).ready(function($) {
543
 
544
  // Let's check the browser version just in case ...
545
 
546
- $response = wp_check_browser_version();
547
 
548
- if ($response && $response['upgrade'])
549
  {
550
- if ($response['insecure'])
551
  $css .= '<div class="gform-browser-warning"><h4>' .
552
  __('Warning: You are using an insecure browser!') . '</h4></div>' ;
553
  else
@@ -556,7 +576,112 @@ jQuery(document).ready(function($) {
556
  }
557
  }
558
 
559
- return $js . $css . $html ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  }
561
 
562
  /**
@@ -618,6 +743,8 @@ jQuery(document).ready(function($) {
618
  */
619
  function SendConfirmationEmail($mode = WPGFORM_EMAIL_FORMAT_HTML, $sendto = false)
620
  {
 
 
621
  if ($sendto === false || $sendto === null) $sendto = get_bloginfo('admin_email') ;
622
 
623
  if ($mode == WPGFORM_EMAIL_FORMAT_HTML)
@@ -634,7 +761,11 @@ jQuery(document).ready(function($) {
634
  get_bloginfo('name'), $sendto) . PHP_EOL ;
635
 
636
  $headers .= sprintf("Cc: %s", $sendto) . PHP_EOL ;
637
- $headers .= sprintf("Bcc: %s", get_bloginfo('admin_email')) . PHP_EOL ;
 
 
 
 
638
  $headers .= sprintf("Reply-To: %s", $sendto) . PHP_EOL ;
639
  $headers .= sprintf("X-Mailer: PHP/%s", phpversion()) ;
640
 
@@ -681,9 +812,11 @@ jQuery(document).ready(function($) {
681
  date('Y-m-d'), date('H:i'), get_option('blogname')) ;
682
  }
683
 
684
- $to = sprintf('%s wpGForm Contact <%s>, %s Admin<%s>',
685
- get_option('blogname'), $sendto,
686
- get_option('blogname'), get_option('admin_email')) ;
 
 
687
 
688
  $subject = sprintf('Form Submission from %s', get_option('blogname')) ;
689
 
@@ -705,6 +838,15 @@ function wpgform_head()
705
 
706
  $wpgform_options = wpgform_get_plugin_options() ;
707
 
 
 
 
 
 
 
 
 
 
708
  // Load default gForm CSS?
709
  if ($wpgform_options['default_css'] == 1)
710
  {
24
  define('WPGFORM_CONFIRM_LIGHTBOX', 'lightbox') ;
25
  define('WPGFORM_CONFIRM_REDIRECT', 'redirect') ;
26
 
27
+ // Need the plugin options to initialize debug
28
+ $wpgform_options = wpgform_get_plugin_options() ;
29
+
30
+ // Enable debug content?
31
+ define('WPGFORM_DEBUG', $wpgform_options['enable_debug'] == 1) ;
32
+
33
+ if (WPGFORM_DEBUG)
34
+ {
35
+ error_reporting(E_ALL) ;
36
+ require_once('wpgform-debug.php') ;
37
+ add_action('send_headers', 'wpgform_send_headers') ;
38
+ }
39
+
40
  /**
41
  * wpgform_init()
42
  *
49
  $wpgform_options = wpgform_get_plugin_options() ;
50
 
51
  if ($wpgform_options['sc_posts'] == 1)
52
+ add_shortcode('gform', array('wpGForm', 'RenderGForm')) ;
53
 
54
  if ($wpgform_options['sc_widgets'] == 1)
55
  add_filter('widget_text', 'do_shortcode') ;
56
 
 
57
  add_filter('the_content', 'wpautop');
58
+ add_action('template_redirect', 'wpgform_head') ;
59
  }
60
 
61
+ add_action('init', array('wpGForm', 'ProcessGForm')) ;
62
+
63
  /**
64
  * Returns the default options for wpGForm.
65
  *
76
  ,'donation_message' => 0
77
  ,'email_format' => WPGFORM_EMAIL_FORMAT_PLAIN
78
  ,'browser_check' => 0
79
+ ,'enable_debug' => 0
80
+ ,'serialize_post_vars' => 0
81
+ ,'bcc_blog_admin' => 1
82
  ) ;
83
 
84
  return apply_filters('wpgform_default_plugin_options', $default_plugin_options) ;
157
  */
158
  function wpgform_register_activation_hook()
159
  {
160
+ add_option('wpgform_options', wpgform_get_default_plugin_options()) ;
 
 
 
 
 
 
 
 
 
 
 
 
161
  add_filter('widget_text', 'do_shortcode') ;
162
  }
163
 
 
 
 
164
  /**
165
  * wpGForm class definition
166
  *
173
  */
174
  class wpGForm
175
  {
176
+ /**
177
+ * Property to hold Google Form Response
178
+ */
179
+ static $response ;
180
+
181
+ /**
182
+ * Property to hold Google Form Post Status
183
+ */
184
+ static $posted = false ;
185
+
186
  /**
187
  * Constructor
188
  */
192
  }
193
 
194
  /**
195
+ * Function ConstructGForm loads HTML from a Google Form URL,
196
+ * processes it, and inserts it into a WordPress filter to output
197
+ * as part of a post, page, or widget.
198
  *
199
  * @param $options array Values passed from the shortcode.
200
  * @return An HTML string if successful, false otherwise.
202
  */
203
  function ConstructGForm($options)
204
  {
205
+ if (WPGFORM_DEBUG) wpgform_whereami(__FILE__, __LINE__, 'ConstructGForm') ;
206
+ if (WPGFORM_DEBUG) wpgform_preprint_r($_POST) ;
207
+
208
+ // Some servers running ModSecurity issue 403 errors because something
209
+ // in the form's POST parameters has triggered a positive match on a rule.
210
+
211
+ if (!empty($_SERVER) && array_key_exists('REDIRECT_STATUS', $_SERVER) && ($_SERVER['REDIRECT_STATUS'] == '403'))
212
+ return '<div class="gform-google-error">Unable to process Google Form. Server is responding with <span class="gform-google-error">403 Permission Denied</span> error.</div>' ;
213
+
214
  // If no URL then return as nothing useful can be done.
215
  if (!$options['form'])
216
  {
311
  if (!is_null($confirm))
312
  $confirm = str_replace(array('&#038;','&#38;','&amp;'), '&', $confirm) ;
313
 
314
+ // The initial rendering of the form content is done using this
315
+ // "remote get", all subsequent renderings will be the result of
316
+ // "post processing".
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
+ if (!self::$posted)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  {
320
+ self::$response = wp_remote_get($form, array('sslverify' => false)) ;
 
321
  }
322
 
323
  // Retrieve the HTML from the URL
324
 
325
+ if (is_wp_error(self::$response))
326
  return '<div class="gform-google-error">Unable to retrieve Google Form. Please try reloading this page.</div>' ;
327
  else
328
+ $html = self::$response['body'] ;
329
 
330
  // Need to filter the HTML retrieved from the form and strip off the stuff
331
  // we don't want. This gets rid of the HTML wrapper from the Google page.
357
  ,'option' => array('value' => array(), 'selected' => array())
358
  ,'form' => array('id' => array(), 'class' => array(), 'action' => array(), 'method' => array(), 'target' => array(), 'onsubmit' => array())
359
  ,'script' => array('type' => array())
360
+ ,'span' => array('class' => array(), 'style' => array())
361
  ,'style' => array()
362
  ,'table' => array()
363
  ,'tbody' => array()
442
  $action = $matches[0][$i] ;
443
  }
444
 
445
+ //$html = str_replace($action, 'action="' . get_permalink(get_the_ID()) . '"', $html) ;
446
+ $html = str_replace($action, 'action=""', $html) ;
447
+ $action = preg_replace(array('/^action=/i', '/"/'), array('', ''), $action) ;
448
+ $action = base64_encode(serialize($action)) ;
449
 
450
  $html = preg_replace('/<\/form>/i',
451
+ "<input type=\"hidden\" value=\"{$action}\" name=\"gform-action\"></form>", $html) ;
452
  }
453
  else
454
  {
455
  $action = null ;
456
  }
457
 
458
+ // Encode all of the short code options so they can
459
+ // be referenced if/when needed during form processing.
460
+
461
+ $html = preg_replace('/<\/form>/i', "<input type=\"hidden\" value=\"" .
462
+ base64_encode(serialize($options)) . "\" name=\"gform-options\"></form>", $html) ;
463
+ //base64_encode($options) . "\" name=\"gform-options\"></form>", $html) ;
464
+
465
  // Output custom CSS?
466
 
467
  $wpgform_options = wpgform_get_plugin_options() ;
494
  $("div.%sss-form-container :input").attr("disabled", true);
495
  ', $prefix) ;
496
 
497
+ /*
498
+ // Serialize the POST variables?
499
+ if ($wpgform_options['serialize_post_vars'] == 1)
500
+ {
501
+ $js .= sprintf('
502
+ $("#%sss-form").submit(function(event) {
503
+ //$("#%sss-form").children().each(function(){
504
+ $.each($("#%sss-form input, #%sss-form textarea"), function() {
505
+ //access to form element via $(this)
506
+ $(this).val($.base64Encode($(this).val()));
507
+ alert($(this).val());
508
+ });
509
+ });
510
+ //var i = 0;
511
+ //$.each($("#%sss-form input:text, #%sss-form input:hidden #%sss-form textarea"), function(i,v) {
512
+ //$.each($("#%sss-form input, #%sss-form textarea"), function(i,v) {
513
+ //var theTag = v.tagName;
514
+ //var theElement = $(v);
515
+ //var theValue = theElement.val();
516
+ //alert(i + ": " + theValue) ;
517
+ //$(v).val($.base64Encode($(v).val()));
518
+ //alert($.base64Encode(theValue)) ;
519
+ //i++;
520
+ //});
521
+
522
+
523
+ //alert("waiting ...");
524
+ //});', $prefix, $prefix, $prefix, $prefix, $prefix, $prefix, $prefix, $prefix, $prefix) ;
525
+ }
526
+ */
527
+
528
  // Before closing the <script> tag, is this the confirmation
529
  // AND do we have a custom confirmation page or alert message?
530
 
531
+ if (self::$posted && is_null($action) && !is_null($alert))
532
  $js .= PHP_EOL . 'alert("' . $alert . '") ;' ;
533
 
534
  // Load the confirmation URL via AJAX?
535
+ if (self::$posted && is_null($action) && !is_null($confirm) && $style === WPGFORM_CONFIRM_AJAX)
536
  $js .= PHP_EOL . '$("body").load("' . $confirm . '") ;' ;
537
 
538
  // Load the confirmation URL via Redirect?
539
+ if (self::$posted && is_null($action) && !is_null($confirm) && $style === WPGFORM_CONFIRM_REDIRECT)
540
  //printf('<h2>%s::%s</h2>', basename(__FILE__), __LINE__) ;
541
  $js .= PHP_EOL . 'window.location.replace("' . $confirm . '") ;' ;
542
 
546
  ' ;
547
 
548
  // Tidy up Javascript to ensure it isn't affected by 'the_content' filters
549
+ //$js = preg_replace($patterns, $replacements, $js) . PHP_EOL ;
 
550
 
551
  // Send email?
552
+ if (self::$posted && is_null($action) && $email)
553
  {
554
  wpGForm::SendConfirmationEmail($wpgform_options['email_format'], $sendto) ;
555
  }
563
 
564
  // Let's check the browser version just in case ...
565
 
566
+ self::$response = wp_check_browser_version();
567
 
568
+ if (self::$response && self::$response['upgrade'])
569
  {
570
+ if (self::$response['insecure'])
571
  $css .= '<div class="gform-browser-warning"><h4>' .
572
  __('Warning: You are using an insecure browser!') . '</h4></div>' ;
573
  else
576
  }
577
  }
578
 
579
+ if (WPGFORM_DEBUG)
580
+ $debug = '<h2 class="gform-debug"><a href="#" class="gform-debug-wrapper">Show wpGForm Debug Content</a></h2>' ;
581
+ else
582
+ $debug = '' ;
583
+
584
+ return $debug . $js . $css . $html ;
585
+ }
586
+
587
+ /**
588
+ * Function ConstructGForm loads HTML from a Google Form URL,
589
+ * processes it, and inserts it into a WordPress filter to output
590
+ * as part of a post, page, or widget.
591
+ *
592
+ * @param $options array Values passed from the shortcode.
593
+ * @return An HTML string if successful, false otherwise.
594
+ * @see RenderGForm
595
+ */
596
+ function ProcessGForm()
597
+ {
598
+ if (WPGFORM_DEBUG) wpgform_whereami(__FILE__, __LINE__, 'ProcessGForm') ;
599
+ if (WPGFORM_DEBUG) wpgform_preprint_r($_POST) ;
600
+ if (!empty($_POST) && array_key_exists('gform-action', $_POST))
601
+ {
602
+ self::$posted = true ;
603
+
604
+ $wpgform_options = wpgform_get_plugin_options() ;
605
+
606
+ //print_r($_POST) ;
607
+ // Are POST variables base64 encoded?
608
+ /*
609
+ if ($wpgform_options['serialize_post_vars'] == 1)
610
+ {
611
+ foreach ($_POST as $key => $value)
612
+ {
613
+ // Need to handle parameters passed as array values
614
+ // separately because of how Python (used Google)
615
+ // handles array arguments differently than PHP does.
616
+
617
+ //if (is_array($_POST[$key]))
618
+ //{
619
+ //$pa = &$_POST[$key] ;
620
+ //foreach ($pa as $pv)
621
+ //$body .= preg_replace($patterns, $replacements, $key) . '=' . rawurlencode($pv) . '&' ;
622
+ //}
623
+ //else
624
+ //{
625
+ $_POST[$key] = base64_decode($value) ;
626
+ //}
627
+ }
628
+ }
629
+ //print_r($_POST) ;
630
+ */
631
+ if (WPGFORM_DEBUG) wpgform_whereami(__FILE__, __LINE__) ;
632
+ if (WPGFORM_DEBUG) wpgform_preprint_r($_POST) ;
633
+
634
+ $action = unserialize(base64_decode($_POST['gform-action'])) ;
635
+ unset($_POST['gform-action']) ;
636
+ $options = $_POST['gform-options'] ;
637
+ unset($_POST['gform-options']) ;
638
+ $options = unserialize(base64_decode($options)) ;
639
+
640
+ if (WPGFORM_DEBUG) wpgform_preprint_r($options) ;
641
+ $form = $options['form'] ;
642
+
643
+ $body = '' ;
644
+
645
+ // The name of the form fields are munged, they need
646
+ // to be restored before the parameters can be posted
647
+
648
+ $patterns = array('/^entry_([0-9]+)_(single|group)_/', '/^entry_([0-9]+)_/') ;
649
+ $replacements = array('entry.\1.\2.', 'entry.\1.') ;
650
+
651
+ foreach ($_POST as $key => $value)
652
+ {
653
+ // Need to handle parameters passed as array values
654
+ // separately because of how Python (used Google)
655
+ // handles array arguments differently than PHP does.
656
+
657
+ if (is_array($_POST[$key]))
658
+ {
659
+ $pa = &$_POST[$key] ;
660
+ foreach ($pa as $pv)
661
+ $body .= preg_replace($patterns, $replacements, $key) . '=' . rawurlencode($pv) . '&' ;
662
+ }
663
+ else
664
+ {
665
+ $body .= preg_replace($patterns, $replacements, $key) . '=' . rawurlencode($value) . '&' ;
666
+ }
667
+ }
668
+
669
+ //$form = str_replace($action, 'action="' . get_permalink(get_the_ID()) . '"', $form) ;
670
+ $form = str_replace($action, 'action=""', $form) ;
671
+
672
+ // WordPress converts all of the ampersand characters to their
673
+ // appropriate HTML entity or some variety of it. Need to undo
674
+ // that so the URL can be actually be used.
675
+
676
+ $action = str_replace(array('&#038;','&#38;','&amp;'), '&', $action) ;
677
+
678
+ self::$response = wp_remote_post($action,
679
+ array('sslverify' => false, 'body' => $body)) ;
680
+ }
681
+ else
682
+ {
683
+ sprintf('%s::%s', basename(__FILE__), __LINE__) ;
684
+ }
685
  }
686
 
687
  /**
743
  */
744
  function SendConfirmationEmail($mode = WPGFORM_EMAIL_FORMAT_HTML, $sendto = false)
745
  {
746
+ $wpgform_options = wpgform_get_plugin_options() ;
747
+
748
  if ($sendto === false || $sendto === null) $sendto = get_bloginfo('admin_email') ;
749
 
750
  if ($mode == WPGFORM_EMAIL_FORMAT_HTML)
761
  get_bloginfo('name'), $sendto) . PHP_EOL ;
762
 
763
  $headers .= sprintf("Cc: %s", $sendto) . PHP_EOL ;
764
+
765
+ // Bcc Blog Admin?
766
+ if ($wpgform_options['bcc_blog_admin'])
767
+ $headers .= sprintf("Bcc: %s", get_bloginfo('admin_email')) . PHP_EOL ;
768
+
769
  $headers .= sprintf("Reply-To: %s", $sendto) . PHP_EOL ;
770
  $headers .= sprintf("X-Mailer: PHP/%s", phpversion()) ;
771
 
812
  date('Y-m-d'), date('H:i'), get_option('blogname')) ;
813
  }
814
 
815
+ $to = sprintf('%s wpGForm Contact <%s>', get_option('blogname'), $sendto) ;
816
+
817
+ //$to = sprintf('%s wpGForm Contact <%s>, %s Admin<%s>',
818
+ // get_option('blogname'), $sendto,
819
+ // get_option('blogname'), get_option('admin_email')) ;
820
 
821
  $subject = sprintf('Form Submission from %s', get_option('blogname')) ;
822
 
838
 
839
  $wpgform_options = wpgform_get_plugin_options() ;
840
 
841
+ /*
842
+ // Load Base64 Encode/Decode jQuery plugin?
843
+ if ($wpgform_options['serialize_post_vars'] == 1)
844
+ {
845
+ wp_enqueue_script('gform-jquery-base64',
846
+ plugins_url(plugin_basename(dirname(__FILE__) . '/js/jquery.base64.js')), array('jquery'));
847
+ }
848
+ */
849
+
850
  // Load default gForm CSS?
851
  if ($wpgform_options['default_css'] == 1)
852
  {
wpgform-debug.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* vim: set expandtab tabstop=4 shiftwidth=4: */
3
+ /**
4
+ * GForm functions.
5
+ *
6
+ * $Id$
7
+ *
8
+ * (c) 2011 by Mike Walsh
9
+ *
10
+ * @author Mike Walsh <mike@walshcrew.com>
11
+ * @package wpGForm
12
+ * @subpackage functions
13
+ * @version $Revision$
14
+ * @lastmodified $Date$
15
+ * @lastmodifiedby $Author$
16
+ *
17
+ */
18
+
19
+ global $wpgform_debug_content ;
20
+
21
+ $wpgform_debug_content = '' ;
22
+ add_action('init', 'wpgform_debug', 0) ;
23
+ add_action('wp_footer', 'wpgform_show_debug_content') ;
24
+
25
+ /**
26
+ * Debug action to examine server variables
27
+ *
28
+ */
29
+ function wpgform_debug()
30
+ {
31
+ global $wp_filter ;
32
+
33
+ wpgform_error_log($_POST) ;
34
+
35
+ if (!is_admin())
36
+ {
37
+ wpgform_whereami(__FILE__, __LINE__, '$_SERVER') ;
38
+ wpgform_preprint_r($_SERVER) ;
39
+ wpgform_whereami(__FILE__, __LINE__, '$_ENV') ;
40
+ wpgform_preprint_r($_ENV) ;
41
+ wpgform_whereami(__FILE__, __LINE__, '$_POST') ;
42
+ wpgform_preprint_r($_POST) ;
43
+ wpgform_whereami(__FILE__, __LINE__, '$_GET') ;
44
+ wpgform_preprint_r($_GET) ;
45
+
46
+ if (array_key_exists('init', $wp_filter))
47
+ {
48
+ wpgform_whereami(__FILE__, __LINE__, '$wp_filter[\'init\']') ;
49
+ wpgform_preprint_r($wp_filter['init']) ;
50
+ }
51
+ if (array_key_exists('template_redirect', $wp_filter))
52
+ {
53
+ wpgform_whereami(__FILE__, __LINE__, '$wp_filter[\'template_redirect\']') ;
54
+ wpgform_preprint_r($wp_filter['template_redirect']) ;
55
+ }
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Debug action to display debug content in a DIV which can be toggled open and closed.
61
+ *
62
+ */
63
+ function wpgform_show_debug_content()
64
+ {
65
+ global $wpgform_debug_content ;
66
+ ?>
67
+ <style>
68
+ h2.gform-debug {
69
+ text-align: center;
70
+ background-color: #ffebe8;
71
+ border: 2px solid #ff0000;
72
+ }
73
+
74
+ div.gform-debug {
75
+ padding: 10px;
76
+ }
77
+
78
+ div.gform-debug h2 {
79
+ background-color: #f00;
80
+ }
81
+
82
+ div.gform-debug h3 {
83
+ padding: 10px;
84
+ color: #fff;
85
+ font-weight: bold;
86
+ border: 1px solid #000000;
87
+ background-color: #024593;
88
+ }
89
+
90
+ div.gform-debug pre {
91
+ color: #000;
92
+ text-align: left;
93
+ border: 1px solid #000000;
94
+ background-color: #c6dffd;
95
+ }
96
+ </style>
97
+ <script type="text/javascript">
98
+ jQuery(document).ready(function($) {
99
+ $("div.gform-debug").hide();
100
+ $("a.gform-debug-wrapper").show();
101
+ $("a.gform-debug-wrapper").text("Show wpGForm Debug Content");
102
+
103
+ $("a.gform-debug-wrapper").click(function(){
104
+ $("div.gform-debug").slideToggle();
105
+
106
+ if ($("a.gform-debug-wrapper").text() == "Show wpGForm Debug Content")
107
+ $("a.gform-debug-wrapper").text("Hide wpGForm Debug Content");
108
+ else
109
+ $("a.gform-debug-wrapper").text("Show wpGForm Debug Content");
110
+ });
111
+ });
112
+ </script>
113
+ <div class="gform-debug">
114
+ <?php echo $wpgform_debug_content ; ?>
115
+ </div>
116
+ <?php
117
+ }
118
+
119
+ /**
120
+ * wpgform_send_headers()
121
+ *
122
+ * @return null
123
+ */
124
+ function wpgform_send_headers()
125
+ {
126
+ header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1
127
+ header('Expires: ' . date(DATE_RFC822, strtotime('yesterday'))); // Date in the past
128
+ header('X-Frame-Options: SAMEORIGIN');
129
+ }
130
+
131
+ /**
132
+ * Debug "where am i" function
133
+ */
134
+ function wpgform_whereami($f, $l, $s = null)
135
+ {
136
+ global $wpgform_debug_content ;
137
+
138
+ if (is_null($s))
139
+ {
140
+ $wpgform_debug_content .= sprintf('<h3>%s::%s</h3>', basename($f), $l) ;
141
+ //error_log(sprintf('%s::%s', basename($f), $l)) ;
142
+ }
143
+ else
144
+ {
145
+ $wpgform_debug_content .= sprintf('<h3>%s::%s::%s</h3>', basename($f), $l, $s) ;
146
+ //error_log(sprintf('%s::%s::%s', basename($f), $l, $s)) ;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Debug functions
152
+ */
153
+ function wpgform_preprint_r()
154
+ {
155
+ global $wpgform_debug_content ;
156
+
157
+ $numargs = func_num_args() ;
158
+ $arg_list = func_get_args() ;
159
+ for ($i = 0; $i < $numargs; $i++) {
160
+ $wpgform_debug_content .= sprintf('<pre style="text-align:left;">%s</pre>', print_r($arg_list[$i], true)) ;
161
+ }
162
+ wpgform_error_log(func_get_args()) ;
163
+ }
164
+ /**
165
+ * Debug functions
166
+ */
167
+ function wpgform_error_log()
168
+ {
169
+ $numargs = func_num_args() ;
170
+ $arg_list = func_get_args() ;
171
+ for ($i = 0; $i < $numargs; $i++) {
172
+ error_log(print_r($arg_list[$i], true)) ;
173
+ }
174
+ }
175
+ ?>
wpgform-options.php CHANGED
@@ -7,7 +7,7 @@
7
  *
8
  * (c) 2011 by Mike Walsh
9
  *
10
- * @author Mike Walsh <mike@walshcrew.com>
11
  * @package wpGForm
12
  * @subpackage options
13
  * @version $Revision$
@@ -258,7 +258,7 @@ function wpgform_options_page()
258
  */
259
  function wpgform_settings_input()
260
  {
261
- $wpgform_options = wpgform_get_plugin_options() ; ?>
262
  <table class="form-table">
263
  <tr valign="top">
264
  <th scope="row"><label><b><i>gform</i></b> Shortcode</label></th>
@@ -299,6 +299,10 @@ function wpgform_settings_input()
299
  <br/>
300
  <input name="wpgform_options[email_format]" type="radio" id="gform_email_format" value="<?php echo WPGFORM_EMAIL_FORMAT_PLAIN ;?>" <?php checked(WPGFORM_EMAIL_FORMAT_PLAIN, $wpgform_options['email_format']) ; ?> />
301
  Send confirmation email (when used) in Plain Text format.</label>
 
 
 
 
302
  </fieldset></td>
303
  </tr>
304
  <tr valign="top">
@@ -307,7 +311,7 @@ function wpgform_settings_input()
307
  <label for="gform_browser_check">
308
  <table style="padding: 0px;" border="0" cellpadding="0" cellspacing="0">
309
  <tr>
310
- <td style="padding: 0px;">
311
  <input name="wpgform_options[browser_check]" type="checkbox" id="gform_browser_check" value="1" <?php checked('1', $wpgform_options['browser_check']) ; ?> />
312
  </td>
313
  <td style="padding: 5px;">
@@ -324,7 +328,7 @@ function wpgform_settings_input()
324
  <label for="gform_donation_message">
325
  <table style="padding: 0px;" border="0" cellpadding="0" cellspacing="0">
326
  <tr>
327
- <td style="padding: 0px;">
328
  <input name="wpgform_options[donation_message]" type="checkbox" id="gform_donation_message" value="1" <?php checked('1', $wpgform_options['donation_message']) ; ?> />
329
  </td>
330
  <td style="padding: 5px;">
@@ -335,6 +339,42 @@ function wpgform_settings_input()
335
  </label>
336
  </fieldset></td>
337
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  </table>
339
  <br /><br />
340
  <?php
7
  *
8
  * (c) 2011 by Mike Walsh
9
  *
10
+ * @author Mike Walsh <mpwalsh8@gmail.com>
11
  * @package wpGForm
12
  * @subpackage options
13
  * @version $Revision$
258
  */
259
  function wpgform_settings_input()
260
  {
261
+ $wpgform_options = wpgform_get_plugin_options() ;
262
  <table class="form-table">
263
  <tr valign="top">
264
  <th scope="row"><label><b><i>gform</i></b> Shortcode</label></th>
299
  <br/>
300
  <input name="wpgform_options[email_format]" type="radio" id="gform_email_format" value="<?php echo WPGFORM_EMAIL_FORMAT_PLAIN ;?>" <?php checked(WPGFORM_EMAIL_FORMAT_PLAIN, $wpgform_options['email_format']) ; ?> />
301
  Send confirmation email (when used) in Plain Text format.</label>
302
+ <br />
303
+ <label for="bcc_blog_admin">
304
+ <input name="wpgform_options[bcc_blog_admin]" type="checkbox" id="gform_bcc_blog_admin" value="1" <?php checked('1', $wpgform_options['bcc_blog_admin']) ; ?> />
305
+ Bcc Blog Admin on Confirmation Email (when used)</label>
306
  </fieldset></td>
307
  </tr>
308
  <tr valign="top">
311
  <label for="gform_browser_check">
312
  <table style="padding: 0px;" border="0" cellpadding="0" cellspacing="0">
313
  <tr>
314
+ <td style="padding: 5px 0px; vertical-align: top;">
315
  <input name="wpgform_options[browser_check]" type="checkbox" id="gform_browser_check" value="1" <?php checked('1', $wpgform_options['browser_check']) ; ?> />
316
  </td>
317
  <td style="padding: 5px;">
328
  <label for="gform_donation_message">
329
  <table style="padding: 0px;" border="0" cellpadding="0" cellspacing="0">
330
  <tr>
331
+ <td style="padding: 5px 0px; vertical-align: top;">
332
  <input name="wpgform_options[donation_message]" type="checkbox" id="gform_donation_message" value="1" <?php checked('1', $wpgform_options['donation_message']) ; ?> />
333
  </td>
334
  <td style="padding: 5px;">
339
  </label>
340
  </fieldset></td>
341
  </tr>
342
+ <!--
343
+ <tr valign="top">
344
+ <th scope="row"><label>Serialize Post Variables</label></th>
345
+ <td><fieldset>
346
+ <label for="gform_serialize_post_vars">
347
+ <table style="padding: 0px;" border="0" cellpadding="0" cellspacing="0">
348
+ <tr>
349
+ <td style="padding: 5px 0px; vertical-align: top;">
350
+ <input name="wpgform_options[serialize_post_vars]" type="checkbox" id="gform_serialize_post_vars" value="1" <?php //checked('1', $wpgform_options['serialize_post_vars']) ; ?> />
351
+ </td>
352
+ <td style="padding: 5px;">
353
+ Serialize POST data prior to form submission? Enabling this <i><b>may</b></i> help with servers where <a href="http://www.modsecurity.org/">Apache's ModSecurity</a> module is installed. If you're experiencing 403 errors after submitting a form, this may alleviate the problem.
354
+ </td>
355
+ </tr>
356
+ </table>
357
+ </label>
358
+ </fieldset></td>
359
+ </tr>
360
+ -->
361
+ <tr valign="top">
362
+ <th scope="row"><label>Enable Debug</label></th>
363
+ <td><fieldset>
364
+ <label for="gform_enable_debug">
365
+ <table style="padding: 0px;" border="0" cellpadding="0" cellspacing="0">
366
+ <tr>
367
+ <td style="padding: 5px 0px; vertical-align: top;">
368
+ <input name="wpgform_options[enable_debug]" type="checkbox" id="gform_enable_debug" value="1" <?php checked('1', $wpgform_options['enable_debug']) ; ?> />
369
+ </td>
370
+ <td style="padding: 5px;">
371
+ Enabling debug will collect data during the form rendering and processing process. The data is added to the page footer but hidden with a link appearing above the form which can toggle the display of the debug data. This data is useful when trying to understand why the plugin isn't operating as expected.
372
+ </td>
373
+ </tr>
374
+ </table>
375
+ </label>
376
+ </fieldset></td>
377
+ </tr>
378
  </table>
379
  <br /><br />
380
  <?php