/**
  * Handles Registration Links.
  *
  * @package s2Member\Registrations
  * @since 3.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after redirection.
  */
 public static function register()
 {
     do_action("ws_plugin__s2member_before_register", get_defined_vars());
     /**/
     if (!empty($_GET["s2member_register"])) {
         eval('while (@ob_end_clean ());');
         /* First we end/clean any output buffers that may exist already. */
         /**/
         $msg_503 = _x('<strong>Your Link Expired:</strong><br />Please contact Support if you need assistance.', "s2member-front", "s2member");
         /**/
         if (is_array($register = preg_split("/\\:\\.\\:\\|\\:\\.\\:/", c_ws_plugin__s2member_utils_encryption::decrypt(trim(stripslashes((string) $_GET["s2member_register"])))))) {
             if (count($register) === 6 && $register[0] === "subscr_gateway_subscr_id_custom_item_number_time") {
                 if (is_numeric($register[5]) && $register[5] <= strtotime("now") && $register[5] >= strtotime("-" . apply_filters("ws_plugin__s2member_register_link_exp_time", "2 days", get_defined_vars()))) {
                     $_COOKIE["s2member_subscr_gateway"] = c_ws_plugin__s2member_utils_encryption::encrypt($register[1]);
                     $_COOKIE["s2member_subscr_id"] = c_ws_plugin__s2member_utils_encryption::encrypt($register[2]);
                     $_COOKIE["s2member_custom"] = c_ws_plugin__s2member_utils_encryption::encrypt($register[3]);
                     $_COOKIE["s2member_item_number"] = c_ws_plugin__s2member_utils_encryption::encrypt($register[4]);
                     /**/
                     if (($reg_cookies = c_ws_plugin__s2member_register_access::reg_cookies_ok()) && extract($reg_cookies)) {
                         status_header(200);
                         /* Send a 200 OK status header. */
                         header("Content-Type: text/html; charset=utf-8");
                         /* Content-Type with UTF-8. */
                         /**/
                         setcookie("s2member_subscr_gateway", $_COOKIE["s2member_subscr_gateway"], time() + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie("s2member_subscr_gateway", $_COOKIE["s2member_subscr_gateway"], time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN);
                         setcookie("s2member_subscr_id", $_COOKIE["s2member_subscr_id"], time() + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie("s2member_subscr_id", $_COOKIE["s2member_subscr_id"], time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN);
                         setcookie("s2member_custom", $_COOKIE["s2member_custom"], time() + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie("s2member_custom", $_COOKIE["s2member_custom"], time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN);
                         setcookie("s2member_item_number", $_COOKIE["s2member_item_number"], time() + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie("s2member_item_number", $_COOKIE["s2member_item_number"], time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN);
                         /**/
                         do_action("ws_plugin__s2member_during_register", get_defined_vars());
                         /**/
                         if (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site() && ($location = c_ws_plugin__s2member_utils_urls::wp_signup_url())) {
                             echo '<script type="text/javascript">' . "\n";
                             echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($location) . "';";
                             echo '</script>' . "\n";
                         } else {
                             if ($location = c_ws_plugin__s2member_utils_urls::wp_register_url()) {
                                 echo '<script type="text/javascript">' . "\n";
                                 echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($location) . "';";
                                 echo '</script>' . "\n";
                             }
                         }
                         exit;
                         /* Clean exit. The browser will now be redirected to ``$location``. */
                     } else {
                         status_header(503) . header("Content-Type: text/html; charset=utf-8") . exit($msg_503);
                     }
                 } else {
                     status_header(503) . header("Content-Type: text/html; charset=utf-8") . exit($msg_503);
                 }
             } else {
                 status_header(503) . header("Content-Type: text/html; charset=utf-8") . exit($msg_503);
             }
         } else {
             status_header(503) . header("Content-Type: text/html; charset=utf-8") . exit($msg_503);
         }
     }
     /**/
     do_action("ws_plugin__s2member_after_register", get_defined_vars());
 }
 /**
  * Builds a reCAPTCHA™ JavaScript `script` tag for display.
  *
  * @package s2Member\Utilities
  * @since 3.5
  *
  * @param string $theme Optional. The theme used in display. Defaults to `clean`.
  * @param string $tabindex Optional. Value of `tabindex=""` attribute. Defaults to `-1`.
  * @param string $error Optional. An error message to display.
  * @return string HTML markup for JavaScript tag.
  */
 public static function recaptcha_script_tag($theme = FALSE, $tabindex = FALSE, $error = FALSE)
 {
     $theme = $theme ? $theme : "clean";
     $tabindex = strlen($tabindex) ? (int) $tabindex : -1;
     $keys = c_ws_plugin__s2member_utils_captchas::recaptcha_keys();
     $options = '<script type="text/javascript">' . "if(typeof RecaptchaOptions !== 'object'){ var RecaptchaOptions = {theme: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($theme) . "', lang: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["recaptcha"]["lang"]) . "', tabindex: " . $tabindex . " }; }" . '</script>' . "\n";
     $no_tabindex_icons = '<script type="text/javascript">' . "if(typeof jQuery === 'function'){ jQuery('td a[id^=\"recaptcha\"]').removeAttr('tabindex'); }" . '</script>';
     $adjustments = !apply_filters("c_ws_plugin__s2member_utils_tabindex_recaptcha_icons", false, get_defined_vars()) ? $no_tabindex_icons : "";
     return $options . '<script type="text/javascript" src="' . esc_attr('https://www.google.com/recaptcha/api/challenge?k=' . urlencode($keys["public"])) . '' . ($error ? '&amp;error=' . urlencode($error) : '') . '"></script>' . $adjustments;
 }
Пример #3
0
 /**
  * Adds Pro Add-on JavaScript.
  *
  * @package s2Member\CSS_JS
  * @since 1.5
  *
  * @attaches-to ``add_action("ws_plugin__s2member_during_js_w_globals");``
  *
  * @param array $vars Expects array of defined variables, passed in by the Action Hook.
  * @return null
  */
 public static function js_w_globals($vars = FALSE)
 {
     $g = "var S2MEMBER_PRO_VERSION = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PRO_VERSION) . "',";
     $g = trim($g, " ,") . ";";
     // Trim & add semicolon.
     $u = $GLOBALS["WS_PLUGIN__"]["s2member_pro"]["c"]["dir_url"];
     $i = $GLOBALS["WS_PLUGIN__"]["s2member_pro"]["c"]["dir_url"] . "/images";
     echo "\n" . $g . "\n";
     // Add a line break before inclusion.
     include_once dirname(dirname(__FILE__)) . "/s2member-pro-min.js";
     return;
     // Return unformity.
 }
 /**
  * Returns a DOCTYPE tag along with the HEAD section and title tag.
  *
  * This method should NOT be called upon until
  * {@link s2Member\API_Constants\c_ws_plugin__s2member_constants::constants()}
  * has been processed. We need access to: ``WS_PLUGIN__S2MEMBER_API_CONSTANTS_MD5``.
  *
  * @package s2Member\Utilities
  * @since 110720
  *
  * @param str $doctype_html_head_title Optional. The title of the HTML document being generated.
  * @param str $doctype_html_head_action Optional. An action Hook to process during HEAD generation.
  * @return str A DOCTYPE tag along with the HEAD section and title tag, configured by parameters.
  */
 public static function doctype_html_head($doctype_html_head_title = FALSE, $doctype_html_head_action = FALSE)
 {
     $s2o = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["s2o_url"];
     /* Loads s2Member only. */
     /**/
     ob_start();
     /* Start output buffering here so we can "return" the output from this utility. */
     /**/
     echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
     /**/
     echo '<html xmlns="http://www.w3.org/1999/xhtml">' . "\n";
     echo '<head>' . "\n";
     /**/
     echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . "\n";
     /**/
     echo '<script type="text/javascript" src="' . esc_attr(site_url("/wp-includes/js/jquery/jquery.js?ver=" . urlencode(c_ws_plugin__s2member_utilities::ver_checksum()))) . '"></script>' . "\n";
     echo '<script type="text/javascript" src="' . esc_attr(site_url("/wp-includes/js/l10n.js?ver=" . urlencode(c_ws_plugin__s2member_utilities::ver_checksum()))) . '"></script>' . "\n";
     /**/
     echo '<script type="text/javascript">' . "var pwsL10n = {empty: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Strength indicator", "s2member-front", "s2member")) . "', short: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Very weak", "s2member-front", "s2member")) . "', bad: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Weak", "s2member-front", "s2member")) . "', good: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Medium", "s2member-front", "s2member")) . "', strong: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Strong", "s2member-front", "s2member")) . "', mismatch: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Mismatch", "s2member-front", "s2member")) . "'}; try{convertEntities(pwsL10n);}catch(e){};</script>" . "\n";
     echo '<script type="text/javascript" src="' . esc_attr(site_url("/wp-admin/js/password-strength-meter.js?ver=" . urlencode(c_ws_plugin__s2member_utilities::ver_checksum()))) . '"></script>' . "\n";
     /**/
     echo '<script type="text/javascript" src="' . esc_attr($s2o . "?ws_plugin__s2member_js_w_globals=" . urlencode(WS_PLUGIN__S2MEMBER_API_CONSTANTS_MD5) . "&amp;qcABC=1&amp;ver=" . urlencode(c_ws_plugin__s2member_utilities::ver_checksum())) . '"></script>' . "\n";
     /**/
     echo '<link href="' . esc_attr($s2o . "?ws_plugin__s2member_css=1&amp;qcABC=1&amp;ver=" . urlencode(c_ws_plugin__s2member_utilities::ver_checksum())) . '" type="text/css" rel="stylesheet" media="all" />' . "\n";
     /**/
     if ($doctype_html_head_title) {
         /* Add <title></title> tag? */
         echo '<title>' . $doctype_html_head_title . '</title>' . "\n";
     }
     /**/
     if ($doctype_html_head_action) {
         /* Add content from Hook? */
         do_action($doctype_html_head_action, get_defined_vars());
     }
     /**/
     echo '</head>' . "\n";
     /**/
     return ob_get_clean();
 }
 /**
  * Handles Profile modifications.
  *
  * @package s2Member\Profiles
  * @since 3.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null After re-configuring the ``$current_user`` object.
  * 	May also exit script execution when handling the Stand-Alone Profile Modification Form.
  */
 public static function handle_profile_modifications()
 {
     global $current_user;
     /* We'll need to update this global object. */
     /**/
     $user =& $current_user;
     /* Shorter reference to the $current_user object. */
     /**/
     do_action("ws_plugin__s2member_before_handle_profile_modifications", get_defined_vars());
     /**/
     if (!empty($_POST["ws_plugin__s2member_profile_save"]) && is_user_logged_in() && is_object($user) && !empty($user->ID) && ($user_id = $user->ID)) {
         if (($nonce = $_POST["ws_plugin__s2member_profile_save"]) && wp_verify_nonce($nonce, "ws-plugin--s2member-profile-save")) {
             $GLOBALS["ws_plugin__s2member_profile_saved"] = true;
             /* Global flag as having been saved/updated successfully. */
             /**/
             $_p = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST));
             /* Clean ``$_POST`` vars. */
             /**/
             $userdata["ID"] = $user_id;
             /* Needed for database update. */
             /**/
             if (!empty($_p["ws_plugin__s2member_profile_email"])) {
                 if (is_email($_p["ws_plugin__s2member_profile_email"])) {
                     if (!email_exists($_p["ws_plugin__s2member_profile_email"])) {
                         $userdata["user_email"] = $_p["ws_plugin__s2member_profile_email"];
                     }
                 }
             }
             /**/
             if (!empty($_p["ws_plugin__s2member_profile_password1"])) {
                 if ($user->user_login !== "demo") {
                     /* No pass change on demo! */
                     $userdata["user_pass"] = $_p["ws_plugin__s2member_profile_password1"];
                 }
             }
             /**/
             if (!empty($_p["ws_plugin__s2member_profile_first_name"])) {
                 $userdata["first_name"] = $_p["ws_plugin__s2member_profile_first_name"];
             }
             /**/
             if (!empty($_p["ws_plugin__s2member_profile_display_name"])) {
                 $userdata["display_name"] = $_p["ws_plugin__s2member_profile_display_name"];
             }
             /**/
             if (!empty($_p["ws_plugin__s2member_profile_last_name"])) {
                 $userdata["last_name"] = $_p["ws_plugin__s2member_profile_last_name"];
             }
             /**/
             wp_update_user($userdata);
             /* OK. Now send this array for an update. */
             /**/
             if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) {
                 if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level("auto-detection", "profile")) {
                     $_existing_fields = get_user_option("s2member_custom_fields", $user_id);
                     /**/
                     foreach (json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field) {
                         $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
                         $field_id_class = preg_replace("/_/", "-", $field_var);
                         /**/
                         if (!in_array($field["id"], $fields_applicable) || strpos($field["editable"], "no") === 0) {
                             if (isset($_existing_fields[$field_var]) && (is_array($_existing_fields[$field_var]) && !empty($_existing_fields[$field_var]) || is_string($_existing_fields[$field_var]) && strlen($_existing_fields[$field_var]))) {
                                 $fields[$field_var] = $_existing_fields[$field_var];
                             } else {
                                 /* Else ``unset()``. */
                                 unset($fields[$field_var]);
                             }
                         } else {
                             if ($field["required"] === "yes" && (!isset($_p["ws_plugin__s2member_profile_" . $field_var]) || !is_array($_p["ws_plugin__s2member_profile_" . $field_var]) && !is_string($_p["ws_plugin__s2member_profile_" . $field_var]) || is_array($_p["ws_plugin__s2member_profile_" . $field_var]) && empty($_p["ws_plugin__s2member_profile_" . $field_var]) || is_string($_p["ws_plugin__s2member_profile_" . $field_var]) && !strlen($_p["ws_plugin__s2member_profile_" . $field_var]))) {
                                 if (isset($_existing_fields[$field_var]) && (is_array($_existing_fields[$field_var]) && !empty($_existing_fields[$field_var]) || is_string($_existing_fields[$field_var]) && strlen($_existing_fields[$field_var]))) {
                                     $fields[$field_var] = $_existing_fields[$field_var];
                                 } else {
                                     /* Else ``unset()``. */
                                     unset($fields[$field_var]);
                                 }
                             } else {
                                 if (isset($_p["ws_plugin__s2member_profile_" . $field_var])) {
                                     if (is_array($_p["ws_plugin__s2member_profile_" . $field_var]) && !empty($_p["ws_plugin__s2member_profile_" . $field_var]) || is_string($_p["ws_plugin__s2member_profile_" . $field_var]) && strlen($_p["ws_plugin__s2member_profile_" . $field_var])) {
                                         $fields[$field_var] = $_p["ws_plugin__s2member_profile_" . $field_var];
                                     } else {
                                         /* Else ``unset()``. */
                                         unset($fields[$field_var]);
                                     }
                                 } else {
                                     /* Else ``unset()``. */
                                     unset($fields[$field_var]);
                                 }
                             }
                         }
                     }
                     /**/
                     if (!empty($fields)) {
                         update_user_option($user_id, "s2member_custom_fields", $fields);
                     } else {
                         /* Else delete their Custom Fields? */
                         delete_user_option($user_id, "s2member_custom_fields");
                     }
                 }
             }
             /**/
             eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
             do_action("ws_plugin__s2member_during_handle_profile_modifications", get_defined_vars());
             unset($__refs, $__v);
             /* Unset defined __refs, __v. */
             /**/
             $user = new WP_User($user_id);
             /* Update the ``WP_User`` object for the current User/Member. */
             function_exists("setup_userdata") ? setup_userdata() : null;
             /* Update global vars. */
             /**/
             $lwp = c_ws_plugin__s2member_login_redirects::login_redirection_url($user);
             $lwp = !$lwp ? get_page_link($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]) : $lwp;
             /**/
             if (empty($_p["ws_plugin__s2member_sc_profile_save"])) {
                 echo '<script type="text/javascript">' . "\n";
                 echo "if(window.parent && window.parent != window) { window.parent.alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Profile updated successfully.", "s2member-front", "s2member")) . "'); window.parent.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($lwp) . "'; }";
                 echo "else if(window.opener) { window.alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Profile updated successfully.", "s2member-front", "s2member")) . "'); window.opener.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($lwp) . "'; window.close(); }";
                 echo "else { alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Profile updated successfully.", "s2member-front", "s2member")) . "'); window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($lwp) . "'; }";
                 echo '</script>' . "\n";
                 /**/
                 exit;
                 /* Clean exit. */
             }
         }
     }
     /**/
     do_action("ws_plugin__s2member_after_handle_profile_modifications", get_defined_vars());
     /**/
     return;
     /* Return for uniformity. */
 }
Пример #6
0
 /**
  * Callback adds Custom Fields to `/wp-admin/user-new.php`.
  *
  * We have to buffer because `/user-new.php` has NO Hooks.
  *
  * @package s2Member\New_Users
  * @since 3.5
  *
  * @attaches-to ``ob_start("c_ws_plugin__s2member_user_new_in::_admin_user_new_fields");``
  *
  * @return string Output buffer.
  */
 public static function _admin_user_new_fields($buffer = FALSE)
 {
     global $pagenow;
     // The current admin page file name.
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action("_ws_plugin__s2member_before_admin_user_new_fields", get_defined_vars());
     unset($__refs, $__v);
     if (is_blog_admin() && $pagenow === "user-new.php" && current_user_can("create_users")) {
         $_p = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST));
         $unfs = '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
         $unfs .= '<h3 style="position:relative;"><img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member (a Membership management system for WordPress)" alt="" style="position:absolute; top:-15px; right:0; border:0;" />s2Member Configuration &amp; Profile Fields' . (is_multisite() ? ' (for this Blog)' : '') . '</h3>' . "\n";
         $unfs .= '<table class="form-table">' . "\n";
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_before", get_defined_vars());
         unset($__refs, $__v);
         if (is_multisite()) {
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_first_name", get_defined_vars());
             unset($__refs, $__v);
             $unfs .= '<tr>' . "\n";
             $unfs .= '<th><label for="ws-plugin--s2member-user-new-first-name">First Name:</label></th>' . "\n";
             $unfs .= '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_user_new_first_name" id="ws-plugin--s2member-user-new-first-name" value="' . esc_attr($_p["ws_plugin__s2member_user_new_first_name"]) . '" class="regular-text" /></td>' . "\n";
             $unfs .= '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_first_name", get_defined_vars());
             unset($__refs, $__v);
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_last_name", get_defined_vars());
             unset($__refs, $__v);
             $unfs .= '<tr>' . "\n";
             $unfs .= '<th><label for="ws-plugin--s2member-user-new-last-name">Last Name:</label></th>' . "\n";
             $unfs .= '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_user_new_last_name" id="ws-plugin--s2member-user-new-last-name" value="' . esc_attr($_p["ws_plugin__s2member_user_new_last_name"]) . '" class="regular-text" /></td>' . "\n";
             $unfs .= '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_last_name", get_defined_vars());
             unset($__refs, $__v);
         }
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_subscr_gateway", get_defined_vars());
         unset($__refs, $__v);
         $unfs .= '<tr>' . "\n";
         $unfs .= '<th><label for="ws-plugin--s2member-user-new-s2member-subscr-gateway">Paid Subscr. Gateway:</label> <a href="#" onclick="alert(\'A Payment Gateway code is associated with the Paid Subscr. ID below. A Paid Subscription ID (or a Buy Now Transaction ID) is only valid for paid Members. Also known as (a Recurring Profile ID, a ClickBank Receipt #, a Google Order ID, an AliPay Trade No.). Under normal circumstances, this is filled automatically by s2Member. This field is ONLY here for Customer Service purposes; just in case you ever need to enter a Paid Subscr. Gateway/ID manually. This field will be empty for Free Subscribers, and/or anyone who is NOT paying you.\\n\\nThe value of Paid Subscr. ID, can be a PayPal Standard `Subscription ID`, or a PayPal Pro `Recurring Profile ID`, or a PayPal `Transaction ID`; depending on the type of sale. Your PayPal account will supply this information. If you\\\'re using Google Wallet, use the Google Order ID. ClickBank provides a Receipt #, ccBill provides a Subscription ID, Authorize.Net provides a Subscription ID, and AliPay provides a Transaction ID. The general rule is... IF there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
         $unfs .= '<td><select name="ws_plugin__s2member_user_new_s2member_subscr_gateway" id="ws-plugin--s2member-user-new-s2member-subscr-gateway" style="width:25em;"><option value=""></option>' . "\n";
         foreach (apply_filters("ws_plugin__s2member_profile_s2member_subscr_gateways", array("paypal" => "PayPal (code: paypal)"), get_defined_vars()) as $gateway => $gateway_name) {
             $unfs .= '<option value="' . esc_attr($gateway) . '"' . ($gateway === $_p["ws_plugin__s2member_user_new_s2member_subscr_gateway"] ? ' selected="selected"' : '') . '>' . esc_html($gateway_name) . '</option>' . "\n";
         }
         $unfs .= '</select>' . "\n";
         $unfs .= '</td>' . "\n";
         $unfs .= '</tr>' . "\n";
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_subscr_gateway", get_defined_vars());
         unset($__refs, $__v);
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_subscr_id", get_defined_vars());
         unset($__refs, $__v);
         $unfs .= '<tr>' . "\n";
         $unfs .= '<th><label for="ws-plugin--s2member-user-new-s2member-subscr-id">Paid Subscr. ID:</label> <a href="#" onclick="alert(\'A Paid Subscription ID (or a Buy Now Transaction ID) is only valid for paid Members. Also known as (a Recurring Profile ID, a ClickBank Receipt #, a Google Order ID, an AliPay Trade No.). Under normal circumstances, this is filled automatically by s2Member. This field is ONLY here for Customer Service purposes; just in case you ever need to enter a Paid Subscr. Gateway/ID manually. This field will be empty for Free Subscribers, and/or anyone who is NOT paying you.\\n\\nThe value of Paid Subscr. ID, can be a PayPal Standard `Subscription ID`, or a PayPal Pro `Recurring Profile ID`, or a PayPal `Transaction ID`; depending on the type of sale. Your PayPal account will supply this information. If you\\\'re using Google Wallet, use the Google Order ID. ClickBank provides a Receipt #, ccBill provides a Subscription ID, Authorize.Net provides a Subscription ID, and AliPay provides a Transaction ID. The general rule is... if there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
         $unfs .= '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_user_new_s2member_subscr_id" id="ws-plugin--s2member-user-new-s2member-subscr-id" value="' . format_to_edit($_p["ws_plugin__s2member_user_new_s2member_subscr_id"]) . '" class="regular-text" /></td>' . "\n";
         $unfs .= '</tr>' . "\n";
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_subscr_id", get_defined_vars());
         unset($__refs, $__v);
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_custom", get_defined_vars());
         unset($__refs, $__v);
         $unfs .= '<tr>' . "\n";
         $unfs .= '<th><label for="ws-plugin--s2member-user-new-s2member-custom">Custom Value:</label> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
         $unfs .= '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_user_new_s2member_custom" id="ws-plugin--s2member-user-new-s2member-custom" value="' . format_to_edit($_p["ws_plugin__s2member_user_new_s2member_custom"]) . '" class="regular-text" /></td>' . "\n";
         $unfs .= '</tr>' . "\n";
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_custom", get_defined_vars());
         unset($__refs, $__v);
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_registration_ip", get_defined_vars());
         unset($__refs, $__v);
         $unfs .= '<tr>' . "\n";
         $unfs .= '<th><label for="ws-plugin--s2member-user-new-s2member-registration-ip">Registration IP:</label> <a href="#" onclick="alert(\'This is the IP Address the User had at the time of registration. If you don\\\'t know the User\\\'s IP Address, just leave this blank. If this is left empty, s2Member will make attempts in the future to grab the User\\\'s IP Address.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
         $unfs .= '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_user_new_s2member_registration_ip" id="ws-plugin--s2member-user-new-s2member-registration-ip" value="' . format_to_edit($_p["ws_plugin__s2member_user_new_s2member_registration_ip"]) . '" class="regular-text" /></td>' . "\n";
         $unfs .= '</tr>' . "\n";
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_registration_ip", get_defined_vars());
         unset($__refs, $__v);
         if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_ccaps", get_defined_vars());
             unset($__refs, $__v);
             $unfs .= '<tr>' . "\n";
             $unfs .= '<th><label for="ws-plugin--s2member-user-new-s2member-ccaps">Custom Capabilities:</label> <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.' . (is_multisite() ? '\\n\\nCustom Capabilities are assigned on a per-Blog basis. So having a set of Custom Capabilities for one Blog, and having NO Custom Capabilities on another Blog - is very common. This is how permissions are designed to work.' : '') . '\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
             $unfs .= '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_user_new_s2member_ccaps" id="ws-plugin--s2member-user-new-s2member-ccaps" value="' . format_to_edit($_p["ws_plugin__s2member_user_new_s2member_ccaps"]) . '" class="regular-text" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></td>' . "\n";
             $unfs .= '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_ccaps", get_defined_vars());
             unset($__refs, $__v);
         }
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_auto_eot_time", get_defined_vars());
         unset($__refs, $__v);
         $unfs .= '<tr>' . "\n";
         $unfs .= '<th><label for="ws-plugin--s2member-user-new-auto-eot-time">Automatic EOT Time:</label> <a href="#" onclick="alert(\'EOT = End Of Term. ( i.e., Account Expiration / Termination. ).\\n\\nIf you leave this empty, s2Member will configure an EOT Time automatically, based on the paid Subscription associated with this account. In other words, if a paid Subscription expires, is cancelled, terminated, refunded, reversed, or charged back to you; s2Member will deal with the EOT automatically.\\n\\nThat being said, if you would rather take control over this, you can. If you type in a date manually, s2Member will obey the Auto-EOT Time that you\\\'ve given, no matter what. In other words, you can force certain Members to expire automatically, at a time that you specify. s2Member will obey.\\n\\nValid formats for Automatic EOT Time:\\n\\nmm/dd/yyyy\\nyyyy-mm-dd\\n+1 year\\n+2 weeks\\n+2 months\\n+10 minutes\\nnext thursday\\ntomorrow\\ntoday\\n\\n* anything compatible with PHP\\\'s strtotime() function.\'); return false;" tabindex="-1">[?]</a>' . ($auto_eot_time ? '<br /><small>(<a href="http://www.world-time-zones.org/zones/greenwich-mean-time.htm" target="_blank" rel="external">Universal Time / GMT</a>)</small>' : '') . '</th>' . "\n";
         $unfs .= '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_user_new_s2member_auto_eot_time" id="ws-plugin--s2member-user-new-auto-eot-time" value="' . format_to_edit($_p["ws_plugin__s2member_user_new_s2member_auto_eot_time"]) . '" class="regular-text" /></td>' . "\n";
         $unfs .= '</tr>' . "\n";
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_auto_eot_time", get_defined_vars());
         unset($__refs, $__v);
         if (c_ws_plugin__s2member_list_servers::list_servers_integrated()) {
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_opt_in", get_defined_vars());
             unset($__refs, $__v);
             $unfs .= '<tr>' . "\n";
             $unfs .= '<th><label for="ws-plugin--s2member-user-new-opt-in">Process List Servers:</label> <a href="#" onclick="alert(\'You have at least one List Server integrated with s2Member. Would you like to process a confirmation request for this new User? If not, just leave the box unchecked.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
             $unfs .= '<td><label><input type="checkbox" name="ws_plugin__s2member_user_new_opt_in" id="ws-plugin--s2member-user-new-opt-in" value="1"' . ($_p["ws_plugin__s2member_user_new_opt_in"] ? ' checked="checked"' : '') . ' /> Yes, send a mailing list confirmation email to this new User.</label></td>' . "\n";
             $unfs .= '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_opt_in", get_defined_vars());
             unset($__refs, $__v);
         }
         if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) {
             // Now, do we have Custom Fields?
             if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level("any", "administrative")) {
                 $unfs .= '<tr>' . "\n";
                 $unfs .= '<td colspan="2">' . "\n";
                 $unfs .= '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
                 $unfs .= '</td>' . "\n";
                 $unfs .= '</tr>' . "\n";
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_custom_fields", get_defined_vars());
                 unset($__refs, $__v);
                 foreach (json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field) {
                     foreach (array_keys(get_defined_vars()) as $__v) {
                         $__refs[$__v] =& ${$__v};
                     }
                     do_action("_ws_plugin__s2member_during_admin_user_new_fields_during_custom_fields_before", get_defined_vars());
                     unset($__refs, $__v);
                     if (in_array($field["id"], $fields_applicable)) {
                         $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
                         $field_id_class = preg_replace("/_/", "-", $field_var);
                         foreach (array_keys(get_defined_vars()) as $__v) {
                             $__refs[$__v] =& ${$__v};
                         }
                         if (apply_filters("_ws_plugin__s2member_during_admin_user_new_fields_during_custom_fields_display", true, get_defined_vars())) {
                             if (!empty($field["section"]) && $field["section"] === "yes") {
                                 // Starts a new section?
                                 $unfs .= '<tr><td colspan="2"><div class="ws-plugin--s2member-user-new-divider-section' . (!empty($field["sectitle"]) ? '-title' : '') . '">' . (!empty($field["sectitle"]) ? $field["sectitle"] : '') . '</div></td></tr>';
                             }
                             $unfs .= '<tr>' . "\n";
                             $unfs .= '<th><label for="ws-plugin--s2member-user-new-' . esc_attr($field_id_class) . '">' . (preg_match("/^(checkbox|pre_checkbox)\$/", $field["type"]) ? ucwords(preg_replace("/_/", " ", $field_var)) : $field["label"]) . ':</label></th>' . "\n";
                             $unfs .= '<td>' . c_ws_plugin__s2member_custom_reg_fields::custom_field_gen(__FUNCTION__, $field, "ws_plugin__s2member_user_new_", "ws-plugin--s2member-user-new-", "", preg_match("/^(text|textarea|select|selects)\$/", $field["type"]) ? "width:99%;" : "", "", "", $_p, $_p["ws_plugin__s2member_user_new_" . $field_var], "administrative") . '</td>' . "\n";
                             $unfs .= '</tr>' . "\n";
                         }
                         unset($__refs, $__v);
                     }
                     foreach (array_keys(get_defined_vars()) as $__v) {
                         $__refs[$__v] =& ${$__v};
                     }
                     do_action("_ws_plugin__s2member_during_admin_user_new_fields_during_custom_fields_after", get_defined_vars());
                     unset($__refs, $__v);
                 }
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_custom_fields", get_defined_vars());
                 unset($__refs, $__v);
                 $unfs .= '<tr>' . "\n";
                 $unfs .= '<td colspan="2">' . "\n";
                 $unfs .= '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
                 $unfs .= '</td>' . "\n";
                 $unfs .= '</tr>' . "\n";
             }
         }
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_before_notes", get_defined_vars());
         unset($__refs, $__v);
         $unfs .= '<tr>' . "\n";
         $unfs .= '<th><label for="ws-plugin--s2member-user-new-s2member-notes">Administrative Notes:</label> <a href="#" onclick="alert(\'This is for Administrative purposes. You can keep a list of Notations about this account. These Notations are private; Users/Members will never see these.\\n\\n*Note* The s2Member software may `append` Notes to this field occasionally, under special circumstances. For example, when/if s2Member demotes a paid Member to a Free Subscriber, s2Member will leave a Note in this field.\'); return false;" tabindex="-1">[?]</a><br /><br /><small>These Notations are private; Users/Members will never see any of these notes.</small></th>' . "\n";
         $unfs .= '<td><textarea name="ws_plugin__s2member_user_new_s2member_notes" id="ws-plugin--s2member-user-new-s2member-notes" rows="5" wrap="off" spellcheck="false" style="width:99%;">' . format_to_edit($_p["ws_plugin__s2member_user_new_s2member_notes"]) . '</textarea></td>' . "\n";
         $unfs .= '</tr>' . "\n";
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_after_notes", get_defined_vars());
         unset($__refs, $__v);
         foreach (array_keys(get_defined_vars()) as $__v) {
             $__refs[$__v] =& ${$__v};
         }
         do_action("_ws_plugin__s2member_during_admin_user_new_fields_after", get_defined_vars());
         unset($__refs, $__v);
         $unfs .= '</table>' . "\n";
         $unfs .= '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
         $buffer = preg_replace("/(\\<\\/table\\>)(\\s*)(\\<p\\s+class\\s*\\=\\s*['\"]submit['\"]\\s*\\>)(\\s*)(\\<input\\s+type\\s*\\=\\s*['\"]submit['\"]\\s+name\\s*\\=\\s*['\"]createuser['\"])/", "\$1\$2\n" . $unfs . "\$3\$4\$5", $buffer);
     }
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action("_ws_plugin__s2member_after_admin_user_new_fields", get_defined_vars());
     unset($__refs, $__v);
     return apply_filters("_ws_plugin__s2member_admin_user_new_fields", $buffer, get_defined_vars());
 }
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     echo '<div class="ws-menu-page-toolbox">' . "\n";
     c_ws_plugin__s2member_menu_pages_tb::display();
     echo '</div>' . "\n";
     echo '<h2>PayPal Buttons</h2>' . "\n";
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     do_action("ws_plugin__s2member_during_paypal_buttons_page_before_left_sections", get_defined_vars());
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         if (($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_levelN_buttons = "ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_level" . $n . "_buttons") && apply_filters($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_levelN_buttons, true, get_defined_vars())) {
             if ($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_levelN_buttons = "ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_level" . $n . "_buttons") {
                 do_action($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_levelN_buttons, get_defined_vars());
             }
             echo '<div class="ws-menu-page-group" title="PayPal Buttons For Level #' . $n . ' Access">' . "\n";
             echo '<div class="ws-menu-page-section ws-plugin--s2member-level' . $n . '-buttons-section">' . "\n";
             echo '<h3>Button Code Generator For Level #' . $n . ' Access</h3>' . "\n";
             echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special PayPal Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their Membership, or fails to make payments on time, s2Member will automatically terminate their Membership privileges. s2Member makes extensive use of the PayPal IPN service. s2Member receives updates from PayPal behind-the-scene.</p>' . "\n";
             echo '<p><em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
             if ($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_levelN_buttons = "ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level" . $n . "_buttons") {
                 do_action($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_levelN_buttons, get_defined_vars());
             }
             echo '<table class="form-table">' . "\n";
             echo '<tbody>' . "\n";
             echo '<tr>' . "\n";
             echo '<th class="ws-menu-page-th-side">' . "\n";
             echo '<label for="ws-plugin--s2member-level' . $n . '-shortcode">' . "\n";
             echo 'Button Code<br />For Level #' . $n . ':<br /><br />' . "\n";
             echo '<div id="ws-plugin--s2member-level' . $n . '-button-prev"></div>' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '<td>' . "\n";
             echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
             echo '<p id="ws-plugin--s2member-level' . $n . '-trial-line">I\'ll offer the first <input type="text" autocomplete="off" id="ws-plugin--s2member-level' . $n . '-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level' . $n . '-trial-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-trial-terms.php"))) . '</select> @ $<input type="text" autocomplete="off" id="ws-plugin--s2member-level' . $n . '-trial-amount" value="0.00" size="4" /></p>' . "\n";
             echo '<p><span id="ws-plugin--s2member-level' . $n . '-trial-then">Then, </span>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-level' . $n . '-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level' . $n . '-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-regular-terms.php"))) . '</select></p>' . "\n";
             echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-level' . $n . '-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level' . $n . '-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level' . $n . '\');" /></p>' . "\n";
             echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-level' . $n . '-desc" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) . ' / description and pricing details here." size="73" /></p>' . "\n";
             echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member ⥱ API Scripting ⥱ Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-level' . $n . '-ccaps" size="40" /></p>' . "\n";
             echo '</form>' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td colspan="2">' . "\n";
             echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
             if ($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_levelN_buttons_before_shortcode = "ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level" . $n . "_buttons_before_shortcode") {
                 do_action($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_levelN_buttons_before_shortcode, get_defined_vars());
             }
             echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
             $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.php")));
             $ws_plugin__s2member_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($n)), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
             echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-level' . $n . '-shortcode" value="' . format_to_edit($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" />' . "\n";
             echo '<div' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '><br />' . "\n";
             echo '<strong>Resulting PayPal Button Code:</strong> (ultimately, your Shortcode will produce this snippet)<br />' . "\n";
             echo '<textarea id="ws-plugin--s2member-level' . $n . '-button" rows="8" wrap="off" onclick="this.select ();">';
             $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/paypal-checkout-button.php")));
             $ws_plugin__s2member_temp_s = preg_replace("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"] ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($n)), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/"))), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_notify=1"))), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_return=1"))), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
             $ws_plugin__s2member_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url())), $ws_plugin__s2member_temp_s);
             echo format_to_edit($ws_plugin__s2member_temp_s);
             echo '</textarea><br />' . "\n";
             echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
             echo '</div>' . "\n";
             echo '</form>' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
             if ($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_levelN_buttons = "ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_level" . $n . "_buttons") {
                 do_action($ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_levelN_buttons, get_defined_vars());
             }
         }
     }
     if (apply_filters("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_modification_buttons", true, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_modification_buttons", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="PayPal Subscr Modification Buttons">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-modification-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Subscription Modifications</h3>' . "\n";
         echo '<p>If you\'d like to give your Members <em>(and/or your Free Subscribers)</em> the ability to modify their billing plan, by switching to a more expensive option, or a less expensive option; generate a new PayPal Modification Button here. Configure the updated Level, pricing, terms, etc. Then, make that new Modification Button available to Members who are logged into their existing account with you. For example, you might want to insert a "Level #2" Upgrade Button into your Login Welcome Page, which would up-sell existing Level #1 Members to a more expensive plan that you offer.</p>' . "\n";
         echo '<p><em><strong>Important Note:</strong> Modification Buttons should be displayed to existing Users/Members, and they should be logged-in, BEFORE clicking this Button. Otherwise, post-processing of their transaction will fail to recognize the Customer\'s existing account within WordPress. Please display this Button only to Users/Members that are already logged into their account (perhaps in your Login Welcome Page for s2Member), or in another location where you can be absolutely sure that a User/Member is logged in. s2Member\'s Simple Conditionals could also be used to ensure a User/Member is logged in, by wrapping your Shortcode within a Conditional test. For further details, please see: <strong>s2Member ⥱ API Scripting ⥱ Simple Conditionals</strong>.</em></p>' . "\n";
         echo '<p><em><strong>Modification Process:</strong> When you send a Member to PayPal using a Subscription Modification Button, PayPal will ask them to login. Once they\'re logged in, instead of being able to signup for a new Membership, PayPal will provide them with the ability to upgrade and/or downgrade their existing Membership with you, by allowing them to switch to the Membership Plan that was specified in the Subscription Modification Button. PayPal handles this nicely, and you\'ll be happy to know that s2Member has been pre-configured to deal with this scenario as well, so that everything remains automated. Their Membership Access Level will either be promoted, or demoted, based on the actions they took at PayPal during the modification process. Once an existing Member completes their Subscription Modification at PayPal, they\'ll be brought back to their Login Welcome Page, instead of to the registration screen.</em></p>' . "\n";
         echo '<p><em><strong>Also Works For Free Subscribers:</strong> Although a Free Subscriber does not have an existing PayPal Subscription, s2Member is capable of adapting to this scenario gracefully. Just make sure that your existing Free Subscribers <em>(the ones who wish to upgrade)</em> pay for their Membership through a Modification Button generated by s2Member. That will allow them to continue using their existing account with you. In other words, they can keep their existing Username <em>(and anything already associated with that Username)</em>, rather than being forced to re-register after checkout.</em></p>' . "\n";
         echo '<p><em><strong>Make It More User-Friendly:</strong> You can make the Subscription Modification Process, more user-friendly, by setting up a <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can tell s2Member to use that Page Style whenever you generate your Button Code.\'); return false;">Custom Page Style at PayPal</a>, specifically for Subscription Modification Buttons. Use a custom header image, with a brief explanation to the Customer. Something like, "Log into PayPal", "You can Modify your Subscription!".</em></p>' . "\n";
         echo '<p><em><strong>Integrating Conditionals:</strong> Since each Modification Button is configured for a specific Level, you may want to create multiple Modification Buttons, one for each combination you intend to make available. s2Member\'s API Conditionals can help you display the proper Button to each Customer, based on the status of their existing account. For further details, see: <strong>s2Member ⥱ API Scripting</strong>.</em></p>' . "\n";
         echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<p><em><strong>Independent Custom Capabilities:</strong> If you just want to sell an existing Member new Custom Capabilities, without affecting their paid Subscription in any way, please see the next Button Generator: <code>Capability (Buy Now) Buttons</code>. Independent Capability Buttons facilitate Buy Now functionality, specifically for Custom Capabilities, without affecting the Customer\'s primary Subscription and Membership Level Access.</em></p>' . "\n" : '';
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_modification_buttons", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-modification-shortcode">' . "\n";
         echo 'Button Code<br />For Modifications:<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-modification-button-prev"></div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>Modification: <select id="ws-plugin--s2member-modification-level">' . "\n";
         for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             echo '<optgroup label="Level #' . $n . '">' . "\n";
             echo '<option value="upgrade:' . $n . '">&uarr; Upgrade To Level #' . $n . '</option>' . "\n";
             echo $n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? '<option value="downgrade:' . $n . '">&darr; Downgrade To Level #' . $n . '</option>' . "\n" : '';
             echo '</optgroup>' . "\n";
             echo $n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? '<option disabled="disabled"></option>' . "\n" : '';
         }
         echo '</select></p>' . "\n";
         echo '<p id="ws-plugin--s2member-modification-trial-line">I\'ll offer the first <input type="text" autocomplete="off" id="ws-plugin--s2member-modification-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-modification-trial-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-trial-terms.php"))) . '</select> @ $<input type="text" autocomplete="off" id="ws-plugin--s2member-modification-trial-amount" value="0.00" size="4" /></p>' . "\n";
         echo '<p><span id="ws-plugin--s2member-modification-trial-then">Then, </span>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-modification-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-modification-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-regular-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-modification-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-modification-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'modification\');" /></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-modification-desc" value="Description and pricing details here." size="73" /></p>' . "\n";
         echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member ⥱ API Scripting ⥱ Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-modification-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_modification_buttons_before_shortcode", get_defined_vars());
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.php")));
         $ws_plugin__s2member_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr("1")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%level_label%% /", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/\\/]\$/", 'modify="1" /]', $ws_plugin__s2member_temp_s);
         // Adds modify="1" to the end of the Shortcode.
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-modification-shortcode" value="' . format_to_edit($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" />' . "\n";
         echo '<div' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '><br />' . "\n";
         echo '<strong>Resulting PayPal Button Code:</strong> (ultimately, your Shortcode will produce this snippet)<br />' . "\n";
         echo '<textarea id="ws-plugin--s2member-modification-button" rows="8" wrap="off" onclick="this.select ();">';
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/paypal-checkout-button.php")));
         $ws_plugin__s2member_temp_s = preg_replace('/name\\="modify" value\\="(.*?)"/', 'name="modify" value="1"', $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"] ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr("1")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%level_label%% /", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_notify=1"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_return=1"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url())), $ws_plugin__s2member_temp_s);
         echo format_to_edit($ws_plugin__s2member_temp_s);
         echo '</textarea><br />' . "\n";
         echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
         echo '</div>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_modification_buttons", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_ccap_buttons", !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site(), get_defined_vars())) {
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_ccap_buttons", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="PayPal Capability (Buy Now) Buttons">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-ccap-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Independent Custom Capabilities</h3>' . "\n";
         echo '<p>This is VERY advanced. For further details, please check your Dashboard: <strong>s2Member ⥱ API Scripting ⥱ Custom Capabiities</strong>.</p>' . "\n";
         echo '<p>With s2Member, you can sell one or more Custom Capabilities using Buy Now functionality, to "existing" Users/Members, regardless of which Membership Level they have on your site <em>(i.e., you could even sell Independent Custom Capabilities to Users at Membership Level #0, normally referred to as Free Subscribers, if you like)</em>. So this is quite flexible. Independent Custom Capabilities do NOT rely on any specific Membership Level. That\'s why s2Member refers to these as `Independent` Custom Capabilities, because you can sell Capabilities this way, through Buy Now functionality, and the Customer\'s Membership Level Access, along with any existing paid Subscription they may already have with you, will remain completely unaffected. That being said, if you intend to charge a recurring fee for Custom Capabilities, please use a <code>Subscr. Modification Button</code> instead; because Independent Custom Capabilities can only be sold through Buy Now functionality.</p>' . "\n";
         echo '<p>Independent Custom Capabilities are added to a Customer\'s account immediately after checkout, and the Customer will have the Custom Capabilities for as long as their Membership lasts, based on their primary Subscription with your site, and/or forever, if they have a Lifetime account with you. In other words, Independent Custom Capabilities will exist on the Customer\'s account forever, or until an EOT <em>(End Of Term)</em> occurs on their primary Subscription with you; in which case s2Member would demote or delete the Customer\'s account <em>(based on your EOT configuration)</em>, and all Custom Capabilities are removed as well.</p>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each set of Custom Capabilities that you plan to sell. Then press (Generate Button Code). These special PayPal Buttons are customized to work with s2Member seamlessly. The Customer will be granted additional access to one or more Custom Capabilities that you specify; while the Customer\'s Membership Level Access and any existing paid Subscription they may already have with you, will remain completely unaffected.</p>' . "\n";
         echo '<p><em><strong>Important Note:</strong> Independent Custom Capability Buttons should ONLY be displayed to existing Users/Members, and they MUST be logged-in, BEFORE clicking this Button. Otherwise, post-processing of their transaction will fail to recognize the Customer\'s existing account within WordPress. Please display this Button only to Users/Members that are already logged into their account (perhaps in your Login Welcome Page for s2Member), or in another location where you can be absolutely sure that a User/Member is logged in. s2Member\'s Simple Conditionals could also be used to ensure a User/Member is logged in, by wrapping your Shortcode within a Conditional test. For further details, please see: <strong>s2Member ⥱ API Scripting ⥱ Simple Conditionals</strong>.</em></p>' . "\n";
         echo '<p><em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your WordPress Editor. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_ccap_buttons", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-ccap-shortcode">' . "\n";
         echo 'Button Code<br />For Capabilities:<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-ccap-button-prev"></div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-ccap-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-ccap-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-ccap-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-ccap-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-ccap-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalCcapButtonGenerate();" /></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-ccap-desc" value="Description and pricing details here." size="73" /></p>' . "\n";
         echo '<p>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member ⥱ API Scripting ⥱ Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-ccap-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_ccap_buttons_before_shortcode", get_defined_vars());
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-ccaps-checkout-button-shortcode.php")));
         $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-ccap-shortcode" value="' . format_to_edit($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" />' . "\n";
         echo '<div' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '><br />' . "\n";
         echo '<strong>Resulting PayPal Button Code:</strong> (ultimately, your Shortcode will produce this snippet)<br />' . "\n";
         echo '<textarea id="ws-plugin--s2member-ccap-button" rows="8" wrap="off" onclick="this.select ();">';
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/paypal-ccaps-checkout-button.php")));
         $ws_plugin__s2member_temp_s = preg_replace("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"] ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_notify=1"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_return=1"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url())), $ws_plugin__s2member_temp_s);
         echo format_to_edit($ws_plugin__s2member_temp_s);
         echo '</textarea><br />' . "\n";
         echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
         echo '</div>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_ccap_buttons", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_cancellation_buttons", true, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_cancellation_buttons", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="PayPal Subscr Cancellation Buttons">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-cancellation-buttons-section">' . "\n";
         echo '<h3>One Button Does It All For Cancellations (copy/paste)</h3>' . "\n";
         echo '<p>Since all recurring charges are associated with a PayPal Subscription; and every PayPal Subscription is associated with a PayPal Account; your Members will always have a PayPal Account of their own, which is tied to their Membership with you. So... a Member can simply log into their own PayPal account and cancel their Subscription(s) with you at anytime, all on their own. However, some Customers do not realize this. So, if you would like to make it clearer (easier) for Members to cancel their own Subscription(s), you can provide this Cancellation Button for them on your Login Welcome Page, or somewhere in the support section of your website. Note... you don\'t have to use this Cancellation Button at all, if you don\'t want to. It\'s completely optional.</p>' . "\n";
         echo '<p><em><strong>Cancellation Process:</strong> Very simple. A Member clicks the Cancellation Button. PayPal asks them to log into their PayPal account. Once they\'re logged in, PayPal will display a list of all active Subscriptions they have with you. They choose which ones they want to cancel, and s2Member is notified silently behind-the-scenes, through the PayPal IPN service.</em></p>' . "\n";
         echo '<p><em><strong>Understanding Cancellations:</strong> It\'s important to realize that a Cancellation is not an EOT (End Of Term). All that happens during a Cancellation event, is that billing is stopped, and it\'s understood that the Customer is going to lose access, at some point in the future. This does NOT mean, that access will be revoked immediately. A separate EOT event will automatically handle a (demotion or deletion) later, at the appropriate time; which could be several days, or even a year after the Cancellation took place.</em></p>' . "\n";
         echo '<p><em><strong>Some Hairy Details:</strong> There might be times whenever you notice that a Member\'s Subscription has been cancelled through PayPal... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when an EOT (End Of Term) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member.</em></p>' . "\n";
         echo '<p><em>s2Member will not process an EOT (End Of Term) until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system (based on your configuration). s2Member also calculates one extra day (24 hours) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_cancellation_buttons", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-cancellation-shortcode">' . "\n";
         echo 'Button Code<br />For Cancellations:<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-cancellation-button-prev">' . "\n";
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/paypal-cancellation-button.php")));
         $ws_plugin__s2member_temp_s = preg_replace("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"] ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url())), $ws_plugin__s2member_temp_s);
         echo preg_replace("/\\<a/", '<a target="_blank"', $ws_plugin__s2member_temp_s);
         echo '</div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>No configuration necessary.</p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_cancellation_buttons_before_shortcode", get_defined_vars());
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-cancellation-button-shortcode.php")));
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-cancellation-shortcode" value="' . format_to_edit($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" />' . "\n";
         echo '<div' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '><br />' . "\n";
         echo '<strong>Resulting PayPal Button Code:</strong> (ultimately, your Shortcode will produce this snippet)<br />' . "\n";
         echo '<textarea id="ws-plugin--s2member-cancellation-button" rows="8" wrap="off" onclick="this.select ();">';
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/paypal-cancellation-button.php")));
         $ws_plugin__s2member_temp_s = preg_replace("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"] ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url())), $ws_plugin__s2member_temp_s);
         echo format_to_edit($ws_plugin__s2member_temp_s);
         echo '</textarea><br />' . "\n";
         echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
         echo '</div>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_cancellation_buttons", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_reg_links", true, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_reg_links", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="PayPal Member Registration Access Links">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-reg-links-section">' . "\n";
         echo '<h3>Registration Access Link Generator (for Customer Service)</h3>' . "\n";
         echo '<p>s2Member automatically generates Registration Access Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Registration Access Link to be created manually, you can use this tool for that. Alternatively, you can create their account yourself/manually by going to <strong>Users ⥱ Add New</strong>. Either of these methods will work fine.</p>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_reg_links", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>Paid Membership Level#: <select id="ws-plugin--s2member-reg-link-level" style="min-width:200px;">' . "\n";
         for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             echo '<option value="' . $n . '">s2Member Level #' . $n . '</option>' . "\n";
         }
         echo '</select></p>' . "\n";
         echo '<p>Paid Subscr. ID: <input type="text" autocomplete="off" id="ws-plugin--s2member-reg-link-subscr-id" value="" size="50" /> <a href="#" onclick="alert(\'The Customer\\\'s Paid Subscr. ID (aka: Recurring Profile ID, Transaction ID) must be unique. This value can be obtained from inside your PayPal account under the History tab. Each paying Customer MUST be associated with a unique Paid Subscr. ID. If the Customer is NOT associated with a Paid Subscr. ID, you will need to generate a unique value for this field on your own. But keep in mind, s2Member will be unable to maintain future communication with the PayPal IPN (i.e., Notification) service if this value does not reflect a real Paid Subscr. ID that exists in your PayPal History log.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p>Custom String Value: <input type="text" autocomplete="off" id="ws-plugin--s2member-reg-link-custom" value="' . esc_attr($_SERVER["HTTP_HOST"]) . '" size="30" /> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_paypalRegLinkGenerate();" /> <img id="ws-plugin--s2member-reg-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
         echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member ⥱ API Scripting ⥱ Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-reg-link-ccaps" size="40" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></p>' . "\n";
         echo '<p>Fixed Term Length (for Buy Now transactions): <input type="text" autocomplete="off" id="ws-plugin--s2member-reg-link-fixed-term" value="" size="10" /> <a href="#" onclick="alert(\'If the Customer purchased Membership through a Buy Now transaction (i.e., there is no Initial/Trial Period and no recurring charges for ongoing access), you may configure a Fixed Term Length in this field. This way the Customer\\\'s Membership Access is automatically revoked by s2Member at the appropriate time. This will be a numeric value, followed by a space, then a single letter.\\n\\nHere are some examples:\\n\\n1 D (this means 1 Day)\\n1 W (this means 1 Week)\\n1 M (this means 1 Month)\\n1 Y (this means 1 Year)\\n1 L (this means 1 Lifetime)\'); return false;">[?]</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-reg-link" style="display:none;"></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_reg_links", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_sp_buttons", true, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_sp_buttons", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="PayPal Specific Post/Page (Buy Now) Buttons">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Specific Post/Page Buttons</h3>' . "\n";
         echo '<p>s2Member now supports an additional layer of functionality (very powerful), which allows you to sell access to specific Posts/Pages that you\'ve created in WordPress. Specific Post/Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Posts/Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be.</p>' . "\n";
         echo '<p>In other words, Customers will NOT need to login, just to receive access to the Specific Post/Page they purchased access to. s2Member will immediately redirect the Customer to the Specific Post/Page after checkout is completed successfully. An email is also sent to the Customer with a link (see: <strong>s2Member ⥱ PayPal Options ⥱ Specific Post/Page Email</strong>). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>' . "\n";
         echo '<p>Specific Post/Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Post/Page on your site; one that you created in WordPress. A Specific Post/Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress Post/Page that you\'ve created. To protect Specific Posts/Pages, please see: <strong>s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access</strong>. Once you\'ve configured your Specific Post/Page Restrictions, those Posts/Pages will be available in the menus below.</p>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each Post/Page that you plan to sell. Then press (Generate Button Code). These special PayPal Buttons are customized to work with s2Member seamlessly. You can even Package Additional Posts/Pages together into one transaction.</p>' . "\n";
         echo '<p><em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your WordPress Editor. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one. If you\'re in Sandbox Test-Mode, and you\'re NOT using the Shortcode Format, please remember to come back and re-generate your Buttons before you go live.</em></p>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_sp_buttons", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-sp-shortcode">' . "\n";
         echo 'Button Code<br />Specific Posts/Pages:<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-sp-button-prev"></div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p><select id="ws-plugin--s2member-sp-leading-id">' . "\n";
         echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
         $ws_plugin__s2member_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
         foreach ($ws_plugin__s2member_temp_a_singulars as $ws_plugin__s2member_temp_o) {
             echo '<option value="' . esc_attr($ws_plugin__s2member_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
         }
         echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p><select id="ws-plugin--s2member-sp-additional-ids" multiple="multiple" style="height:100px;">' . "\n";
         echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
         foreach ($ws_plugin__s2member_temp_a_singulars as $ws_plugin__s2member_temp_o) {
             echo '<option value="' . esc_attr($ws_plugin__s2member_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
         }
         echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-sp-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-sp-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-sp-hours.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-sp-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
         echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-sp-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-sp-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalSpButtonGenerate();" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_sp_buttons_before_shortcode", get_defined_vars());
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-sp-checkout-button-shortcode.php")));
         $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-sp-shortcode" value="' . format_to_edit($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" />' . "\n";
         echo '<div' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '><br />' . "\n";
         echo '<strong>Resulting PayPal Button Code:</strong> (ultimately, your Shortcode will produce this snippet)<br />' . "\n";
         echo '<textarea id="ws-plugin--s2member-sp-button" rows="8" wrap="off" onclick="this.select ();">';
         $ws_plugin__s2member_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/paypal-sp-checkout-button.php")));
         $ws_plugin__s2member_temp_s = preg_replace("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"] ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_notify=1"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url("/?s2member_paypal_return=1"))), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
         $ws_plugin__s2member_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url())), $ws_plugin__s2member_temp_s);
         echo format_to_edit($ws_plugin__s2member_temp_s);
         echo '</textarea><br />' . "\n";
         echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
         echo '</div>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_sp_buttons", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_sp_links", true, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_sp_links", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="PayPal Specific Post/Page Access Links">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-links-section">' . "\n";
         echo '<h3>Specific Post/Page Access Link Generator (for Customer Service)</h3>' . "\n";
         echo '<p>s2Member automatically generates Specific Post/Page Access Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Specific Post/Page Access Link to be created manually, you can use this tool for that.</p>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_sp_links", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p><select id="ws-plugin--s2member-sp-link-leading-id">' . "\n";
         echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
         $ws_plugin__s2member_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
         foreach ($ws_plugin__s2member_temp_a_singulars as $ws_plugin__s2member_temp_o) {
             echo '<option value="' . esc_attr($ws_plugin__s2member_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
         }
         echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p><select id="ws-plugin--s2member-sp-link-additional-ids" multiple="multiple" style="height:100px; min-width:450px;">' . "\n";
         echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
         foreach ($ws_plugin__s2member_temp_a_singulars as $ws_plugin__s2member_temp_o) {
             echo '<option value="' . esc_attr($ws_plugin__s2member_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
         }
         echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p><select id="ws-plugin--s2member-sp-link-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-sp-hours.php"))) . '</select> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_paypalSpLinkGenerate();" /> <img id="ws-plugin--s2member-sp-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
         echo '<p id="ws-plugin--s2member-sp-link" style="display:none;"></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_sp_links", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_shortcode_attrs", true, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_shortcode_attrs", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Shortcode Attributes (Explained)">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-shortcode-attrs-section">' . "\n";
         echo '<h3>Shortcode Attributes (Explained In Full Detail)</h3>' . "\n";
         echo '<p>When you generate a Button Code, s2Member will make a <a href="http://codex.wordpress.org/Shortcode_API#Overview" target="_blank" rel="external">Shortcode</a> available to you. Like most Shortcodes for WordPress, s2Member reads Attributes in your Shortcode. These Attributes will be pre-configured by one of s2Member\'s Button Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_shortcode_attrs", get_defined_vars());
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr style="padding-top:0;">' . "\n";
         echo '<td style="padding-top:0;">' . "\n";
         echo '<ul class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>cancel="0"</code> Cancellation Button. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Cancellation Button, <code>1</code> = this IS a Cancellation Button.</li>' . "\n";
         echo '<li><code>cc="USD"</code> 3 character Currency Code. Not valid when <code>cancel="1"</code>.</li>' . "\n";
         echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>ccaps="music,videos"</code> A comma-delimited list of Custom Capabilities. Only valid w/ Membership Level Access and/or Independent Custom Capabilities.</li>' . "\n" : '';
         echo '<li><code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '"</code> must start with your domain. Additional values can be piped in (ex: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3|etc"</code>). Not valid when <code>cancel="1"</code>.</li>' . "\n";
         echo '<li><code>desc="Gold Membership"</code> A brief purchase Description. Not valid when <code>cancel="1"</code>.</li>' . "\n";
         echo '<li><code>dg="0"</code> The Digital Goods directive. s2Member will eventually be integrated with <a href="http://www.s2member.com/paypal-express-co-digitals" target="_blank" rel="external">Digital Goods</a> for inline Express Checkout. But for now, this should always be <code>0</code>.</li>' . "\n";
         echo '<li><code>exp="72"</code> Access Expires (in hours). Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>ids="14"</code> A Post/Page ID#, or a comma-delimited list of IDs. Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>image="default"</code> Button Image Location. Possible values: <code>default</code> = use the default PayPal Button, <code>http://...</code> = location of your custom Image.</li>' . "\n";
         echo '<li><code>lang=""</code> Optional 5 character Button Language Code <em>(ake: Locale Code—ex: <code>en_US</code>)</em>. This controls the interface language of the PayPal Button itself. If unspecified, the language defaults to English (i.e., <code>en_US</code>; or to the value set by an optional MO translation file; which translates s2Member overall). See <a href="https://cms.paypal.com/mx/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECButtonIntegration#id089QD0O0TX4__id08AH904I0YK" target="_blank" rel="external">this list of possible Locale Codes</a>.</li>' . "\n";
         echo '<li><code>lc=""</code> Optional 2 character Country/Locale Code <em>(i.e., Country Code—ex: <code>US</code>)</em>. This controls the interface language used at PayPal during checkout. If unspecified, the language is determined by PayPal when possible, defaulting to <code>US</code> <em>english</em> when not possible. See <a href="https://cms.paypal.com/mx/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECButtonIntegration#id089QD0O0TX4__id08AH904I0YK" target="_blank" rel="external">this list of possible Country Codes</a>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
         echo '<li><code>level="1"</code> Membership Level [1-4] <em>(or, up to the number of configured Levels)</em>. Only valid for Buttons providing paid Membership Level Access.' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' Or, with Independent Custom Capabilities this MUST be set to <code>level="*"</code>, and <code>ccaps=""</code> must NOT be empty <em>(i.e., <code>level="*" ccaps="music,videos"</code>)</em>.') . '</li>' . "\n";
         echo '<li><code>modify="0"</code> Modification directive. Only valid w/ Membership Level Access. Possible values: <code>0</code> = allows Customers to only create a new Subscription, <code>1</code> = allows Customers to modify their current Subscription or sign up for a new one, <code>2</code> = allows Customers to only modify their current Subscription.</li>' . "\n";
         echo '<li><code>ns="1"</code> The <em>no_shipping</em> directive. Possible values: <code>0</code> = prompt for an address, but do not require one, <code>1</code> = do not prompt for a shipping address, <code>2</code> = prompt for an address, and require one. Not valid when <code>cancel="1"</code>.</li>' . "\n";
         echo '<li><code>output="button"</code> Output Type. Possible values: <code>button</code> = PayPal Button w/hidden inputs, <code>anchor</code> = PayPal Button (  &lt;a&gt; anchor tag ) URL w/ ?query string, <code>url</code> = raw URL w/ ?query string.</li>' . "\n";
         echo '<li><code>ps="paypal"</code> PayPal checkout Page Style. Not valid when <code>cancel="1"</code>.</li>' . "\n";
         echo '<li><code>ra="0.01"</code> Regular, Buy Now, and/or Recurring Amount. Must be &gt;= <code>0.01</code>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
         echo '<li><code>rp="1"</code> Regular Period. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Must be &gt;= <code>1</code> (ex: <code>1</code> Week, <code>2</code> Months, <code>1</code> Month, <code>3</code> Days).</li>' . "\n";
         echo '<li><code>rt="M"</code> Regular Term. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years, <code>L</code> = Lifetime.</li>' . "\n";
         echo '<li><code>rr="1"</code> Recurring directive. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>0</code> = non-recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>1</code> = recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>BN</code> = non-recurring "Buy Now" functionality, no Trial Period possible.</li>' . "\n";
         echo '<li><code>rrt=""</code> Recurring Times <em>(i.e., a fixed number of installments)</em>. Only valid w/ Membership Level Access. When unspecified, any recurring charges will remain ongoing until cancelled, or until payments start failing. If this is set to <code>1 or higher</code> the regular recurring charges will only continue for X billing cycles, depending on what you specify. This is only valid when <code>rr="1"</code> for recurring "Subscriptions". Please note that a fixed number of installments, also means a fixed period of access. If a Customer\'s billing is monthly, and you set <code>rrt="3"</code>, billing will continue for only 3 monthly installments. After that, billing would stop, and their access to the site would be revoked as well <em>(based on your EOT Behavior setting under: s2Member ⥱ PayPal Options)</em>.</li>' . "\n";
         echo '<li><code>rra="1"</code> Reattempt failed payments? Possible values: <code>0</code> = do NOT reattempt billing when/if a recurring payment fails; <code>1</code> = yes, DO reattempt billing when/if a recurring payment fails. With PayPal Standard integration, PayPal will retry a maximum of 2 times when you set <code>rra="1"</code>; after that, a Subscription would be terminated due to Max Failed Payments having been reached. PayPal Standard integration does NOT make it possible to configure Max Failed Payments, it simply defaults to a value of <code>2</code> whenever <code>rra="1"</code>, indicating that you DO want to retry failed payments.</li>' . "\n";
         echo '<li><code>sp="0"</code> Specific Post/Page Button. Possible values: <code>0</code> = this is NOT a Specific Post/Page Access Button, <code>1</code> = this IS a Specific Post/Page Access Button.</li>' . "\n";
         echo '<li><code>ta="0.00"</code> Trial Amount. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
         echo '<li><code>tp="0"</code> Trial Period. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
         echo '<li><code>tt="D"</code> Trial Term. Only valid w/ Membership Level Access. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years.</li>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_shortcode_attrs_lis", get_defined_vars());
         echo '</ul>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_shortcode_attrs", get_defined_vars());
     }
     do_action("ws_plugin__s2member_during_paypal_buttons_page_after_left_sections", get_defined_vars());
     echo '</td>' . "\n";
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
 }
Пример #8
0
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     echo '<div class="ws-menu-page-toolbox">' . "\n";
     c_ws_plugin__s2member_menu_pages_tb::display();
     echo '</div>' . "\n";
     echo '<h2>Google Wallet Buttons</h2>' . "\n";
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<div class="ws-menu-page-group" title="Buttons For Level #' . $n . ' Access">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-level' . $n . '-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Level #' . $n . ' Access</h3>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These Google Wallet Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their Membership, or fails to make payments on time, s2Member will automatically terminate their Membership privileges. s2Member makes extensive use of the Google Postback/IPN service. s2Member receives updates from Google behind-the-scene. <em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-level' . $n . '-shortcode">' . "\n";
         echo 'Button Code<br />For Level #' . $n . ':<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-pro-level' . $n . '-button-prev"></div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p id="ws-plugin--s2member-pro-level' . $n . '-trial-line">I\'ll offer the first <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-pro-level' . $n . '-trial-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-membership-trial-terms.php"))) . '</select> @ $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-trial-amount" value="0.00" size="4" /></p>' . "\n";
         echo '<p><span id="ws-plugin--s2member-pro-level' . $n . '-trial-then">Then, </span>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-level' . $n . '-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-membership-regular-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-desc" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) . ' / description and pricing details here." size="73" /></p>' . "\n";
         echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-ccaps" size="40" /></p>' . "\n";
         echo '<p>Currency: <select id="ws-plugin--s2member-pro-level' . $n . '-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-currencies.php"))) . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_googleButtonGenerate(\'level' . $n . '\');" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/google-checkout-button-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($n)), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
     }
     echo '<div class="ws-menu-page-group" title="Modification/Cancellation Buttons">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-cancellation-buttons-section">' . "\n";
     echo '<h3>One Button Does It All For Modifications/Cancellations (copy/paste)</h3>' . "\n";
     echo '<p>Every Google Recurring Subscription can be modified by the Customer, or even cancelled by the Customer through Google Wallet. It\'s very simple. A Member clicks a Modification/Cancellation Button. This brings the Customer to a "Purchase History" screen inside their Google Wallet account. Here they\'ll have easy access to make any changes they like. When important changes occur (such as a cancellation), information regarding this event will be relayed back to s2Member through Google\'s Postback/IPN service. s2Member will react appropriately at that time.</p>' . "\n";
     echo '<p><em><strong>Understanding Cancellations:</strong> It\'s important to realize that a Cancellation is not an EOT (End Of Term). All that happens during a Cancellation event, is that billing is stopped, and it\'s understood that the Customer is going to lose access, at some point in the future. This does NOT mean, that access will be revoked immediately. A separate EOT event will automatically handle a (demotion or deletion) later, at the appropriate time; which could be several days, or even a year after the Cancellation took place.</em></p>' . "\n";
     echo '<p><em><strong>Some Hairy Details:</strong> There might be times whenever you notice that a Member\'s Subscription has been cancelled through Google Wallet... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when an EOT (End Of Term) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member.</em></p>' . "\n";
     echo '<p><em>s2Member will not process an EOT (End Of Term) until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system (based on your configuration). s2Member also calculates one extra day (24 hours) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<th class="ws-menu-page-th-side">' . "\n";
     echo '<label for="ws-plugin--s2member-pro-cancellation-shortcode">' . "\n";
     echo 'Button Code<br />For Cancellations:<br /><br />' . "\n";
     echo '<div id="ws-plugin--s2member-pro-cancellation-button-prev">' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/google-cancellation-button.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member_pro"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr(home_url())), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/&amp;/", "&", $ws_plugin__s2member_pro_temp_s);
     // Match this with the JavaScript generator.
     echo preg_replace("/\\<a/", '<a target="_blank"', $ws_plugin__s2member_pro_temp_s);
     echo '</div>' . "\n";
     echo '</label>' . "\n";
     echo '</th>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p>No configuration necessary.</p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     echo '<td colspan="2">' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/google-cancellation-button-shortcode.php")));
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-cancellation-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
         echo '<div class="ws-menu-page-group" title="Capability (Buy Now) Buttons">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-ccap-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Independent Custom Capabilities</h3>' . "\n";
         echo '<p>This is VERY advanced. For further details, please check your Dashboard: <strong>s2Member → API Scripting → Custom Capabiities</strong>.</p>' . "\n";
         echo '<p>With s2Member, you can sell one or more Custom Capabilities using Buy Now functionality, to "existing" Users/Members, regardless of which Membership Level they have on your site <em>(i.e., you could even sell Independent Custom Capabilities to Users at Membership Level #0, normally referred to as Free Subscribers, if you like)</em>. So this is quite flexible. Independent Custom Capabilities do NOT rely on any specific Membership Level. That\'s why s2Member refers to these as `Independent` Custom Capabilities, because you can sell Capabilities this way, through Buy Now functionality, and the Customer\'s Membership Level Access, along with any existing paid Subscription they may already have with you, will remain completely unaffected. That being said, if you intend to charge a recurring fee for Custom Capabilities, please use a <code>Membership Level# Button</code> instead; because Independent Custom Capabilities can only be sold through Buy Now functionality.</p>' . "\n";
         echo '<p>Independent Custom Capabilities are added to a Customer\'s account immediately after checkout, and the Customer will have the Custom Capabilities for as long as their Membership lasts, based on their primary Subscription with your site, and/or forever, if they have a Lifetime account with you. In other words, Independent Custom Capabilities will exist on the Customer\'s account forever, or until an EOT <em>(End Of Term)</em> occurs on their primary Subscription with you; in which case s2Member would demote or delete the Customer\'s account <em>(based on your EOT configuration)</em>, and all Custom Capabilities are removed as well.</p>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each set of Custom Capabilities that you plan to sell. Then press (Generate Button Code). These Google Wallet Buttons are customized to work with s2Member seamlessly. The Customer will be granted additional access to one or more Custom Capabilities that you specify; while the Customer\'s Membership Level Access and any existing paid Subscription they may already have with you, will remain completely unaffected.</p>' . "\n";
         echo '<p><em><strong>Important Note:</strong> Independent Custom Capability Buttons should ONLY be displayed to existing Users/Members, and they MUST be logged-in, BEFORE clicking this Button. Otherwise, post-processing of their transaction will fail to recognize the Customer\'s existing account within WordPress. Please display this Button only to Users/Members that are already logged into their account (perhaps in your Login Welcome Page for s2Member), or in another location where you can be absolutely sure that a User/Member is logged in. s2Member\'s Simple Conditionals could also be used to ensure a User/Member is logged in, by wrapping your Shortcode within a Conditional test. For further details, please see: <strong>s2Member → API Scripting → Simple Conditionals</strong>.</em></p>' . "\n";
         echo '<p><em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-ccap-shortcode">' . "\n";
         echo 'Button Code<br />For Capabilities:<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-pro-ccap-button-prev"></div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-ccap-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-membership-ccap-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-desc" value="Description and pricing details here." size="73" /></p>' . "\n";
         echo '<p>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-ccap-ccaps" size="40" /></p>' . "\n";
         echo '<p>Currency: <select id="ws-plugin--s2member-pro-ccap-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-currencies.php"))) . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_googleCcapButtonGenerate();" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/google-ccaps-checkout-button-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
     }
     echo '<div class="ws-menu-page-group" title="Google Member Registration Access Links">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-reg-links-section">' . "\n";
     echo '<h3>Registration Access Link Generator (for Customer Service)</h3>' . "\n";
     echo '<p>s2Member automatically generates Registration Access Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Registration Access Link to be created manually, you can use this tool for that. Alternatively, you can create their account yourself/manually by going to <strong>Users → Add New</strong>. Either of these methods will work fine.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p>Paid Membership Level#: <select id="ws-plugin--s2member-pro-reg-link-level">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<option value="' . $n . '">s2Member Level #' . $n . '</option>' . "\n";
     }
     echo '</select></p>' . "\n";
     echo '<p>Paid Subscr. ID: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-subscr-id" value="" size="50" /> <a href="#" onclick="alert(\'The Customer\\\'s Paid Subscr. ID (aka: a Google Wallet Order ID. This value can be obtained from inside your Google Wallet account. Each paying Customer MUST be associated with a unique Paid Subscr. ID. If the Customer is NOT associated with a Paid Subscr. ID, you will need to generate a unique value for this field on your own. But keep in mind, s2Member will be unable to maintain future communication with the Google IPN (i.e., Notification/Postback) service if this value does not reflect a real Paid Subscr. ID that exists in your Google Wallet transaction log.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>Custom String Value: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-custom" value="' . esc_attr($_SERVER["HTTP_HOST"]) . '" size="30" /> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_googleRegLinkGenerate();" /> <img id="ws-plugin--s2member-pro-reg-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-ccaps" size="40" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></p>' . "\n";
     echo '<p>Fixed Term Length (for Buy Now transactions): <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-fixed-term" value="" size="10" /> <a href="#" onclick="alert(\'If the Customer purchased Membership through a Buy Now transaction (i.e., there is no Initial/Trial Period and no recurring charges for ongoing access), you may configure a Fixed Term Length in this field. This way the Customer\\\'s Membership Access is revoked by s2Member at the appropriate time. This will be a numeric value, followed by a space, then a single letter.\\n\\nHere are some examples:\\n\\n1 D (this means 1 Day)\\n1 W (this means 1 Week)\\n1 M (this means 1 Month)\\n1 Y (this means 1 Year)\\n1 L (this means 1 Lifetime)\'); return false;">[?]</a></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-reg-link" class="monospace" style="display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Specific Post/Page (Buy Now) Buttons">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-buttons-section">' . "\n";
     echo '<h3>Button Code Generator For Specific Post/Page Buttons</h3>' . "\n";
     echo '<p>s2Member now supports an additional layer of functionality (very powerful), which allows you to sell access to specific Posts/Pages that you\'ve created in WordPress. Specific Post/Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Posts/Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be.</p>' . "\n";
     echo '<p>In other words, Customers will NOT need to login, just to receive access to the Specific Post/Page they purchased access to. s2Member can simply send an email to the Customer with a link (see: <strong>s2Member → Google Options → Specific Post/Page Email</strong>). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>' . "\n";
     echo '<p>Specific Post/Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Post/Page on your site; one that you created in WordPress. A Specific Post/Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress Post/Page that you\'ve created. To protect Specific Posts/Pages, please see: <strong>s2Member → Restriction Options → Specific Post/Page Access</strong>. Once you\'ve configured your Specific Post/Page Restrictions, those Posts/Pages will be available in the menus below.</p>' . "\n";
     echo '<p>Very simple. All you do is customize the form fields provided, for each Post/Page that you plan to sell. Then press (Generate Button Code). These Google Wallet Buttons are customized to work with s2Member seamlessly. You can even Package Additional Posts/Pages together into one transaction. <em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your WordPress Editor, wherever you feel it would be most appropriate. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<th class="ws-menu-page-th-side">' . "\n";
     echo '<label for="ws-plugin--s2member-pro-sp-shortcode">' . "\n";
     echo 'Button Code<br />Specific Posts/Pages:<br /><br />' . "\n";
     echo '<div id="ws-plugin--s2member-pro-sp-button-prev"></div>' . "\n";
     echo '</label>' . "\n";
     echo '</th>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-additional-ids" multiple="multiple" style="height:100px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-sp-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-sp-hours.php"))) . '</select></p>' . "\n";
     echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
     echo '<p>Currency: <select id="ws-plugin--s2member-pro-sp-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-currencies.php"))) . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_googleSpButtonGenerate();" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     echo '<td colspan="2">' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/google-sp-checkout-button-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Specific Post/Page Access Links">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-links-section">' . "\n";
     echo '<h3>Specific Post/Page Access Link Generator (for Customer Service)</h3>' . "\n";
     echo '<p>s2Member automatically generates a Specific Post/Page Access Link for your Customer after checkout; and it sends this link in a Confirmation Email to the customer. However, if you ever need to deal with a Customer Service issue that requires a new Specific Post/Page Access Link to be created manually, you can use this tool for that.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-additional-ids" multiple="multiple" style="height:100px; min-width:450px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/google-sp-hours.php"))) . '</select> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_googleSpLinkGenerate();" /> <img id="ws-plugin--s2member-pro-sp-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-sp-link" class="monospace" style="display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Shortcode Attributes (Explained)">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-shortcode-attrs-section">' . "\n";
     echo '<h3>Shortcode Attributes (Explained In Full Detail)</h3>' . "\n";
     echo '<p>When you generate a Button Code, s2Member will make a <a href="http://s2member.com/r/shortcode-reference/" target="_blank" rel="external">Shortcode</a> available to you. Like most Shortcodes for WordPress, s2Member reads Attributes in your Shortcode. These Attributes will be pre-configured by one of s2Member\'s Button Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
     echo '<table class="form-table" style="margin-top:0;">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr style="padding-top:0;">' . "\n";
     echo '<td style="padding-top:0;">' . "\n";
     echo '<ul class="ws-menu-page-li-margins">' . "\n";
     echo '<li><code>cancel="0"</code> Cancellation Button. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Cancellation Button, <code>1</code> = this IS a Cancellation Button.</li>' . "\n";
     echo '<li><code>cc="USD"</code> 3 character Currency Code. Not valid when <code>modify|cancel="1"</code>. Google currently supports: <code>USD</code>, <code>EUR</code>, <code>CAD</code>, <code>GBP</code>, <code>AUD</code>, <code>HKD</code>, <code>JPY</code>, <code>DKK</code>, <code>NOK</code>, <code>SEK</code>. Note: Google automatically converts the billing currency you specify, to the currency that\'s been defined by your Google Wallet merchant account.</li>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>ccaps="music,videos"</code> A comma-delimited list of Custom Capabilities. Only valid w/ Membership Level Access and/or Independent Custom Capabilities.</li>' . "\n" : '';
     echo '<li><code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '"</code> must start with your domain. Additional values can be piped in (ex: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3|etc"</code>). Not valid when <code>modify|cancel="1"</code>.</li>' . "\n";
     echo '<li><code>desc="Gold Membership"</code> A brief purchase Description. Not valid when <code>modify|cancel="1"</code>.</li>' . "\n";
     echo '<li><code>exp="72"</code> Access Expires (in hours). Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>ids="14"</code> A Post/Page ID#, or a comma-delimited list of IDs. Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>image="default"</code> Button Image Location. Possible values: <code>default</code> = use the default Google Wallet Button, <code>http://...</code> = location of your custom Image.</li>' . "\n";
     echo '<li><code>level="1"</code> Membership Level [1-4] <em>(or, up to the number of configured Levels)</em>. Only valid for Buttons providing paid Membership Level Access.' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' Or, with Independent Custom Capabilities this MUST be set to <code>level="*"</code>, and <code>ccaps=""</code> must NOT be empty <em>(i.e., <code>level="*" ccaps="music,videos"</code>)</em>.') . '</li>' . "\n";
     echo '<li><code>modify="0"</code> Modification Button. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Modification Button, <code>1</code> = this IS a Modification Button.</li>' . "\n";
     echo '<li><code>output="anchor"</code> Output Type. Possible values: <code>anchor</code> = Google Wallet Button (&lt;a&gt; anchor tag) URL w/ onclick handler, <code>url</code> = raw URL w/ possible ?query string (valid only for Modification/Cancellation Buttons). Note that <code>output="url"</code> is NOT valid for most Google Wallet Buttons because of their dependency on JavaScript. Using <code>output="url"</code> is valid only for Modification/Cancellation Buttons where a raw URL is possible.</li>' . "\n";
     echo '<li><code>ra="0.01"</code> Regular, Buy Now, and/or Recurring Amount. Must be &gt;= <code>0.01</code>. Not valid when <code>modify|cancel="1"</code>.</li>' . "\n";
     echo '<li><code>rp="1"</code> Regular Period. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Must be &gt;= <code>1</code> (ex: <code>1</code> Week, <code>2</code> Months, <code>1</code> Month, <code>3</code> Days). Please note—Google Wallet supports only the following recurring interval: <code>monthly</code>. Thus, this MUST be set to a value of <code>1</code> with a term of <code>M</code> if you intend for charges to recur. If you don\'t intend for charges to recur, you can set this to whatever you prefer.</li>' . "\n";
     echo '<li><code>rt="M"</code> Regular Term. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years, <code>L</code> = Lifetime. Please note—Google Wallet supports only the following recurring interval: <code>monthly</code>. Thus, this MUST be set to a value of <code>M</code> with a period of <code>1</code> if you intend for charges to recur. If you don\'t intend for charges to recur, you can set this to whatever you prefer.</li>' . "\n";
     echo '<li><code>rr="1"</code> Recurring directive. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>0</code> = non-recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>1</code> = recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>BN</code> = non-recurring "Buy Now" functionality, no Trial Period possible.</li>' . "\n";
     echo '<li><code>rrt=""</code> Recurring Times <em>(i.e., a fixed number of installments)</em>. Only valid w/ Membership Level Access. When unspecified, any recurring charges will remain ongoing until cancelled, or until payments start failing. If this is set to <code>1 or higher</code> the regular recurring charges will only continue for X billing cycles, depending on what you specify. This is only valid when <code>rr="1"</code> for recurring "Subscriptions". Please note that a fixed number of installments, also means a fixed period of access. If a Customer\'s billing is monthly, and you set <code>rrt="3"</code>, billing will continue for only 3 monthly installments. After that, billing would stop, and their access to the site would be revoked as well <em>(based on your EOT Behavior setting under: s2Member → Google Wallet Options)</em>.</li>' . "\n";
     echo '<li><code>sp="0"</code> Specific Post/Page Button. Possible values: <code>0</code> = this is NOT a Specific Post/Page Access Button, <code>1</code> = this IS a Specific Post/Page Access Button.</li>' . "\n";
     echo '<li><code>ta="0.00"</code> Trial Amount. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
     echo '<li><code>tp="0"</code> Trial Period. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
     echo '<li><code>tt="D"</code> Trial Term. Only valid w/ Membership Level Access. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years.</li>' . "\n";
     echo '</ul>' . "\n";
     echo '<hr />' . "\n";
     echo '<ul class="ws-menu-page-li-margins">' . "\n";
     echo '<li><code>success=""</code> Success Return URL <em>(optional)</em>. s2Member handles this automatically for you. However, if you would prefer to take control over the landing page after checkout <em>(i.e., your own custom Thank-You Page)</em>, you can. If supplied, this must be a full URL, starting with <code>http://</code>.</li>' . "\n";
     echo '<li><code>failure=""</code> Failure Return URL <em>(optional)</em>. s2Member handles this automatically for you. However, if you would prefer to take control over the landing page after a checkout failure <em>(i.e., your own custom Failure Page)</em>, you can. If supplied, this must be a full URL, starting with <code>http://</code>. <strong>Note:</strong> most site owners prefer to leave this empty; doing nothing in this scenario is often exactly what\'s expected by a customer.</li>' . "\n";
     echo '</ul>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '</td>' . "\n";
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
 }
Пример #9
0
 /**
  * Adds Custom Fields to the admin Profile editing page.
  *
  * @package s2Member\Users_List
  * @since 3.5
  *
  * @attaches-to ``add_action("edit_user_profile");``
  * @attaches-to ``add_action("show_user_profile");``
  *
  * @param obj $user Expects a `WP_User` object passed in by the Action Hook.
  * @return null
  */
 public static function users_list_edit_cols($user = FALSE)
 {
     global $current_site, $current_blog;
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action("ws_plugin__s2member_before_users_list_edit_cols", get_defined_vars());
     unset($__refs, $__v);
     $current_user = is_user_logged_in() ? wp_get_current_user() : false;
     // Current User.
     if (is_object($user) && !empty($user->ID) && ($user_id = $user->ID) && is_object($current_user) && !empty($current_user->ID)) {
         $role = c_ws_plugin__s2member_user_access::user_access_role($user);
         // This User's current WordPress Role.
         $level = c_ws_plugin__s2member_user_access::user_access_level($user);
         // User's Access Level for s2Member.
         if (current_user_can("edit_users") && (!is_multisite() || is_super_admin() || is_user_member_of_blog($user_id))) {
             echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
             echo '<h3 style="position:relative;"><img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member (a Membership management system for WordPress)" alt="" style="position:absolute; top:-15px; right:0; border:0;" />s2Member Configuration &amp; Profile Fields' . (is_multisite() ? ' (for this Blog)' : '') . '</h3>' . "\n";
             echo '<table class="form-table">' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_before", get_defined_vars());
             unset($__refs, $__v);
             if (is_multisite() && is_super_admin()) {
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_before_originating_blog", get_defined_vars());
                 unset($__refs, $__v);
                 echo '<tr>' . "\n";
                 echo '<th><label for="ws-plugin--s2member-profile-s2member-originating-blog">Originating Blog ID#:</label> <a href="#" onclick="alert(\'On a Multisite Network, this is how s2Member keeps track of which Blog each User/Member originated from. So this ID#, is automatically associated with a Blog in your Network, matching the User\\\'s point of origin. ~ ONLY a Super Admin can modify this.\\n\\nOn a Multisite Blog Farm, the Originating Blog ID# for your own Customers, will ALWAYS be associated with your (Main Site). It is NOT likely that you\\\'ll need to modify this manually, but s2Member makes it available; just in case.\\n\\n*Tip* - If you add Users (and/or Blogs) with the `Super Admin` Network Administration panel inside WordPress, then you WILL need to set everything manually. s2Member does NOT tamper with automation routines whenever YOU (as a Super Administrator) are working in that area.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
                 echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_originating_blog" id="ws-plugin--s2member-profile-s2member-originating-blog" value="' . format_to_edit(get_user_meta($user_id, "s2member_originating_blog", true)) . '" class="regular-text" /></td>' . "\n";
                 echo '</tr>' . "\n";
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_after_originating_blog", get_defined_vars());
                 unset($__refs, $__v);
             }
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_before_subscr_gateway", get_defined_vars());
             unset($__refs, $__v);
             echo '<tr>' . "\n";
             echo '<th><label for="ws-plugin--s2member-profile-s2member-subscr-gateway">Paid Subscr. Gateway:</label> <a href="#" onclick="alert(\'A Payment Gateway code is associated with the Paid Subscr. ID below. A Paid Subscription ID (or a Buy Now Transaction ID) is only valid for paid Members. Also known as (a Recurring Profile ID, a ClickBank Receipt #, a Google Order ID, an AliPay Trade No.). This will be filled automatically by s2Member.\\n\\nThis field will be empty for Free Subscribers, and/or anyone who is NOT paying you. This field is only editable for Customer Service purposes; just in case you ever need to update the Paid Subscr. Gateway/ID manually.\\n\\nThe value of Paid Subscr. ID, can be a PayPal Standard `Subscription ID`, or a PayPal Pro `Recurring Profile ID`, or a PayPal `Transaction ID`; depending on the type of sale. Your PayPal account will supply this information. If you\\\'re using Google Wallet, use the Google Order ID. ClickBank provides a Receipt #, ccBill provides a Subscription ID, Authorize.Net provides a Subscription ID, and AliPay provides a Transaction ID. The general rule is... IF there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
             echo '<td><select name="ws_plugin__s2member_profile_s2member_subscr_gateway" id="ws-plugin--s2member-profile-s2member-subscr-gateway" style="width:25em;"><option value=""></option>' . "\n";
             foreach (apply_filters("ws_plugin__s2member_profile_s2member_subscr_gateways", array("paypal" => "PayPal (code: paypal)"), get_defined_vars()) as $gateway => $gateway_name) {
                 echo '<option value="' . esc_attr($gateway) . '"' . ($gateway === get_user_option("s2member_subscr_gateway", $user_id) ? ' selected="selected"' : '') . '>' . esc_html($gateway_name) . '</option>' . "\n";
             }
             echo '</select>' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_after_subscr_gateway", get_defined_vars());
             unset($__refs, $__v);
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_before_subscr_id", get_defined_vars());
             unset($__refs, $__v);
             echo '<tr>' . "\n";
             echo '<th><label for="ws-plugin--s2member-profile-s2member-subscr-id">Paid Subscr. ID:</label> <a href="#" onclick="alert(\'A Paid Subscription ID (or a Buy Now Transaction ID) is only valid for paid Members. Also known as (a Recurring Profile ID, a ClickBank Receipt #, a Google Order ID, an AliPay Trade No.). This will be filled automatically by s2Member.\\n\\nThis field will be empty for Free Subscribers, and/or anyone who is NOT paying you. This field is only editable for Customer Service purposes; just in case you ever need to update the Paid Subscr. Gateway/ID manually.\\n\\nThe value of Paid Subscr. ID, can be a PayPal Standard `Subscription ID`, or a PayPal Pro `Recurring Profile ID`, or a PayPal `Transaction ID`; depending on the type of sale. Your PayPal account will supply this information. If you\\\'re using Google Wallet, use the Google Order ID. ClickBank provides a Receipt #, ccBill provides a Subscription ID, Authorize.Net provides a Subscription ID, and AliPay provides a Transaction ID. The general rule is... IF there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
             echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_subscr_id" id="ws-plugin--s2member-profile-s2member-subscr-id" value="' . format_to_edit(get_user_option("s2member_subscr_id", $user_id)) . '" class="regular-text" /></td>' . "\n";
             echo '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_after_subscr_id", get_defined_vars());
             unset($__refs, $__v);
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_before_custom", get_defined_vars());
             unset($__refs, $__v);
             echo '<tr>' . "\n";
             echo '<th><label for="ws-plugin--s2member-profile-s2member-custom">Custom Value:</label> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
             echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_custom" id="ws-plugin--s2member-profile-s2member-custom" value="' . format_to_edit(get_user_option("s2member_custom", $user_id)) . '" class="regular-text" /></td>' . "\n";
             echo '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_after_custom", get_defined_vars());
             unset($__refs, $__v);
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_before_registration_ip", get_defined_vars());
             unset($__refs, $__v);
             echo '<tr>' . "\n";
             echo '<th><label for="ws-plugin--s2member-profile-s2member-registration-ip">Registration IP:</label> <a href="#" onclick="alert(\'This is the IP Address the User had at the time of registration. If you don\\\'t know the User\\\'s IP Address, just leave this blank. If this is left empty, s2Member will make attempts in the future to grab the User\\\'s IP Address.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
             echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_registration_ip" id="ws-plugin--s2member-profile-s2member-registration-ip" value="' . format_to_edit(get_user_option("s2member_registration_ip", $user_id)) . '" class="regular-text" /></td>' . "\n";
             echo '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_after_registration_ip", get_defined_vars());
             unset($__refs, $__v);
             if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
                 foreach ($user->allcaps as $cap => $cap_enabled) {
                     if (preg_match("/^access_s2member_ccap_/", $cap)) {
                         $ccaps[] = preg_replace("/^access_s2member_ccap_/", "", $cap);
                     }
                 }
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_before_ccaps", get_defined_vars());
                 unset($__refs, $__v);
                 echo '<tr>' . "\n";
                 echo '<th><label for="ws-plugin--s2member-profile-s2member-ccaps">Custom Capabilities:</label> <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -› API Scripting -› Custom Capabilities.' . (is_multisite() ? '\\n\\nCustom Capabilities are assigned on a per-Blog basis. So having a set of Custom Capabilities for one Blog, and having NO Custom Capabilities on another Blog - is very common. This is how permissions are designed to work.' : '') . '\'); return false;" tabindex="-1">[?]</a>' . (is_multisite() ? '<br /><small>(for this Blog)</small>' : '') . '</th>' . "\n";
                 echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_ccaps" id="ws-plugin--s2member-profile-s2member-ccaps" value="' . format_to_edit(!empty($ccaps) ? implode(",", $ccaps) : "") . '" class="regular-text" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></td>' . "\n";
                 echo '</tr>' . "\n";
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_after_ccaps", get_defined_vars());
                 unset($__refs, $__v);
             }
             if (!$user->has_cap("administrator")) {
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_before_auto_eot_time", get_defined_vars());
                 unset($__refs, $__v);
                 echo '<tr>' . "\n";
                 $auto_eot_time = get_user_option("s2member_auto_eot_time", $user_id);
                 $auto_eot_time = $auto_eot_time ? date("D M j, Y g:i a T", $auto_eot_time) : "";
                 echo '<th><label for="ws-plugin--s2member-profile-s2member-auto-eot-time">Automatic EOT Time:</label> <a href="#" onclick="alert(\'EOT = End Of Term. ( i.e. Account Expiration / Termination. ).\\n\\nIf you leave this empty, s2Member will configure an EOT Time automatically, based on the paid Subscription associated with this account. In other words, if a paid Subscription expires, is cancelled, terminated, refunded, reversed, or charged back to you; s2Member will deal with the EOT automatically.\\n\\nThat being said, if you would rather take control over this, you can. If you type in a date manually, s2Member will obey the Auto-EOT Time that you\\\'ve given, no matter what. In other words, you can force certain Members to expire automatically, at a time that you specify. s2Member will obey.\\n\\nValid formats for Automatic EOT Time:\\n\\nmm/dd/yyyy\\nyyyy-mm-dd\\n+1 year\\n+2 weeks\\n+2 months\\n+10 minutes\\nnext thursday\\ntomorrow\\ntoday\\n\\n* anything compatible with PHP\\\'s strtotime() function.\'); return false;" tabindex="-1">[?]</a>' . ($auto_eot_time ? '<br /><small>(<a href="http://en.wikipedia.org/wiki/Coordinated_Universal_Time" target="_blank" rel="external">Universal Time / GMT</a>)</small>' : '') . '</th>' . "\n";
                 echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_auto_eot_time" id="ws-plugin--s2member-profile-s2member-auto-eot-time" value="' . format_to_edit($auto_eot_time) . '" class="regular-text" /></td>' . "\n";
                 echo '</tr>' . "\n";
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_after_auto_eot_time", get_defined_vars());
                 unset($__refs, $__v);
                 if (c_ws_plugin__s2member_utils_conds::pro_is_installed()) {
                     foreach (array_keys(get_defined_vars()) as $__v) {
                         $__refs[$__v] =& ${$__v};
                     }
                     do_action("ws_plugin__s2member_during_users_list_edit_cols_before_reset_pass_resend", get_defined_vars());
                     unset($__refs, $__v);
                     echo '<tr>' . "\n";
                     echo '<th><label for="ws-plugin--s2member-profile-reset-pass-resend">Reset Password &amp; Resend Welcome Email Message:</label> <a href="#" onclick="alert(\'Checking this box will tell s2Member to reset this User\\\'s password and then reprocess the New User Email Notification message against this User\\\'s account. This way they\\\'ll get an email message with their Username/Password.\\n\\nThis can be helpful in cases where a User/Member missed the original email message for some reason.\\n\\nThe User\\\'s password is reset to a new auto-generated password by default. However, you can provide a custom password by entering a new password of your choosing in the field above — provided by WordPress itself.\\n\\nIt is also possible to customize the New User Email Notification message with s2Member. Please see: `Dashboard -› s2Member -› General Options -› Email Configuration -› New User Notifications`.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
                     echo '<td><label><input type="checkbox" name="ws_plugin__s2member_profile_reset_pass_resend" id="ws-plugin--s2member-profile-reset-pass-resend" value="1" /> Yes, reset password &amp; resend welcome email message to this User.</label></td>' . "\n";
                     echo '</tr>' . "\n";
                     foreach (array_keys(get_defined_vars()) as $__v) {
                         $__refs[$__v] =& ${$__v};
                     }
                     do_action("ws_plugin__s2member_during_users_list_edit_cols_after_reset_pass_resend", get_defined_vars());
                     unset($__refs, $__v);
                 }
             }
             if (c_ws_plugin__s2member_list_servers::list_servers_integrated()) {
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_before_opt_in", get_defined_vars());
                 unset($__refs, $__v);
                 echo '<tr>' . "\n";
                 echo '<th><label for="ws-plugin--s2member-profile-opt-in">Re-process List Servers:</label> <a href="#" onclick="alert(\'You have at least one List Server integrated with s2Member. Would you like to re-process a confirmation request for this User? If not, just leave the box un-checked.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
                 echo '<td><label><input type="checkbox" name="ws_plugin__s2member_profile_opt_in" id="ws-plugin--s2member-profile-opt-in" value="1" /> Yes, send a mailing list confirmation email to this User.</label></td>' . "\n";
                 echo '</tr>' . "\n";
                 foreach (array_keys(get_defined_vars()) as $__v) {
                     $__refs[$__v] =& ${$__v};
                 }
                 do_action("ws_plugin__s2member_during_users_list_edit_cols_after_opt_in", get_defined_vars());
                 unset($__refs, $__v);
                 if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"]) {
                     if ($custom_reg_auto_op_outs = c_ws_plugin__s2member_utils_strings::wrap_deep($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_outs"], "/^", "\$/i")) {
                         if (c_ws_plugin__s2member_utils_arrays::in_regex_array("user-role-change", $custom_reg_auto_op_outs) || c_ws_plugin__s2member_utils_arrays::in_regex_array("modification", $custom_reg_auto_op_outs)) {
                             foreach (array_keys(get_defined_vars()) as $__v) {
                                 $__refs[$__v] =& ${$__v};
                             }
                             do_action("ws_plugin__s2member_during_users_list_edit_cols_before_auto_opt_out_transitions", get_defined_vars());
                             unset($__refs, $__v);
                             echo '<tr>' . "\n";
                             echo '<th><label for="ws-plugin--s2member-custom-reg-auto-opt-out-transitions">Allow List Transitioning:</label> <a href="#" onclick="alert(\'You\\\'ve configured s2Member with List Transitions enabled. By leaving this box checked, s2Member will Transition the User\\\'s mailing list subscription(s) automatically. For example, if a Member is demoted from Level #2, down to Level #1; s2Member will add them to the Level #1 List(s) after it removes them from the Level #2 List(s).\\n\\nDepending on your configuration of s2Member, a transition may ONLY occur if s2Member IS able to successfully remove them from an existing List. In other words, if they are currently NOT subscribed to any List(s), s2Member may NOT transition them to any new Lists (depending on your configuration).\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
                             echo '<td><label><input type="checkbox" name="ws_plugin__s2member_custom_reg_auto_opt_out_transitions" id="ws-plugin--s2member-custom-reg-auto-opt-out-transitions" value="1" checked="checked" /> Yes, automatically transition this User\'s mailing list subscription(s) when/if I change their Role.</label></td>' . "\n";
                             echo '</tr>' . "\n";
                             foreach (array_keys(get_defined_vars()) as $__v) {
                                 $__refs[$__v] =& ${$__v};
                             }
                             do_action("ws_plugin__s2member_during_users_list_edit_cols_after_auto_opt_out_transitions", get_defined_vars());
                             unset($__refs, $__v);
                         }
                     }
                 }
             }
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_before_ip_restrictions", get_defined_vars());
             unset($__refs, $__v);
             echo '<tr>' . "\n";
             echo '<th><label for="ws-plugin--s2member-profile-ip-restrictions">Reset IP Restrictions:</label> <a href="#" onclick="alert(\'A single Username is only valid for a certain number of unique IP addresses (as configured in your s2Member -› General Options). Once that limit is reached, s2Member assumes there has been a security breach. At that time, s2Member will place a temporary ban (preventing access).\\n\\nIf you have spoken to a legitimate Customer that is receiving an error upon logging in (ex: 503 / too many IP addresses), you can remove this temporary ban by checking the box below. If the abusive behavior continues, s2Member will automatically re-instate IP Restrictions in the future. If you would like to gain further control over IP Restrictions, please check your General Options panel for s2Member.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
             echo '<td><label><input type="checkbox" name="ws_plugin__s2member_profile_ip_restrictions" id="ws-plugin--s2member-profile-ip-restrictions" value="1" /> Yes, delete/reset IP Restrictions associated with this Username.</label>' . (c_ws_plugin__s2member_ip_restrictions::specific_ip_restriction_at_or_above_max(strtolower($user->user_login)) || c_ws_plugin__s2member_ip_restrictions::specific_ip_restriction_breached_security(strtolower($user->user_login)) ? '<br /><em>*WARNING* this User is at (or above) max allowable IP addresses (based on your IP Restrictions).</em>' : '<br /><em>*Note* this User is NOT currently banned by any of your IP Restrictions.</em>') . '</td>' . "\n";
             echo '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_after_ip_restrictions", get_defined_vars());
             unset($__refs, $__v);
             if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) {
                 // Only if configured.
                 if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level($level, "administrative")) {
                     echo '<tr>' . "\n";
                     echo '<td colspan="2">' . "\n";
                     echo '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
                     echo '</td>' . "\n";
                     echo '</tr>' . "\n";
                     $fields = get_user_option("s2member_custom_fields", $user_id);
                     // Existing fields.
                     foreach (array_keys(get_defined_vars()) as $__v) {
                         $__refs[$__v] =& ${$__v};
                     }
                     do_action("ws_plugin__s2member_during_users_list_edit_cols_before_custom_fields", get_defined_vars());
                     unset($__refs, $__v);
                     foreach (json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field) {
                         foreach (array_keys(get_defined_vars()) as $__v) {
                             $__refs[$__v] =& ${$__v};
                         }
                         do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_before", get_defined_vars());
                         unset($__refs, $__v);
                         if (in_array($field["id"], $fields_applicable)) {
                             $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
                             $field_id_class = preg_replace("/_/", "-", $field_var);
                             foreach (array_keys(get_defined_vars()) as $__v) {
                                 $__refs[$__v] =& ${$__v};
                             }
                             if (apply_filters("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_display", true, get_defined_vars())) {
                                 if (!empty($field["section"]) && $field["section"] === "yes") {
                                     // Starts a new section?
                                     echo '<tr><td colspan="2"><div class="ws-plugin--s2member-profile-divider-section' . (!empty($field["sectitle"]) ? '-title' : '') . '">' . (!empty($field["sectitle"]) ? $field["sectitle"] : '') . '</div></td></tr>';
                                 }
                                 echo '<tr>' . "\n";
                                 echo '<th><label for="ws-plugin--s2member-profile-' . esc_attr($field_id_class) . '">' . (preg_match("/^(checkbox|pre_checkbox)\$/", $field["type"]) ? ucwords(preg_replace("/_/", " ", $field_var)) : $field["label"]) . ':</label></th>' . "\n";
                                 echo '<td>' . c_ws_plugin__s2member_custom_reg_fields::custom_field_gen(__FUNCTION__, $field, "ws_plugin__s2member_profile_", "ws-plugin--s2member-profile-", "", preg_match("/^(text|textarea|select|selects)\$/", $field["type"]) ? "width:99%;" : "", "", "", $fields, $fields[$field_var], "administrative") . '</td>' . "\n";
                                 echo '</tr>' . "\n";
                             }
                             unset($__refs, $__v);
                         }
                         foreach (array_keys(get_defined_vars()) as $__v) {
                             $__refs[$__v] =& ${$__v};
                         }
                         do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_after", get_defined_vars());
                         unset($__refs, $__v);
                     }
                     foreach (array_keys(get_defined_vars()) as $__v) {
                         $__refs[$__v] =& ${$__v};
                     }
                     do_action("ws_plugin__s2member_during_users_list_edit_cols_after_custom_fields", get_defined_vars());
                     unset($__refs, $__v);
                     echo '<tr>' . "\n";
                     echo '<td colspan="2">' . "\n";
                     echo '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
                     echo '</td>' . "\n";
                     echo '</tr>' . "\n";
                 }
             }
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_before_notes", get_defined_vars());
             unset($__refs, $__v);
             echo '<tr>' . "\n";
             echo '<th><label for="ws-plugin--s2member-profile-s2member-notes">Administrative Notes:</label> <a href="#" onclick="alert(\'This is for Administrative purposes. You can keep a list of Notations about this account. These Notations are private; Users/Members will never see these.\\n\\n*Note* The s2Member software may `append` Notes to this field occasionally, under special circumstances. For example, when/if s2Member demotes a paid Member to a Free Subscriber, s2Member will leave a Note in this field.\'); return false;" tabindex="-1">[?]</a><br /><br /><small>These Notations are private; Users/Members will never see any of these notes.</small></th>' . "\n";
             echo '<td><textarea name="ws_plugin__s2member_profile_s2member_notes" id="ws-plugin--s2member-profile-s2member-notes" rows="5" wrap="off" spellcheck="false" style="width:99%;">' . format_to_edit(get_user_option("s2member_notes", $user_id)) . '</textarea></td>' . "\n";
             echo '</tr>' . "\n";
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_after_notes", get_defined_vars());
             unset($__refs, $__v);
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action("ws_plugin__s2member_during_users_list_edit_cols_after", get_defined_vars());
             unset($__refs, $__v);
             echo '</table>' . "\n";
             echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
         } else {
             if ($current_user->ID === $user->ID) {
                 if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) {
                     if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level($level, "profile")) {
                         echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
                         echo '<h3>' . _x("Additional Profile Fields", "s2member-front", "s2member") . (is_multisite() ? ' ' . _x("(for this site)", "s2member-front", "s2member") : "") . '</h3>' . "\n";
                         echo '<table class="form-table">' . "\n";
                         foreach (array_keys(get_defined_vars()) as $__v) {
                             $__refs[$__v] =& ${$__v};
                         }
                         do_action("ws_plugin__s2member_during_users_list_edit_cols_before", get_defined_vars());
                         unset($__refs, $__v);
                         $fields = get_user_option("s2member_custom_fields", $user_id);
                         // Existing fields.
                         foreach (array_keys(get_defined_vars()) as $__v) {
                             $__refs[$__v] =& ${$__v};
                         }
                         do_action("ws_plugin__s2member_during_users_list_edit_cols_before_custom_fields", get_defined_vars());
                         unset($__refs, $__v);
                         foreach (json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field) {
                             foreach (array_keys(get_defined_vars()) as $__v) {
                                 $__refs[$__v] =& ${$__v};
                             }
                             do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_before", get_defined_vars());
                             unset($__refs, $__v);
                             if (in_array($field["id"], $fields_applicable)) {
                                 $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
                                 $field_id_class = preg_replace("/_/", "-", $field_var);
                                 foreach (array_keys(get_defined_vars()) as $__v) {
                                     $__refs[$__v] =& ${$__v};
                                 }
                                 if (apply_filters("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_display", true, get_defined_vars())) {
                                     if (!empty($field["section"]) && $field["section"] === "yes") {
                                         // Starts a new section?
                                         echo '<tr><td colspan="2"><div class="ws-plugin--s2member-profile-divider-section' . (!empty($field["sectitle"]) ? '-title' : '') . '">' . (!empty($field["sectitle"]) ? $field["sectitle"] : '') . '</div></td></tr>';
                                     }
                                     echo '<tr>' . "\n";
                                     echo '<th><label for="ws-plugin--s2member-profile-' . esc_attr($field_id_class) . '">' . (preg_match("/^(checkbox|pre_checkbox)\$/", $field["type"]) ? ucwords(preg_replace("/_/", " ", $field_var)) : $field["label"]) . ':</label></th>' . "\n";
                                     echo '<td>' . c_ws_plugin__s2member_custom_reg_fields::custom_field_gen(__FUNCTION__, $field, "ws_plugin__s2member_profile_", "ws-plugin--s2member-profile-", "", preg_match("/^(text|textarea|select|selects)\$/", $field["type"]) ? "width:99%;" : "", "", "", $fields, $fields[$field_var], "profile") . '</td>' . "\n";
                                     echo '</tr>' . "\n";
                                 }
                                 unset($__refs, $__v);
                             }
                             foreach (array_keys(get_defined_vars()) as $__v) {
                                 $__refs[$__v] =& ${$__v};
                             }
                             do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_after", get_defined_vars());
                             unset($__refs, $__v);
                         }
                         foreach (array_keys(get_defined_vars()) as $__v) {
                             $__refs[$__v] =& ${$__v};
                         }
                         do_action("ws_plugin__s2member_during_users_list_edit_cols_after_custom_fields", get_defined_vars());
                         unset($__refs, $__v);
                         foreach (array_keys(get_defined_vars()) as $__v) {
                             $__refs[$__v] =& ${$__v};
                         }
                         do_action("ws_plugin__s2member_during_users_list_edit_cols_after", get_defined_vars());
                         unset($__refs, $__v);
                         echo '</table>' . "\n";
                         echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
                     }
                 }
             }
         }
     }
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action("ws_plugin__s2member_after_users_list_edit_cols", get_defined_vars());
     unset($__refs, $__v);
     return;
 }
Пример #10
0
 /**
  * Handles the Shortcode for: `[s2Stream /]`.
  *
  * @package s2Member\s2File
  * @since 130119
  *
  * @attaches-to ``add_shortcode('s2Stream');``
  *
  * @param array  $attr An array of Attributes.
  * @param string $content Content inside the Shortcode.
  * @param string $shortcode The actual Shortcode name itself.
  *
  * @return string HTML markup that produces an audio/video stream for a specific player.
  */
 public static function sc_get_stream($attr = array(), $content = '', $shortcode = '')
 {
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action('ws_plugin__s2member_before_sc_get_stream', get_defined_vars());
     unset($__refs, $__v);
     // Housekeeping.
     $attr = c_ws_plugin__s2member_utils_strings::trim_qts_deep((array) $attr);
     $attr = shortcode_atts(array('download' => '', 'file_download' => '', 'download_key' => '', 'stream' => 'yes', 'inline' => 'yes', 'storage' => '', 'remote' => '', 'ssl' => '', 'rewrite' => 'yes', 'rewrite_base' => '', 'skip_confirmation' => '', 'url_to_storage_source' => 'yes', 'count_against_user' => 'yes', 'check_user' => 'yes', 'player' => 'jwplayer-v6-rtmp', 'player_id' => 's2-stream-' . md5(uniqid('', TRUE)), 'player_path' => '/jwplayer/jwplayer.js', 'player_key' => '', 'player_title' => '', 'player_image' => '', 'player_mediaid' => '', 'player_description' => '', 'player_captions' => '', 'player_resolutions' => '', 'player_controls' => 'yes', 'player_skin' => '', 'player_stretching' => 'uniform', 'player_width' => '480', 'player_height' => '270', 'player_aspectratio' => '', 'player_autostart' => 'no', 'player_fallback' => 'yes', 'player_mute' => 'no', 'player_primary' => $attr['player'] === 'jw-player-v6' ? 'html5' : 'flash', 'player_repeat' => 'no', 'player_startparam' => '', 'player_option_blocks' => ''), $attr);
     $attr['download'] = !empty($attr['file_download']) ? $attr['file_download'] : $attr['download'];
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action('ws_plugin__s2member_before_sc_get_stream_after_shortcode_atts', get_defined_vars());
     unset($__refs, $__v);
     // Housekeeping.
     foreach ($attr as $key => $value) {
         // Now we need to go through and a `file_` prefix  to certain Attribute keys, for compatibility.
         if (strlen($value) && in_array($key, array('download', 'download_key', 'stream', 'inline', 'storage', 'remote', 'ssl', 'rewrite', 'rewrite_base'))) {
             $config['file_' . $key] = $value;
         } else {
             if (strlen($value) && !in_array($key, array('file_download', 'player')) && strpos($key, 'player_') !== 0) {
                 $config[$key] = $value;
             }
         }
     }
     unset($key, $value);
     // Ditch these now. We don't want these bleeding into Hooks/Filters anyway.
     if (!empty($config) && isset($config['file_download'])) {
         if ($attr['player_resolutions'] && c_ws_plugin__s2member_utils_conds::pro_is_installed()) {
             $file_download_extension = strtolower(ltrim((string) strrchr(basename($config['file_download']), '.'), '.'));
             $file_download_resolution_wo_extension = substr($config['file_download'], 0, -(strlen($file_download_extension) + 1));
             $file_download_wo_resolution_extension = preg_replace('/\\-r[0-9]+([^.]*)$/i', '', $file_download_resolution_wo_extension);
             // e.g., `r720p-HD` is removed here.
             $file_download_resolutions = array();
             // Initialize the array of resolutions.
             foreach (preg_split('/[,;\\s]+/', $attr['player_resolutions'], NULL, PREG_SPLIT_NO_EMPTY) as $_player_resolution) {
                 $_player_resolution = ltrim($_player_resolution, 'Rr');
                 // Remove R|r prefix.
                 $file_download_resolutions[$_player_resolution] = $file_download_wo_resolution_extension . '-r' . $_player_resolution . '.' . $file_download_extension;
             }
             unset($_player_resolution);
             // Housekeeping.
             $file_download_urls = array();
             // Initialize array of all file download urls.
             foreach ($file_download_resolutions as $_player_resolution => $_file_download_resolution) {
                 $_file_download_config = array_merge($config, array('file_download' => $_file_download_resolution));
                 if ($file_download_urls) {
                     // If this is a ANOTHER resolution, don't count it against the user.
                     $_file_download_config = array_merge($_file_download_config, array('check_user' => FALSE, 'count_against_user' => FALSE));
                 }
                 if (!($file_download_urls[str_replace(array('_', '-'), ' ', $_player_resolution)] = c_ws_plugin__s2member_files::create_file_download_url($_file_download_config, TRUE))) {
                     return apply_filters('ws_plugin__s2member_sc_get_stream', NULL, get_defined_vars());
                 }
                 // Failure.
             }
             unset($_player_resolution, $_file_download_resolution, $_file_download_config);
             // Housekeeping.
         } else {
             $file_download_urls = array(c_ws_plugin__s2member_files::create_file_download_url($config, TRUE));
         }
         // Default behavior.
         if ($file_download_urls && $attr['player'] && is_file($template = dirname(dirname(__FILE__)) . '/templates/players/' . $attr['player'] . '.php') && $attr['player_id'] && $attr['player_path']) {
             $template = is_file(TEMPLATEPATH . '/' . basename($template)) ? TEMPLATEPATH . '/' . basename($template) : $template;
             $template = is_file(get_stylesheet_directory() . '/' . basename($template)) ? get_stylesheet_directory() . '/' . basename($template) : $template;
             $template = is_file(WP_CONTENT_DIR . '/' . basename($template)) ? WP_CONTENT_DIR . '/' . basename($template) : $template;
             if (strpos($attr['player'], 'jwplayer-v6') === 0) {
                 $player = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($template)));
                 $_first_file_download_url = array();
                 // Holds the first one.
                 $_last_file_download_url = array();
                 // Holds the last one.
                 $_uses_rtmp_streamers = FALSE;
                 // Streamers use RTMP?
                 $_total_player_sources = count($file_download_urls);
                 // Total sources.
                 $_player_sources_counter = 1;
                 // Player sources counter; needed by the loop below.
                 $player_resolution_aspect_ratio_w = 16;
                 // Default aspect ratio width.
                 $player_resolution_aspect_ratio_h = 9;
                 // Default aspect ratio in height.
                 if ($attr['player_aspectratio'] && preg_match('/^[0-9]+\\:[0-9]+$/', $attr['player_aspectratio'])) {
                     list($player_resolution_aspect_ratio_w, $player_resolution_aspect_ratio_h) = explode(':', $attr['player_aspectratio']);
                 }
                 $player_resolution_aspect_ratio_w = (int) $player_resolution_aspect_ratio_w;
                 // Force integer value.
                 $player_resolution_aspect_ratio_h = (int) $player_resolution_aspect_ratio_h;
                 // Force integer value.
                 // See: <http://wsharks.com/1yzjAl6> and <http://wsharks.com/1yzkhea> regarging the SMIL bitrate hints given here.
                 $player_resolution_bitrates = array(2160 => '35000000', 1440 => '10000000', 1080 => '8000000', 720 => '5000000', 640 => '2500001', 480 => '2500000', 360 => '1000000', 320 => '999999', 240 => '500000', 180 => '300000');
                 $player_resolution_bitrates = apply_filters('ws_plugin__s2member_sc_get_stream_resolution_bitrates', $player_resolution_bitrates, get_defined_vars());
                 $player_resolution_sources_smil_file_id = md5(serialize($attr) . $_SERVER['REMOTE_ADDR']);
                 // Initialize SMIL ID.
                 $player_resolution_sources_smil_file_url = home_url('/s2member-rsf-file.smil?s2member_rsf_file=' . urlencode($player_resolution_sources_smil_file_id) . '&s2member_rsf_file_ip=' . urlencode($_SERVER['REMOTE_ADDR']));
                 $player_resolution_sources_smil_file_url = c_ws_plugin__s2member_utils_urls::add_s2member_sig($player_resolution_sources_smil_file_url);
                 $player_resolution_sources_smil_file_contents = '';
                 // Initialize player sources SMIL file contents.
                 $player_sources = '';
                 // Initialize player sources; empty string.
                 foreach ($file_download_urls as $_file_download_url_label => $_file_download_url) {
                     $_is_first_file_download_url = $_player_sources_counter <= 1;
                     $_is_last_file_download_url = $_player_sources_counter >= $_total_player_sources;
                     if ($_is_first_file_download_url) {
                         // We base this conditional on the first streamer.
                         $_uses_rtmp_streamers = stripos($_file_download_url['streamer'], 'rtmp') === 0;
                     }
                     switch ($attr['player']) {
                         case 'jwplayer-v6':
                             // Default w/ a direct URL (very simple).
                             $player_sources .= ',{';
                             // Open this source; JSON object properties.
                             $player_sources .= "'file': '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($_file_download_url['url']) . "'";
                             if (is_string($_file_download_url_label)) {
                                 $player_sources .= ",'label': '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($_file_download_url_label) . "'";
                             }
                             if ($_is_first_file_download_url) {
                                 $player_sources .= ",'default': 'true'";
                             }
                             $player_sources .= '}';
                             // Close this source.
                             break;
                             // Break switch loop.
                         // Break switch loop.
                         case 'jwplayer-v6-rtmp':
                             // RTMP w/ downloadable fallback (mobile compatibility).
                         // RTMP w/ downloadable fallback (mobile compatibility).
                         case 'jwplayer-v6-rtmp-only':
                             // RTMP streaming only (flash player only).
                             if ($attr['player_resolutions'] && $_total_player_sources > 1 && $_uses_rtmp_streamers) {
                                 if ($_is_first_file_download_url) {
                                     $player_sources .= ',{';
                                     // Open this source; JSON object properties.
                                     $player_sources .= "'file': '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($player_resolution_sources_smil_file_url) . "'";
                                     if ($_is_first_file_download_url) {
                                         $player_sources .= ",'default': 'true'";
                                     }
                                     $player_sources .= '}';
                                     // Close this source.
                                 }
                                 $_file_download_url['smil']['height'] = (int) $_file_download_url_label;
                                 // e.g., `720p-HD` becomes `720`.
                                 if (!$_file_download_url['smil']['height']) {
                                     $_file_download_url['smil']['height'] = 720;
                                 }
                                 // Use a default height if invalid.
                                 $_file_download_url['smil']['width'] = ceil($_file_download_url['smil']['height'] / $player_resolution_aspect_ratio_h * $player_resolution_aspect_ratio_w);
                                 $_file_download_url['smil']['system-bitrate'] = '1';
                                 // Default value.
                                 if (!empty($player_resolution_bitrates[$_file_download_url['smil']['height']])) {
                                     $_file_download_url['smil']['system-bitrate'] = $player_resolution_bitrates[$_file_download_url['smil']['height']];
                                 }
                                 $player_resolution_sources_smil_file_contents .= '<video src="' . esc_attr($_file_download_url['file']) . '"' . ' width="' . esc_attr($_file_download_url['smil']['width']) . '"' . ' height="' . esc_attr($_file_download_url['smil']['height']) . '"' . ' system-bitrate="' . esc_attr($_file_download_url['smil']['system-bitrate']) . '" />';
                             } else {
                                 $player_sources .= ',{';
                                 // Open this source; JSON object properties.
                                 $player_sources .= "'file': '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($_file_download_url['streamer'] . '/' . $_file_download_url['prefix'] . $_file_download_url['file']) . "'";
                                 if (is_string($_file_download_url_label)) {
                                     $player_sources .= ",'label': '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($_file_download_url_label) . "'";
                                 }
                                 if ($_is_first_file_download_url) {
                                     $player_sources .= ",'default': 'true'";
                                 }
                                 $player_sources .= '}';
                                 // Close this source.
                             }
                             if ($_is_last_file_download_url && $attr['player'] === 'jwplayer-v6-rtmp') {
                                 $player_sources .= ',{';
                                 // Open this source; JSON object properties.
                                 $player_sources .= "'file': '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($_file_download_url['url']) . "'";
                                 $player_sources .= '}';
                                 // Close this source.
                             }
                             break;
                             // Break switch loop.
                     }
                     if ($_is_first_file_download_url) {
                         $_first_file_download_url = $_file_download_url;
                         // Record for use later.
                         $player = preg_replace('/%%streamer%%/', $_file_download_url['streamer'], $player);
                         $player = preg_replace('/%%prefix%%/', $_file_download_url['prefix'], $player);
                         $player = preg_replace('/%%file%%/', $_file_download_url['file'], $player);
                         $player = preg_replace('/%%url%%/', $_file_download_url['url'], $player);
                     }
                     if ($_is_last_file_download_url) {
                         $_last_file_download_url = $_file_download_url;
                         // Record for use later.
                     }
                     $_player_sources_counter++;
                     // Increment the counter.
                 }
                 $player_sources = '[' . trim($player_sources, ',') . ']';
                 // Build array.
                 if ($player_resolution_sources_smil_file_contents && $_first_file_download_url) {
                     $player_resolution_sources_smil_file_contents = '<smil>' . ' <head><meta base="' . esc_attr($_first_file_download_url['streamer']) . '" /></head>' . ' <body><switch>' . $player_resolution_sources_smil_file_contents . '</switch></body>' . '</smil>';
                     set_transient('s2m_rsf_' . $player_resolution_sources_smil_file_id, $player_resolution_sources_smil_file_contents, 86400);
                 }
                 unset($_first_file_download_url, $_last_file_download_url, $_uses_rtmp_streamers, $_total_player_sources, $_player_sources_counter, $_is_first_file_download_url, $_is_last_file_download_url, $_file_download_url_label, $_file_download_url);
                 $player = preg_replace('/%%player_id%%/', $attr['player_id'], $player);
                 $player = preg_replace('/%%player_path%%/', $attr['player_path'], $player);
                 $player = preg_replace('/%%player_key%%/', $attr['player_key'], $player);
                 $player = preg_replace('/%%player_title%%/', $attr['player_title'], $player);
                 $player = preg_replace('/%%player_image%%/', $attr['player_image'], $player);
                 $player = preg_replace('/%%player_mediaid%%/', $attr['player_mediaid'], $player);
                 $player = preg_replace('/%%player_description%%/', $attr['player_description'], $player);
                 if ($attr['player_captions'] = c_ws_plugin__s2member_utils_strings::trim($attr['player_captions'], NULL, '[]')) {
                     $player = preg_replace('/%%player_captions%%/', '[' . (strpos($attr['player_captions'], ':') !== FALSE ? $attr['player_captions'] : base64_decode($attr['player_captions'])) . ']', $player);
                 } else {
                     $player = preg_replace('/%%player_captions%%/', '[]', $player);
                 }
                 $player = preg_replace('/%%player_sources%%/', $player_sources, $player);
                 // Sources are constructed dynamically.
                 $player = preg_replace('/%%player_controls%%/', filter_var($attr['player_controls'], FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false', $player);
                 $player = preg_replace('/%%player_width%%/', strpos($attr['player_width'], '%') !== FALSE ? "'" . $attr['player_width'] . "'" : (int) $attr['player_width'], $player);
                 $player = preg_replace('/%%player_height%%/', $attr['player_aspectratio'] ? "''" : (strpos($attr['player_height'], '%') !== FALSE ? "'" . $attr['player_height'] . "'" : (int) $attr['player_height']), $player);
                 $player = preg_replace('/%%player_aspectratio%%/', $attr['player_aspectratio'], $player);
                 $player = preg_replace('/%%player_stretching%%/', $attr['player_stretching'], $player);
                 $player = preg_replace('/%%player_skin%%/', $attr['player_skin'], $player);
                 $player = preg_replace('/%%player_autostart%%/', filter_var($attr['player_autostart'], FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false', $player);
                 $player = preg_replace('/%%player_fallback%%/', filter_var($attr['player_fallback'], FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false', $player);
                 $player = preg_replace('/%%player_mute%%/', filter_var($attr['player_mute'], FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false', $player);
                 $player = preg_replace('/%%player_repeat%%/', filter_var($attr['player_repeat'], FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false', $player);
                 $player = preg_replace('/%%player_startparam%%/', $attr['player_startparam'], $player);
                 $player = preg_replace('/%%player_primary%%/', $attr['player_primary'], $player);
                 $player = preg_replace('/%%player_option_blocks%%/', strpos($attr['player_option_blocks'], ':') !== FALSE ? $attr['player_option_blocks'] : base64_decode($attr['player_option_blocks']), $player);
             }
         }
     }
     return apply_filters('ws_plugin__s2member_sc_get_stream', isset($player) ? $player : NULL, get_defined_vars());
 }
Пример #11
0
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     echo '<div class="ws-menu-page-toolbox">' . "\n";
     c_ws_plugin__s2member_menu_pages_tb::display();
     echo '</div>' . "\n";
     echo '<h2>AliPay Buttons</h2>' . "\n";
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<div class="ws-menu-page-group" title="AliPay Buttons For Level #' . $n . ' Access">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-level' . $n . '-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Level #' . $n . ' Access</h3>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special AliPay Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. s2Member makes extensive use of the AliPay IPN service. s2Member receives updates from AliPay behind-the-scene. <em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-level' . $n . '-shortcode">' . "\n";
         echo 'Button Code<br />For Level #' . $n . ':<br /><br />' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-level' . $n . '-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/alipay-membership-regular-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-desc" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) . ' / description and pricing details here." size="73" /></p>' . "\n";
         echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member ⥱ API Scripting ⥱ Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-ccaps" size="40" /></p>' . "\n";
         echo '<p><input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_alipayButtonGenerate(\'level' . $n . '\');" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/alipay-checkout-button-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($n)), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
     }
     if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
         echo '<div class="ws-menu-page-group" title="AliPay Capability (Buy Now) Buttons">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-ccap-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Independent Custom Capabilities</h3>' . "\n";
         echo '<p>This is VERY advanced. For further details, please check your Dashboard: <strong>s2Member ⥱ API Scripting ⥱ Custom Capabiities</strong>.</p>' . "\n";
         echo '<p>With s2Member, you can sell one or more Custom Capabilities using Buy Now functionality, to "existing" Users/Members, regardless of which Membership Level they have on your site <em>(i.e., you could even sell Independent Custom Capabilities to Users at Membership Level #0, normally referred to as Free Subscribers, if you like)</em>. So this is quite flexible. Independent Custom Capabilities do NOT rely on any specific Membership Level. That\'s why s2Member refers to these as `Independent` Custom Capabilities, because you can sell Capabilities this way, through Buy Now functionality, and the Customer\'s Membership Level Access, along with any existing paid access they may already have with you, will remain completely unaffected.</p>' . "\n";
         echo '<p>Independent Custom Capabilities are added to a Customer\'s account immediately after checkout, and the Customer will have the Custom Capabilities for as long as their Membership lasts, based on their primary Subscription with your site, and/or forever, if they have a Lifetime account with you. In other words, Independent Custom Capabilities will exist on the Customer\'s account forever, or until an EOT <em>(End Of Term)</em> occurs on their primary Subscription with you; in which case s2Member would demote or delete the Customer\'s account <em>(based on your EOT configuration)</em>, and all Custom Capabilities are removed as well.</p>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each set of Custom Capabilities that you plan to sell. Then press (Generate Button Code). These special AliPay Buttons are customized to work with s2Member seamlessly. The Customer will be granted additional access to one or more Custom Capabilities that you specify; while the Customer\'s Membership Level Access and any existing paid Subscription they may already have with you, will remain completely unaffected.</p>' . "\n";
         echo '<p><em><strong>Important Note:</strong> Independent Custom Capability Buttons should ONLY be displayed to existing Users/Members, and they MUST be logged-in, BEFORE clicking this Button. Otherwise, post-processing of their transaction will fail to recognize the Customer\'s existing account within WordPress. Please display this Button only to Users/Members that are already logged into their account (perhaps in your Login Welcome Page for s2Member), or in another location where you can be absolutely sure that a User/Member is logged in. s2Member\'s Simple Conditionals could also be used to ensure a User/Member is logged in, by wrapping your Shortcode within a Conditional test. For further details, please see: <strong>s2Member ⥱ API Scripting ⥱ Simple Conditionals</strong>.</em></p>' . "\n";
         echo '<p><em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-ccap-shortcode">' . "\n";
         echo 'Button Code<br />For Capabilities:<br /><br />' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-ccap-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/alipay-membership-ccap-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-desc" value="Description and pricing details here." size="73" /></p>' . "\n";
         echo '<p>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member ⥱ API Scripting ⥱ Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-ccap-ccaps" size="40" /></p>' . "\n";
         echo '<p><input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_alipayCcapButtonGenerate();" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/alipay-ccaps-checkout-button-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
     }
     echo '<div class="ws-menu-page-group" title="AliPay Member Registration Access Links">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-reg-links-section">' . "\n";
     echo '<h3>Registration Access Link Generator (for Customer Service)</h3>' . "\n";
     echo '<p>s2Member automatically generates Registration Access Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Registration Access Link to be created manually, you can use this tool for that. Alternatively, you can create their account yourself/manually by going to <strong>Users ⥱ Add New</strong>. Either of these methods will work fine.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p>Paid Membership Level#: <select id="ws-plugin--s2member-pro-reg-link-level">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<option value="' . $n . '">s2Member Level #' . $n . '</option>' . "\n";
     }
     echo '</select></p>' . "\n";
     echo '<p>Paid Subscr. ID: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-subscr-id" value="" size="50" /> <a href="#" onclick="alert(\'The Customer\\\'s Paid Subscr. ID ( aka: AliPay Trade No. ) must be unique. This value can be obtained from inside your AliPay account. Each paying Customer MUST be associated with a unique Paid Subscr. ID. If the Customer is NOT associated with a Paid Subscr. ID, you will need to generate a unique value for this field on your own. But keep in mind, s2Member will be unable to maintain future communication with the AliPay IPN (i.e., Notification) service if this value does not reflect a real Paid Subscr. ID that exists in your AliPay transaction log.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>Custom String Value: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-custom" value="' . esc_attr($_SERVER["HTTP_HOST"]) . '" size="30" /> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_alipayRegLinkGenerate();" /> <img id="ws-plugin--s2member-pro-reg-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member ⥱ API Scripting ⥱ Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-ccaps" size="40" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></p>' . "\n";
     echo '<p>Fixed Term Length (for Buy Now transactions): <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-fixed-term" value="" size="10" /> <a href="#" onclick="alert(\'You may configure a Fixed Term Length in this field. This way the Customer\\\'s Membership Access is automatically revoked by s2Member at the appropriate time. This will be a numeric value, followed by a space, then a single letter.\\n\\nHere are some examples:\\n\\n1 D (this means 1 Day)\\n1 W (this means 1 Week)\\n1 M (this means 1 Month)\\n1 Y (this means 1 Year)\\n1 L (this means 1 Lifetime)\'); return false;">[?]</a></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-reg-link" class="monospace" style="display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="AliPay Specific Post/Page (Buy Now) Buttons">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-buttons-section">' . "\n";
     echo '<h3>Button Code Generator For Specific Post/Page Buttons</h3>' . "\n";
     echo '<p>s2Member now supports an additional layer of functionality (very powerful), which allows you to sell access to specific Posts/Pages that you\'ve created in WordPress. Specific Post/Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Posts/Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be.</p>' . "\n";
     echo '<p>In other words, Customers will NOT need to login, just to receive access to the Specific Post/Page they purchased access to. s2Member will immediately redirect the Customer to the Specific Post/Page after checkout is completed successfully. An email is also sent to the Customer with a link (see: <strong>s2Member ⥱ AliPay Options ⥱ Specific Post/Page Email</strong>). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>' . "\n";
     echo '<p>Specific Post/Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Post/Page on your site; one that you created in WordPress. A Specific Post/Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress Post/Page that you\'ve created. To protect Specific Posts/Pages, please see: <strong>s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access</strong>. Once you\'ve configured your Specific Post/Page Restrictions, those Posts/Pages will be available in the menus below.</p>' . "\n";
     echo '<p>Very simple. All you do is customize the form fields provided, for each Post/Page that you plan to sell. Then press (Generate Button Code). These special AliPay Buttons are customized to work with s2Member seamlessly. You can even Package Additional Posts/Pages together into one transaction. <em><strong>Please note:</strong> buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your WordPress Editor, wherever you feel it would be most appropriate. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<th class="ws-menu-page-th-side">' . "\n";
     echo '<label for="ws-plugin--s2member-pro-sp-shortcode">' . "\n";
     echo 'Button Code<br />Specific Posts/Pages:<br /><br />' . "\n";
     echo '</label>' . "\n";
     echo '</th>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-additional-ids" multiple="multiple" style="height:100px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-sp-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/alipay-sp-hours.php"))) . '</select></p>' . "\n";
     echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-desc" value="Description and pricing details here." size="67" /></p>' . "\n";
     echo '<p><input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_alipaySpButtonGenerate();" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     echo '<td colspan="2">' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/alipay-sp-checkout-button-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="AliPay Specific Post/Page Access Links">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-links-section">' . "\n";
     echo '<h3>Specific Post/Page Access Link Generator (for Customer Service)</h3>' . "\n";
     echo '<p>s2Member automatically generates Specific Post/Page Access Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Specific Post/Page Access Link to be created manually, you can use this tool for that.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-additional-ids" multiple="multiple" style="height:100px; min-width:450px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member ⥱ Restriction Options ⥱ Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/alipay-sp-hours.php"))) . '</select> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_alipaySpLinkGenerate();" /> <img id="ws-plugin--s2member-pro-sp-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-sp-link" class="monospace" style="display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Shortcode Attributes (Explained)">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-shortcode-attrs-section">' . "\n";
     echo '<h3>Shortcode Attributes (Explained In Full Detail)</h3>' . "\n";
     echo '<p>When you generate a Button Code, s2Member will make a <a href="http://codex.wordpress.org/Shortcode_API#Overview" target="_blank" rel="external">Shortcode</a> available to you. Like most Shortcodes for WordPress, s2Member reads Attributes in your Shortcode. These Attributes will be pre-configured by one of s2Member\'s Button Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
     echo '<table class="form-table" style="margin-top:0;">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr style="padding-top:0;">' . "\n";
     echo '<td style="padding-top:0;">' . "\n";
     echo '<ul class="ws-menu-page-li-margins">' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>ccaps="music,videos"</code> A comma-delimited list of Custom Capabilities. Only valid w/ Membership Level Access and/or Independent Custom Capabilities.</li>' . "\n" : '';
     echo '<li><code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '"</code> must start with your domain. Additional values can be piped in (ex: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3|etc"</code>).</li>' . "\n";
     echo '<li><code>desc="Gold Membership"</code> A brief purchase Description; which may also include pricing details.</li>' . "\n";
     echo '<li><code>exp="72"</code> Access Expires (in hours). Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>ids="14"</code> A Post/Page ID#, or a comma-delimited list of IDs. Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>image="default"</code> Button Image Location. Possible values: <code>default</code> = use the default AliPay Button, <code>http://...</code> = location of your custom Image.</li>' . "\n";
     echo '<li><code>level="1"</code> Membership Level [1-4] <em>(or, up to the number of configured Levels)</em>. Only valid for Buttons providing paid Membership Level Access.' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' Or, with Independent Custom Capabilities this MUST be set to <code>level="*"</code>, and <code>ccaps=""</code> must NOT be empty <em>(i.e., <code>level="*" ccaps="music,videos"</code>)</em>.') . '</li>' . "\n";
     echo '<li><code>output="anchor"</code> Output Type. Possible values: <code>anchor</code> = AliPay Button (  &lt;a&gt; anchor tag ) URL w/ ?query string, <code>url</code> = raw URL w/ ?query string.</li>' . "\n";
     echo '<li><code>ra="0.01"</code> Regular / Buy Now Amount. Must be &gt;= <code>0.01</code>.</li>' . "\n";
     echo '<li><code>rp="1"</code> Regular Period. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Must be &gt;= <code>1</code> (ex: <code>1</code> Week, <code>2</code> Months, <code>1</code> Month, <code>3</code> Days).</li>' . "\n";
     echo '<li><code>rt="M"</code> Regular Term. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years, <code>L</code> = Lifetime.</li>' . "\n";
     echo '<li><code>sp="0"</code> Specific Post/Page Button. Possible values: <code>0</code> = this is NOT a Specific Post/Page Access Button, <code>1</code> = this IS a Specific Post/Page Access Button.</li>' . "\n";
     echo '<li><code>success=""</code> Success Return URL <em>(optional)</em>. s2Member handles this automatically for you. However, if you would prefer to take control over the landing page after checkout <em>(i.e., your own custom Thank-You Page)</em>, you can. If supplied, this must be a full URL, starting with <code>http://</code>. Note, s2Member will NOT use this value if an existing account holder is being modified. s2Member handles account updates <em>(i.e., billing modification)</em> in a more dynamic way. Your Success Return URL is only applied to (new) Customers.</li>' . "\n";
     echo '</ul>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '</td>' . "\n";
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
 }
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     /**/
     echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
     echo '<h2>s2Member® Pro / Authorize.Net® Pro Forms</h2>' . "\n";
     /**/
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="Quick-Start Guide For Authorize.Net®">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-forms-guide-section">' . "\n";
     echo '<img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
     echo '<h3>Quick-Start Guide For Authorize.Net® Integration</h3>' . "\n";
     echo '<p>The s2Member Pro Module makes it possible for s2Member to use <a href="http://www.s2member.com/authorize.net" target="_blank" rel="external">Authorize.Net®</a> Pro Forms. Pro Forms integrate seamlessly with WordPress® Shortcodes. This allows you to keep Customers on your site at all times, and it consolidates the Checkout / Registration steps into a single form that you can dress up just the way you like. If you would like to take advantage of Authorize.Net® integration, please supply your Authorize.Net® API Login ID, Transaction Key, and Secret MD5 Hash. See <code>s2Member -> Authorize.Net® Options</code>.</p>' . "\n";
     echo '<p><em><strong>*Recurring Billing*</strong> If you plan to use any of the ( `Subscription` ) options in the s2Member Form Generators below, you will ALSO need <a href="http://www.s2member.com/authorize.net-arb" target="_blank" rel="external">ARB ( Automated Recurring Billing )</a> enabled for your Authorize.Net® account. Authorize.Net\'s Recurring Billing service is <strong>required</strong> for all types of ( `Subscriptions` ), whether you intend for them to be recurring or not. However, it is NOT required for ( `Buy Now` ) functionality. The drop-down menus in the Form Generators below, have been marked ( `Subscription` ) and ( `Buy Now` ) just for this reason. This way you can see which options will require the use of Authorize.Net\'s Recurring Billing service. Authorize.Net® will charge you a small monthly fee for their Automated Recurring Billing service.</em></p>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<p><em><strong>*Secure Server*</strong> In order to comply with Authorize.Net® and PCI Compliance policies, as set forth by major credit card companies; you will need to host all of your Authorize.Net® Pro Forms on an SSL enabled site. Please check with your hosting provider to ask about obtaining an SSL certificate for your domain. Please note... when you create Authorize.Net® Pro Forms with s2Member; you\'ll be supplied with WordPress® Shortcodes, which you\'ll insert into Posts/Pages of your choosing. These special Posts/Pages will need to be displayed in SSL mode, using links that start with ( <code>https://</code> ). &mdash; You can skip the SSL certificate during Development/Sandbox testing. SSL is not required until you officially go live. Once you\'re live, you can add the Custom Field <code>s2member_force_ssl = yes</code> to any Post/Page.</em></p>' . "\n" : '<p><em><strong>*Secure Server*</strong> In order to comply with Authorize.Net® and PCI Compliance policies, as set forth by major credit card companies; you will need to host all of your Authorize.Net® Pro Forms on an SSL enabled page. When you create Authorize.Net® Pro Forms with s2Member; you\'ll be supplied with WordPress® Shortcodes, which you\'ll insert into Posts/Pages of your choosing. These special Posts/Pages will need to be displayed in SSL mode, using links that start with ( <code>https://</code> ). You can add the Custom Field <code>s2member_force_ssl = yes</code> to any Post/Page that contains a Pro Form Shortcode. This tells s2Member to force those special Posts/Pages to be viewed over SSL at all times; no matter what.</em></p>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<p><em><strong>*SSL Compatibility*</strong> All themes available at <a href="http://www.primothemes.com/" target="_blank" rel="external">PriMoThemes.com</a> include full support for SSL, as does WordPress® itself. However, there are many themes/plugins that do NOT support SSL enabled Posts/Pages like they should. For this reason, you should be very careful when choosing a WordPress® theme to use with s2Member Pro. Otherwise, your visitors could see the famous "Secure/Insecure" warnings in Internet Explorer® browsers. With s2Member installed, you can add the Custom Field <code>s2member_force_ssl = yes</code> to any Post/Page. s2Member will buffer output on those special Posts/Pages, converting everything over to <code>https://</code> for you automatically, and forcing those specific Posts/Pages to be viewed over a secure SSL connection; so long as your server supports the https protocol.</em></p>' . "\n" : '';
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="Authorize.Net® / Free Registration Forms">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-registration-forms-section">' . "\n";
     echo '<h3>One Form Does It All For Free Registrations ( copy/paste )</h3>' . "\n";
     echo '<p>Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0.</p>' . "\n";
     echo '<p><em><strong>*Note*</strong> the use of this particular Form will override your Open Registration configuration. In other words, making this Form available is the same as turning Open Registration <code>(on)</code>. One of the benefits to this functionality, is that it makes it possible for you to integrate this Free Registration Form in creative ways ( i.e. making it available ONLY under certain circumstances ); while still leaving Open Registration <code>(off)</code> throughout the rest of the site.</em></p>' . "\n";
     echo '<p><em><strong>*Tip ( optional )*</strong> It is also possible to change the <code>level="0"</code> Attribute to something other than the default Level #0 ( Free Subscriber ). For example, if you need to, you can change it to <code>level="1"</code>, attach Custom Capabilities with the <code>ccaps=""</code> Attribute, and even limit this access to a certain timeframe with <code>tp="30" tt="D"</code> ( i.e. 30 Days ). So this Form is very flexible. It can be used to allow free access to just about any aspect of your service. For more information on Attributes, please see the section below: Shortcode Attributes ( Explained ).</em></p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/authnet-registration-form-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr("0")), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level0_label"])), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-registration-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<div class="ws-menu-page-group" title="Authorize.Net® Forms For Level #' . $n . ' Access">' . "\n";
         /**/
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-level' . $n . '-forms-section">' . "\n";
         echo '<h3>Pro Form Generator For Level #' . $n . ' Access</h3>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Form Code). These special Authorize.Net® Forms are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When a Member cancels their Membership, or fails to make payments on time, s2Member will automatically terminate their Membership privileges. s2Member makes extensive use of the Authorize.Net® Silent Post and ARB services. s2Member receives updates from Authorize.Net® behind-the-scene.</p>' . "\n";
         echo '<p><em>* Forms are NOT saved here. This is only a Form Generator. Once you\'ve generated your Form, copy/paste it into any Post/Page you like. You\'ll want to provide your visitors with a link to the Post/Page where this Form is located. We suggest placing a link to this Form on your Membership Options Page. That way your visitors can get registered &amp; checkout!</em></p>' . "\n";
         /**/
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         echo '<p id="ws-plugin--s2member-pro-level' . $n . '-trial-line">I\'ll offer the first <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-pro-level' . $n . '-trial-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-membership-trial-terms.php"))) . '</select> @ $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-trial-amount" value="0.00" size="4" /></p>' . "\n";
         echo '<p><span id="ws-plugin--s2member-pro-level' . $n . '-trial-then">Then, </span>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-level' . $n . '-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-membership-regular-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-desc" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) . ' / description and pricing details here." size="68" /></p>' . "\n";
         echo '<p>Currency: <select id="ws-plugin--s2member-pro-level' . $n . '-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_authnetFormGenerate(\'level' . $n . '\');" class="button-primary" /></p>' . "\n";
         echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma-delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/authnet-checkout-form-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($n)), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '</div>' . "\n";
     }
     /**/
     echo '<div class="ws-menu-page-group" title="Authorize.Net® Billing Modification Forms">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-modification-forms-section">' . "\n";
     echo '<h3>Pro Form Generator For Billing Modifications</h3>' . "\n";
     echo '<p>If you\'d like to give your Members ( and/or your Free Subscribers ) the ability to change ( modify ) their billing plan; you can generate a new Authorize.Net® Modification Form here. Configure the updated Level, pricing, terms, etc. Then, make that new Modification Form available to Members who are logged into their existing account with you. For example, you might want to insert a "Level #2" Upgrade link into your Login Welcome Page, which would up-sell existing Level #1 Members to a more expensive plan that you offer.</p>' . "\n";
     echo '<p><em><strong>*Modification Process*</strong> Very simple. A Member clicks a link to a special Post/Page, which contains a Modification Form you\'ve generated. The Member fills in their billing information. After a successful form submission, s2Member will update the status of their account to the Level, pricing, and terms that you configure below. If the Member already has an existing paid Subscription with you, that paid Subscription will be cancelled automatically behind-the-scene, and a new paid Subscription will be created to replace the old one. Again, the new paid Subscription is based on the Level, pricing, and terms that you specify below. If you need to give Customers some sort of grace period when/if they upgrade to a more expensive plan, please feel free to handle this through the application of free days, or with special pricing configured below.</em></p>' . "\n";
     echo '<p><em><strong>*Integrating Conditionals*</strong> Since each Modification Form is configured for a specific Level, you may want to create multiple Modification Forms, one for each combination you intend to make available. s2Member\'s API Conditionals can help you display the proper Form to each Customer, based on the status of their existing account. For further details, see: <code>s2Member -> API Scripting</code>.</em></p>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<p><em><strong>*Independent Custom Capabilities*</strong> If you just want to sell an existing Member new Custom Capabilities, without affecting their paid Subscription in any way, please see the next Form Generator: <code>Capability (Buy Now) Forms</code>. Independent Capability Forms facilitate Buy Now functionality, specifically for Custom Capabilities, without affecting the Customer\'s primary Subscription and Membership Level Access.</em></p>' . "\n" : '';
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     /**/
     echo '<p>Modification: <select id="ws-plugin--s2member-pro-modification-level">' . "\n";
     /**/
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<optgroup label="Level #' . $n . '">' . "\n";
         echo '<option value="upgrade:' . $n . '">&uarr; Upgrade To Level #' . $n . '</option>' . "\n";
         echo $n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? '<option value="downgrade:' . $n . '">&darr; Downgrade To Level #' . $n . '</option>' . "\n" : '';
         echo '</optgroup>' . "\n";
         /**/
         echo $n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? '<option disabled="disabled"></option>' . "\n" : '';
     }
     /**/
     echo '</select></p>' . "\n";
     /**/
     echo '<p id="ws-plugin--s2member-pro-modification-trial-line">I\'ll offer the first <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-pro-modification-trial-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-membership-trial-terms.php"))) . '</select> @ $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-trial-amount" value="0.00" size="4" /></p>' . "\n";
     echo '<p><span id="ws-plugin--s2member-pro-modification-trial-then">Then, </span>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-modification-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-membership-regular-terms.php"))) . '</select></p>' . "\n";
     echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
     echo '<p>Currency: <select id="ws-plugin--s2member-pro-modification-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_authnetFormGenerate(\'modification\');" class="button-primary" /></p>' . "\n";
     echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma-delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-modification-ccaps" size="40" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/authnet-checkout-form-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr("1")), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/\\/]\$/", 'modify="1" /]', $ws_plugin__s2member_pro_temp_s);
     /* Adds modify="1" to the end of the Shortcode. */
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
         echo '<div class="ws-menu-page-group" title="Authorize.Net® Capability (Buy Now) Forms">' . "\n";
         /**/
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-ccap-forms-section">' . "\n";
         echo '<h3>Pro Form Generator For Independent Custom Capabilities</h3>' . "\n";
         echo '<p>This is VERY advanced. For further details, please check your Dashboard: <code>s2Member -> API Scripting -> Custom Capabiities</code>.</p>' . "\n";
         echo '<p>With s2Member, you can sell one or more Custom Capabilities using Buy Now functionality, to "existing" Users/Members, regardless of which Membership Level they have on your site <em>( i.e. you could even sell Independent Custom Capabilities to Users at Membership Level #0, normally referred to as Free Subscribers, if you like )</em>. So this is quite flexible. Independent Custom Capabilities do NOT rely on any specific Membership Level. That\'s why s2Member refers to these as `Independent` Custom Capabilities, because you can sell Capabilities this way, through Buy Now functionality, and the Customer\'s Membership Level Access, along with any existing paid Subscription they may already have with you, will remain completely unaffected. That being said, if you intend to charge a recurring fee for Custom Capabilities, please use a <code>Billing Modification Form</code> instead; because Independent Custom Capabilities can only be sold through Buy Now functionality.</p>' . "\n";
         echo '<p>Independent Custom Capabilities are added to a Customer\'s account immediately after checkout, and the Customer will have the Custom Capabilities for as long as their Membership lasts, based on their primary Subscription with your site, and/or forever, if they have a Lifetime account with you. In other words, Independent Custom Capabilities will exist on the Customer\'s account forever, or until an EOT <em>( End Of Term )</em> occurs on their primary Subscription with you; in which case s2Member would demote or delete the Customer\'s account <em>( based on your EOT configuration )</em>, and all Custom Capabilities are removed as well.</p>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each set of Custom Capabilities that you plan to sell. Then press (Generate Form Code). These special Authorize.Net® Forms are customized to work with s2Member seamlessly. The Customer will be granted additional access to one or more Custom Capabilities that you specify; while the Customer\'s Membership Level Access and any existing paid Subscription they may already have with you, will remain completely unaffected.</p>' . "\n";
         /**/
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         /**/
         echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-ccap-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-membership-ccap-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
         echo '<p>Currency: <select id="ws-plugin--s2member-pro-ccap-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_authnetCcapFormGenerate();" class="button-primary" /></p>' . "\n";
         echo '<p>Custom Capabilities ( comma-delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-ccap-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/authnet-ccaps-checkout-form-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '</div>' . "\n";
     }
     /**/
     echo '<div class="ws-menu-page-group" title="Authorize.Net® Billing Update Forms">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-update-forms-section">' . "\n";
     echo '<h3>One Form Does It All For Billing Updates ( copy/paste )</h3>' . "\n";
     echo '<p>An Update Form can be provided to existing Members, as a way for them to update their billing information; without modifying their existing paid Subscription in any way. For instance, a Customer may need to update their billing information, because their credit card is expiring, or because they moved their bank account.</p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/authnet-update-form-shortcode.php")));
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-update-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="Authorize.Net® Billing Cancellation Forms">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-cancellation-forms-section">' . "\n";
     echo '<h3>One Form Does It All For Cancellations ( copy/paste )</h3>' . "\n";
     echo '<p>According to Authorize.Net\'s policy on recurring billing, you MUST provide each and every Customer with an easy to way to cancel future charges. Generating a Cancellation Form here, and making that Form available to all Customers is our recommendation. For further details and legalities, please visit the <a href="http://www.s2member.com/authorize.net-developers" target="_blank" rel="external">Authorize.Net® Developer Network</a>.</p>' . "\n";
     echo '<p><em><strong>*Cancellation Process*</strong> Very simple. A Member clicks a link to a Post/Page that contains a Cancellation Form you\'ve generated. The Member clicks the Submit button to confirm the cancellation. s2Member is notified silently behind-the-scene, and will immediately cancel all future billing. s2Member will later terminate their account access, at the correct point in time. This works in conjunction with the s2Member Auto-EOT System. For further details, see: <code>s2Member -> Authorize.Net® Options -> EOT Behavior</code>.</em></p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/authnet-cancellation-form-shortcode.php")));
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-cancellation-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="Authorize.Net® Member Registration Access Links">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-reg-links-section">' . "\n";
     echo '<h3>Registration Access Link Generator ( for Customer Service )</h3>' . "\n";
     echo '<p>s2Member Pro Forms consolidate the Registration/Checkout process into a single-step solution, so it is unlikely that you will ever need this tool. That being said, if you DO need to deal with a Customer Service issue that requires a simple paid Registration Access Link to be created manually, you can use this tool for that. Alternatively, you can create their account yourself/manually by going to <code>s2Member -> Add A Member</code>. Either of these methods will work fine.</p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<p>Paid Membership Level#: <select id="ws-plugin--s2member-pro-reg-link-level">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<option value="' . $n . '">s2Member Level #' . $n . '</option>' . "\n";
     }
     echo '</select></p>' . "\n";
     echo '<p>Paid Subscr. ID: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-subscr-id" value="" size="50" /> <a href="#" onclick="alert(\'The Customer\\\'s Paid Subscr. ID ( aka: Authorize.Net® Subscription ID or Transaction ID ) must be unique. This value can be obtained from inside your Authorize.Net® account. Each paying Customer MUST be associated with a unique Paid Subscr. ID. If the Customer is NOT associated with a Paid Subscr. ID, you will need to generate a unique value for this field on your own. But keep in mind, s2Member will be unable to maintain future communication with the Authorize.Net® Silent Post and ARB services if this value does not reflect a real Paid Subscr. ID, one that exists in your Authorize.Net® transaction log.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>Custom String Value: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-custom" value="' . esc_attr($_SERVER["HTTP_HOST"]) . '" size="30" /> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_authnetRegLinkGenerate();" class="button-primary" /> <img id="ws-plugin--s2member-pro-reg-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma-delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-ccaps" size="40" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></p>' . "\n";
     echo '<p>Fixed Term Length ( for Buy Now transactions ): <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-fixed-term" value="" size="10" /> <a href="#" onclick="alert(\'If the Customer purchased Membership through a Buy Now transaction ( i.e. there is no Initial/Trial Period and no recurring charges for ongoing access ), you may configure a Fixed Term Length in this field. This way the Customer\\\'s Membership Access is revoked by s2Member at the appropriate time. This will be a numeric value, followed by a space, then a single letter.\\n\\nHere are some examples:\\n\\n1 D ( this means 1 Day )\\n1 W ( this means 1 Week )\\n1 M ( this means 1 Month )\\n1 Y ( this means 1 Year )\\n1 L ( this means 1 Lifetime )\'); return false;">[?]</a></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-reg-link" style="font-family:Consolas, monospace; display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="Authorize.Net® Specific Post/Page (Buy Now) Forms">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-forms-section">' . "\n";
     echo '<h3>Pro Form Generator For Specific Post/Page Forms</h3>' . "\n";
     echo '<p>s2Member now supports an additional layer of functionality ( very powerful ), which allows you to sell access to specific Posts/Pages that you\'ve created in WordPress®. Specific Post/Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Posts/Pages using "Buy Now" functionality. Your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be.</p>' . "\n";
     echo '<p>In other words, Customers will NOT need to login, just to receive access to the Specific Post/Page they purchased access to. s2Member will immediately redirect the Customer to the Specific Post/Page after checkout is completed successfully. An email is also sent to the Customer with a link ( see: <code>s2Member -> Authorize.Net® Options -> Specific Post/Page Email</code> ). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>' . "\n";
     echo '<p>Specific Post/Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Post/Page on your site; one that you created in WordPress®. A Specific Post/Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress® Post/Page that you\'ve created. To protect Specific Posts/Pages, please see: <code>s2Member -> Restriction Options -> Specific Post/Page Access</code>. Once you\'ve configured your Specific Post/Page Restrictions, those Posts/Pages will be available in the menus below.</p>' . "\n";
     echo '<p>Very simple. All you do is customize the form fields provided, for each Post/Page that you plan to sell. Then press (Generate Form Code). These special Authorize.Net® Forms are customized to work with s2Member seamlessly. You can even Package Additional Posts/Pages together into one transaction. <em>* Forms are NOT saved here. This is only a Form Generator. Once you\'ve generated your Form, copy/paste it into any Post/Page you like. You\'ll want to provide your visitors with a link to the Post/Page where this Form is located.</em></p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     /**/
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-additional-ids" multiple="multiple" style="height:100px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page ( they\\\'ll land on your Leading Post/Page after checkout ), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically ( e.g. only one Access Link is needed, and s2Member generates this automatically ). However, you will STILL need to design your Leading Post/Page ( which is what a Customer will actually land on ), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-sp-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-sp-hours.php"))) . '</select></p>' . "\n";
     echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
     echo '<p>Currency: <select id="ws-plugin--s2member-pro-sp-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_authnetSpFormGenerate();" class="button-primary" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/authnet-sp-checkout-form-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="Authorize.Net® Specific Post/Page Access Links">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-links-section">' . "\n";
     echo '<h3>Specific Post/Page Link Generator ( for Customer Service )</h3>' . "\n";
     echo '<p>s2Member automatically generates Specific Post/Page Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Specific Post/Page Link to be created manually, you can use this tool for that.</p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     /**/
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-additional-ids" multiple="multiple" style="height:100px; min-width:450px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page ( they\\\'ll land on your Leading Post/Page after checkout ), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically ( e.g. only one Access Link is needed, and s2Member generates this automatically ). However, you will STILL need to design your Leading Post/Page ( which is what a Customer will actually land on ), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/authnet-sp-hours.php"))) . '</select> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_authnetSpLinkGenerate();" class="button-primary" /> <img id="ws-plugin--s2member-pro-sp-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-sp-link" style="font-family:Consolas, monospace; display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
         echo '<div class="ws-menu-page-group" title="Custom Return URLs Upon Success">' . "\n";
         /**/
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-forms-success-section">' . "\n";
         echo '<h3>Custom Return URLs Upon Success ( optional, for developers )</h3>' . "\n";
         echo '<p>s2Member Pro opens the door for Custom Return URLs upon success. You can add a special attribute to any Form Shortcode ( <code>success="/my-thank-you-page/"</code> ). This makes it possible to integrate Authorize.Net® Pro Forms in very creative ways; and even receive/verify Replacement Code variables, as needed. For example, ( <code>success="/my-thank-you-page/?subscr_id=%%subscr_id%%"</code> ).</p>' . "\n";
         echo '<p><em>A Custom Return URL is 100% optional. In fact, if you only need to obtain details for the purpose of tracking sales, you should just use the simpler API Tracking methods provided by s2Member, under: <code>s2Member -> API / Tracking</code>. In other words, if you don\'t use the <code>success=""</code> attribute in your Shortcode, s2Member will handle things gracefully, all on its own. So using a Custom Return URL is only necessary when you need advanced customization for one reason or another.</em></p>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<h3>Free Registration Forms ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-free-registration\').toggle(); return false;" class="ws-dotted-link">open/close</a> )</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-free-registration" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%role%%</code> = The Role ID <code>( subscriber, s2member_level[0-9]+, administrator, editor, author, contributor )</code>.</li>' . "\n";
         echo '<li><code>%%level%%</code> = The Level number <code>( 0, 1, 2, 3, 4 )</code>. ( <em>deprecated, no longer recommended; use <code>%%role%%</code></em> )</li>' . "\n";
         echo '<li><code>%%ccaps%%</code> = Custom Capabilities. Ex: <code>music,videos,free_gift</code> ( <em>in comma-delimited format</em> ).</li>' . "\n";
         echo '<li><code>%%auto_eot_time%%</code> = Auto-EOT Time ( if applicable ). Ex: <code>1299925670</code> ( <em>unix timestamp</em> ).</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name ( First &amp; Last ) of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username the Member selected during registration.</li>' . "\n";
         echo '<li><code>%%user_pass%%</code> = The Password selected or generated during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The User\'s IP Address, via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID generated during registration.</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_decrypt%28%29" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         /**/
         echo '<strong>Custom Registration/Profile Fields are also supported here:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         /**/
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>( The campaign ( i.e. christmas-promo ) could be referenced using <code>%%cv1%%</code> )</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<h3>Membership Sales / Signups &amp; Modifications ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-sales\').toggle(); return false;" class="ws-dotted-link">open/close</a> )</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-sales" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%subscr_id%%</code> = The Authorize.Net® Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase. Authorize.Net® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a 100% Free Trial, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. Even if that amount is 0.\\n\\nIf a Customer signs up, under the terms of a 100% Free Trial Period, this will be 0. So be careful using %%initial%% when you offer a 100% Free Trial Period, because a $0.00 sale amount could cause havoc with affiliate programs.\\n\\nIf you\\\'re offering a 100% Free Trial Period, and you need to track sales through affiliate programs, you can either hard-code an amount; or use `s2Member -> API Notifications -> Payment Notifications` instead.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. This value is <code>always > 0</code>, no matter what. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an Initial Period expires. The %%regular%% rate is always > 0. If you did NOT offer an Initial Period at a different price, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a recurring basis, or <code>0</code> if non-recurring. [ <a href="#" onclick="alert(\'If Recurring Payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the Regular Recurring Rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) for the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
         echo '<li><code>%%initial_term%%</code> = This is the term length of the Initial Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\n%%initial_term%% = 1 W ( this means 1 Week )\\n%%initial_term%% = 1 M ( this means 1 Month )\\n%%initial_term%% = 1 Y ( this means 1 Year )\\n\\nThe Initial Period never recurs, so this only lasts for the term length specified, then it is over.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%regular_term%%</code> = This is the term length of the Regular Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\n%%regular_term%% = 1 W ( this means 1 Week )\\n%%regular_term%% = 1 M ( this means 1 Month )\\n%%regular_term%% = 1 Y ( this means 1 Year )\\n%%regular_term%% = 1 L ( this means 1 Lifetime )\\n\\nThe Regular Term is usually recurring. So the Regular Term value represents the period ( or duration ) of each recurring period. If %%recurring%% = 0, then the Regular Term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their Membership privileges are going to last after the %%initial_term%% has expired, if there was an Initial Term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%modification%%</code> = <code>1</code> if/when a Billing Modification has just taken place; otherwise <code>0</code> indicates a new Customer.</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The Customer\'s original IP Address, during checkout/registration via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_decrypt%28%29" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         /**/
         echo '<strong>Custom Registration/Profile Fields are also supported here:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         /**/
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>( The campaign ( i.e. christmas-promo ) could be referenced using <code>%%cv1%%</code> )</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<h3>Independent Custom Capability Sales ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-ccaps\').toggle(); return false;" class="ws-dotted-link">open/close</a> )</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-ccaps" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%txn_id%%</code> = The Payment Transaction ID, which is always unique for each payment received.</li>' . "\n";
         echo '<li><code>%%amount%%</code> = The Amount of the payment. Most affiliate programs calculate commissions from this.</li>' . "\n";
         echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>*level:custom_capabilities:fixed term</em></code> ) that the payment is for. [ <a href="#" onclick="alert(\'With Independent Custom Capabilities, the `level` portion of this string will be an asterisk ( `*` ), since the Membership Level is irrelevant, and remains `as it was`.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The Customer\'s original IP Address, during checkout/registration via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_decrypt%28%29" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         /**/
         echo '<strong>Custom Registration/Profile Fields are also supported here:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         /**/
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>( The campaign ( i.e. christmas-promo ) could be referenced using <code>%%cv1%%</code> )</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<h3>Specific Post/Page Transactions ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-sp-sales\').toggle(); return false;" class="ws-dotted-link">open/close</a> )</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-sp-sales" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%sp_access_url%%</code> = The full URL ( generated by s2Member ) where the Customer can gain access.</li>' . "\n";
         echo '<li><code>%%sp_access_exp%%</code> = Human readable expiration for <code>%%sp_access_url%%</code>. Ex: <em>( link expires in <code>%%sp_access_exp%%</code> )</em>.</li>' . "\n";
         echo '<li><code>%%txn_id%%</code> = The Authorize.Net® Transaction ID. Authorize.Net® assigns a unique identifier for every purchase.</li>' . "\n";
         echo '<li><code>%%amount%%</code> = The full Amount of the sale. Most affiliate programs calculate commissions from this.</li>' . "\n";
         echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The Customer\'s IP Address, detected during checkout via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%item_number%%</code> = The Item Number. Ex: <code><em>sp:13,24,36:72</em></code> ( translates to: <code><em>sp:comma-delimited IDs:expiration hours</em></code> ).</li>' . "\n";
         echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link to the Specific Post/Page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link to the Specific Post/Page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_decrypt%28%29" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         /**/
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>( The campaign ( i.e. christmas-promo ) could be referenced using <code>%%cv1%%</code> )</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<h3>Cancellations &amp; Billing Updates ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-cancellations-updates\').toggle(); return false;" class="ws-dotted-link">open/close</a> )</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-cancellations-updates" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;">' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link back to their account page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link back to their account page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_decrypt%28%29" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<h3>Verify The Integrity Of Replacement Codes ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-verification\').toggle(); return false;" class="ws-dotted-link">open/close</a> )</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-verification" style="display:none;">' . "\n";
         echo '<p>If you know a little PHP, you can verify the integrity of the Replacement Codes returned by s2Member. This is important, because in this particular situation, Replacement Codes are passed publicly in the query string of your Custom Return URL. In other words, a Customer could manually change one of the values; like the dollar amounts. For this reason, you should always verify the integrity of the details being returned to any processing routines that receive this information. In the PHP code for your Custom Return URL, you can use this s2Member API Function: <code>s2member_pro_authnet_s2p_v_query_ok()</code>.</p>' . "\n";
         echo '<p>Here are some examples:</p>' . "\n";
         echo '<p>1. <strong>Shortcode attribute:</strong> <code>success="/thank-you/?subscr_id=%%subscr_%%&amp;initial=%%initial%%&amp;regular=%%regular%%"</code></p>' . "\n";
         echo '<p>2. <strong>s2Member returns Customer to:</strong> <code>/thank-you/?subscr_id=123&amp;initial=0.00&amp;regular=24.95&amp;s2p-v=234098234-23409sdfs234sd234209sdf</code></p>' . "\n";
         echo '<p>3. <strong>Now, in your Custom Return Page, you will need to do this before trusting anything:</strong></p>' . "\n";
         echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/authnet-s2p-v-query-ok-1.x-php")) . '</p>' . "\n";
         echo '<p>s2Member will only verify a query string for up to 10 seconds. After 10 seconds, <code>s2member_pro_authnet_s2p_v_query_ok()</code> will always return <code>false</code>, even if the integrity of the query string is valid. This prevents a Customer from bookmarking your Return URL; thereby causing duplicate commissions; in case you\'re using it for tracking purposes.</p>' . "\n";
         echo '<p>Again, if you only need to obtain details for the purpose of tracking sales, you should just use the simpler API Tracking methods provided by s2Member, under: <code>s2Member -> API / Tracking</code>. The API Tracking methods are specifically designed for tracking sales, exactly ONE time for each Customer.</p>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<p><em>If it is your intention to allow Customers to bookmark your Custom Return URL, you can still do that. Just be aware that <code>s2member_pro_authnet_s2p_v_query_ok()</code> will return <code>false</code> after the first 10 seconds. If you want to verify after 10 seconds, you can pass a second argument to the function, like this:</em></p>' . "\n";
         echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/authnet-s2p-v-query-ok-2.x-php")) . '</p>' . "\n";
         /**/
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         /**/
         echo '<h3>Could a Customer change the timestamp in the URL?</h3>' . "\n";
         echo '<p>Based on the structure of the URL, it would appear possible; however, it\'s NOT. s2Member uses an advanced checksum.</p>' . "\n";
         echo '<h3>Can I get rid of the <code>s2p-v</code> variable?</h3>' . "\n";
         echo '<p>No, this variable is always passed to your Custom Return URL, it\'s for important verification purposes.</p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '</div>' . "\n";
     }
     /**/
     echo '<div class="ws-menu-page-group" title="Shortcode Attributes ( Explained )">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-shortcode-attrs-section">' . "\n";
     echo '<h3>Shortcode Attributes ( Explained In Full Detail )</h3>' . "\n";
     echo '<p>When you generate a Form, s2Member will make a <a href="http://codex.wordpress.org/Shortcode_API#Overview" target="_blank" rel="external">Shortcode</a> available to you. Like most Shortcodes for WordPress®, s2Member reads Attributes in your Shortcode. These Attributes will be pre-configured by one of s2Member\'s Form Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
     /**/
     echo '<table class="form-table" style="margin-top:0;">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr style="padding-top:0;">' . "\n";
     /**/
     echo '<td style="padding-top:0;">' . "\n";
     echo '<ul>' . "\n";
     echo '<li><code>accept="visa,mastercard,amex,discover"</code> Accepted Billing Methods. A comma-delimited list of Billing Methods you want to accept. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>accept_coupons="1"</code> Accept Coupons? Possible values: <code>0</code> = do NOT accept Coupons on this particular Form; <code>1</code> = DO accept Coupon Codes on this particular Form.</li>' . "\n";
     echo '<li><code>cancel="0"</code> Cancellation Form. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Cancellation Form, <code>1</code> = this IS a Cancellation Form.</li>' . "\n";
     echo '<li><code>captcha="clean"</code> When you set this Attribute, visitors must prove they\'re human by typing a <a href="http://en.wikipedia.org/wiki/CAPTCHA" target="_blank" rel="external">captcha/security code</a>. Possible values: <code>0</code> = do NOT require a captcha code on this Form; <code>clean</code> = DO require a captcha code on this Form; using the <code>clean</code> theme style. Possible <a href="http://www.s2member.com/google-recaptcha-styles" target="_blank" rel="external">theme styles</a> include: <code>red</code>, <code>white</code>, <code>clean</code>, and <code>blackglass</code>. This service is powered by Google\'s reCaptcha system.</li>' . "\n";
     echo '<li><code>cc="USD"</code> 3 character Currency Code. Authorize.Net® processes all transactions in USD. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>ccaps="music,videos"</code> A comma-delimited list of Custom Capabilities. Only valid w/ Membership Level Access and/or Independent Custom Capabilities.</li>' . "\n" : '';
     echo '<li><code>coupon="SAVE-10"</code> Default/pre-filled Coupon Code. This is optional, and the Coupon Code ( if supplied ) must exist in your Coupon Code configuration.</li>' . "\n";
     echo '<li><code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '"</code> must start with your domain. Additional values can be piped in ( ex: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3|etc"</code> ). Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>default_country_code="US"</code> If you set this 2-character value, it will pre-configure the default Country that is selected in the drop-down menu for Checkout and Billing Update Forms. This MUST be an uppercase country code, following the <a href="http://www.iso.org/iso/english_country_names_and_code_elements" target="_blank" rel="external">ISO-3166-1 specification</a>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>desc="Gold Membership @ $29/mo"</code> A brief purchase Description. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>exp="72"</code> Access Expires ( in hours ). Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>ids="14"</code> A Post/Page ID#, or a comma-delimited list of IDs. Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>level="1"</code> Membership Level [1-4] <em>( or, up to the number of configured Levels )</em>. Only valid for Forms providing Membership Level Access, which includes Free Registration Forms too. Free Registration Forms allow a value of <code>level="0"</code> whenever <code>register="1"</code> for Free Registration. In addition, Free Registration Forms will also allow visitors to register for free, even at higher Levels if you wish. Free Registration Forms will accept any value [0-4] <em>( or, up to the number of configured Levels )</em>.' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' With Independent Custom Capabilities this MUST be set to <code>level="*"</code>, and <code>ccaps=""</code> must NOT be empty <em>( i.e. <code>level="*" ccaps="music,videos"</code> )</em>.') . '</li>' . "\n";
     echo '<li><code>modify="0"</code> Modification directive. Only valid w/ Membership Level Access. Possible values: <code>0</code> = allows Customers to modify their current Subscription or sign up for a new one, <code>1</code> = allows Customers to only modify their current Subscription. When <code>modify="1"</code>, s2Member will force a Customer to be logged-in before they can fill out the Form ( very handy ).</li>' . "\n";
     echo '<li><code>register="0"</code> Free Registration Form. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Free Registration Form, <code>1</code> = this IS a Free Registration Form.</li>' . "\n";
     echo '<li><code>ra="0.01"</code> Regular, Buy Now, and/or Recurring Amount. Must be &gt;= <code>0.01</code>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>rp="1"</code> Regular Period. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Must be &gt;= <code>1</code> ( ex: <code>1</code> Week, <code>3</code> Weeks, <code>2</code> Months, <code>1</code> Year ).</li>' . "\n";
     echo '<li><code>rt="M"</code> Regular Term. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years, <code>L</code> = Lifetime.</li>' . "\n";
     echo '<li><code>rr="1"</code> Recurring directive. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>0</code> = non-recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>1</code> = recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>BN</code> = non-recurring "Buy Now" functionality, no Trial Period possible.</li>' . "\n";
     echo '<li><code>sp="0"</code> Specific Post/Page Form. Possible values: <code>0</code> = this is NOT a Specific Post/Page Access Form, <code>1</code> = this IS a Specific Post/Page Access Form.</li>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>success=""</code> 100% optional. This can be used to create a Custom Return URL on success. Please see the sub-section above titled: <em>Custom Return URLs on Success</em>.</li>' . "\n" : '';
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>template=""</code> 100% optional. This can be a custom template file that exists inside your WordPress® theme directory. For example: <code>template="checkout.php"</code>.</li>' . "\n" : '';
     echo '<li><code>ta="0.00"</code> Trial Amount. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
     echo '<li><code>tp="0"</code> Trial Period. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
     echo '<li><code>tt="D"</code> Trial Term. Only valid w/ Membership Level Access. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years.</li>' . "\n";
     echo '<li><code>update="0"</code> Billing Update Form. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Billing Update Form, <code>1</code> = this IS a Billing Update Form.</li>' . "\n";
     echo '</ul>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '</td>' . "\n";
     /**/
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     /**/
     echo '</div>' . "\n";
 }
Пример #13
0
 /**
  * Widget display.
  *
  * @package s2Member\Widgets
  * @since 140628
  *
  * @param array $args Optional. An array of basic settings.
  * @param array $instance Optional. An array of options for this instance.
  */
 public static function ___static_widget___($args = array(), $instance = array())
 {
     $options = self::___static_configure_options_and_their_defaults___((array) $instance);
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action('ws_plugin__s2member_pro_login_widget_before_display', get_defined_vars());
     unset($__refs, $__v);
     // Housekeeping.
     echo $args['before_widget'];
     // OK, here we go into this widget.
     if (is_user_logged_in() && strlen($options['profile_title']) || !is_user_logged_in() && strlen($options['title'])) {
         echo $args['before_title'] . apply_filters('widget_title', $options[is_user_logged_in() ? 'profile_title' : 'title']) . $args['after_title'];
     }
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action('ws_plugin__s2member_pro_login_widget_during_display_before', get_defined_vars());
     unset($__refs, $__v);
     // Housekeeping.
     if (!is_user_logged_in()) {
         $links = c_ws_plugin__s2member_cache::cached_page_links();
         $ops_page = $GLOBALS['WS_PLUGIN__']['s2member']['o']['membership_options_page'];
         if ($ops_page && is_page($ops_page) && !empty($_GET['_s2member_seeking']['_uri'])) {
             $seeking = trim(base64_decode(trim(stripslashes((string) $_GET['_s2member_seeking']['_uri']))));
         }
         $options['login_redirect'] = $options['login_redirect'] === '%%previous%%' && empty($seeking) && $ops_page && is_page($ops_page) ? '' : $options['login_redirect'];
         $options['login_redirect'] = $options['login_redirect'] === '%%previous%%' && empty($seeking) && is_front_page() ? '' : $options['login_redirect'];
         $options['login_redirect'] = $options['login_redirect'] === '%%previous%%' && !empty($seeking) && $seeking === '/' ? '' : $options['login_redirect'];
         $redirect_to = $options['login_redirect'];
         $redirect_to = preg_replace('/%%previous%%/i', !empty($seeking) ? $seeking : $_SERVER['REQUEST_URI'], $redirect_to);
         $redirect_to = preg_replace('/%%home%%/i', home_url('/'), $redirect_to);
         echo '<div class="ws-plugin--s2member-pro-login-widget">' . "\n";
         echo '<form method="post" action="' . esc_attr(site_url('wp-login.php', 'login_post')) . '" class="ws-plugin--s2member-pro-login-widget-form">' . "\n";
         echo '<div class="ws-plugin--s2member-pro-login-widget-username">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-login-widget-username">' . _x('Username', 's2member-front', 's2member') . ':</label><br />' . "\n";
         echo '<input type="text" name="log" id="ws-plugin--s2member-pro-login-widget-username" class="form-control" title="Username" />' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-plugin--s2member-pro-login-widget-password">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-login-widget-password">' . _x('Password', 's2member-front', 's2member') . ':</label><br />' . "\n";
         echo '<input type="password" name="pwd" id="ws-plugin--s2member-pro-login-widget-password" class="form-control" title="Password" />' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-plugin--s2member-pro-login-widget-lost-password">' . "\n";
         $reg_cookies_ok_url = is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site() ? c_ws_plugin__s2member_utils_urls::wp_signup_url() : c_ws_plugin__s2member_utils_urls::wp_register_url();
         echo $options['signup_url'] ? '<a href="' . esc_attr($options['signup_url'] !== '%%automatic%%' ? $options['signup_url'] : (c_ws_plugin__s2member_register_access::reg_cookies_ok() ? $reg_cookies_ok_url : $links['membership_options_page'])) . '" tabindex="-1">' . _x('signup now', 's2member-front', 's2member') . '</a> | ' : '';
         echo '<a href="' . esc_attr(wp_lostpassword_url()) . '" tabindex="-1">' . _x('forgot password?', 's2member-front', 's2member') . '</a>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-plugin--s2member-pro-login-widget-remember-me">' . "\n";
         echo '<label><input type="checkbox" name="rememberme" value="forever" />' . _x('Remember Me', 's2member-front', 's2member') . '</label>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-plugin--s2member-pro-login-widget-submit">' . "\n";
         if ($redirect_to) {
             echo '<input type="hidden" name="redirect_to" value="' . esc_attr($redirect_to) . '" />' . "\n" . (empty($seeking) ? '<input type="hidden" name="redirect_to_automatic" value="1" />' . "\n" : '');
         }
         echo '<input type="submit" class="btn btn-primary" value="' . esc_attr(_x('Log Me In', 's2member-front', 's2member')) . '" />' . "\n";
         echo '</div>' . "\n";
         echo '</form>' . "\n";
         echo '<div class="ws-plugin--s2member-pro-login-widget-code">' . "\n";
         if (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) {
             echo do_shortcode(trim($options['logged_out_code']));
         } else {
             // Otherwise, it's OK to execute PHP code.
             echo do_shortcode(c_ws_plugin__s2member_utilities::evl(trim($options['logged_out_code'])));
         }
         echo '</div>' . "\n";
         echo '<div style="clear:both;"></div>' . "\n";
         echo '</div>' . "\n";
     } else {
         if (is_user_logged_in() && is_object($user = wp_get_current_user()) && !empty($user->ID) && ($user_id = $user->ID)) {
             $links = c_ws_plugin__s2member_cache::cached_page_links();
             $ops_page = $GLOBALS['WS_PLUGIN__']['s2member']['o']['membership_options_page'];
             $welcome_page = $GLOBALS['WS_PLUGIN__']['s2member']['o']['login_welcome_page'];
             $options['logout_redirect'] = $options['logout_redirect'] === '%%previous%%' && $ops_page && is_page($ops_page) ? '' : $options['logout_redirect'];
             $options['logout_redirect'] = $options['logout_redirect'] === '%%previous%%' && $welcome_page && is_page($welcome_page) ? '' : $options['logout_redirect'];
             $redirect_to = preg_replace('/%%previous%%/i', $_SERVER['REQUEST_URI'], $redirect_to = $options['logout_redirect']);
             $redirect_to = preg_replace('/%%home%%/i', home_url('/'), $redirect_to);
             echo '<div id="ws-plugin--s2member-pro-login-widget" class="ws-plugin--s2member-pro-login-widget">' . "\n";
             echo '<div class="ws-plugin--s2member-pro-login-widget-profile-summary">' . "\n";
             echo $options['display_gravatar'] ? ($options['link_gravatar'] ? '<a href="http://www.gravatar.com/" target="_blank">' : '') . get_avatar($user_id, 48) . ($options['link_gravatar'] ? '</a>' : '') . "\n" : '';
             echo $options['display_name'] ? '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-name">' . esc_html($user->display_name) . '</div>' . "\n" : '';
             echo '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-code">' . "\n";
             if (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) {
                 echo do_shortcode(trim($options['logged_in_code']));
             } else {
                 // Otherwise, it's OK to execute PHP code.
                 echo do_shortcode(c_ws_plugin__s2member_utilities::evl(trim($options['logged_in_code'])));
             }
             echo '</div>' . "\n";
             echo $options['my_account_url'] ? '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-my-account"><a href="' . esc_attr($options['my_account_url'] !== '%%automatic%%' ? c_ws_plugin__s2member_login_redirects::fill_login_redirect_rc_vars($options['my_account_url']) : (($login_redirection_url = c_ws_plugin__s2member_login_redirects::login_redirection_url($user)) ? $login_redirection_url : $links['login_welcome_page'])) . '">' . _x('My Account', 's2member-front', 's2member') . '</a></div>' . "\n" : '';
             echo $options['my_profile_url'] ? '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-edit-profile"><a href="' . ($options['my_profile_url'] !== '%%automatic%%' ? esc_attr(c_ws_plugin__s2member_login_redirects::fill_login_redirect_rc_vars($options['my_profile_url'])) : esc_attr(home_url('/?s2member_profile=1')) . '" onclick="if(!window.open(\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr(home_url('/?s2member_profile=1'))) . '\',\'_profile\', \'width=600,height=400,left=\'+((screen.width/2)-(600/2))+\',screenX=\'+((screen.width/2)-(600/2))+\',top=\'+((screen.height/2)-(400/2))+\',screenY=\'+((screen.height/2)-(400/2))+\',location=0,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1\')) alert(\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x('Please disable popup blockers and try again!', 's2member-front', 's2member')) . '\'); return false;') . '">' . _x('Edit My Profile', 's2member-front', 's2member') . '</a></div>' . "\n" : '';
             echo '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-logout"><a href="' . esc_attr(wp_logout_url($redirect_to)) . '">' . _x('Logout', 's2member-front', 's2member') . '</a></div>' . "\n";
             echo '<div style="clear:both;"></div>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
         }
     }
     foreach (array_keys(get_defined_vars()) as $__v) {
         $__refs[$__v] =& ${$__v};
     }
     do_action('ws_plugin__s2member_pro_login_widget_during_display_after', get_defined_vars());
     unset($__refs, $__v);
     // Housekeeping.
     echo $args['after_widget'];
     do_action('ws_plugin__s2member_pro_login_widget_after_display', get_defined_vars());
 }
 /**
  * Outputs JS for theme integration.
  *
  * Be sure s2Member's API Constants are already defined before firing this.
  *
  * @package s2Member\CSS_JS
  * @since 3.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after loading JS w/Globals.
  */
 public static function js_w_globals()
 {
     do_action("ws_plugin__s2member_before_js_w_globals", get_defined_vars());
     /**/
     if (!empty($_GET["ws_plugin__s2member_js_w_globals"])) {
         status_header(200);
         /* 200 OK status header. */
         /**/
         header("Content-Type: text/javascript; charset=utf-8");
         header("Expires: " . gmdate("D, d M Y H:i:s", strtotime("+1 week")) . " GMT");
         header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
         header("Cache-Control: max-age=604800");
         header("Pragma: public");
         /**/
         eval('while (@ob_end_clean ());');
         /**/
         include_once dirname(dirname(__FILE__)) . "/jquery/jquery.sprintf/jquery.sprintf-min.js";
         /**/
         echo "\n";
         /* Add a line break before writing JavaScript Globals to file. */
         /**/
         echo "var S2MEMBER_VERSION = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_VERSION) . "',";
         /**/
         echo "S2MEMBER_CURRENT_USER_LOGIN_COUNTER = " . S2MEMBER_CURRENT_USER_LOGIN_COUNTER . ",";
         /**/
         echo "S2MEMBER_CURRENT_USER_IS_LOGGED_IN = " . (S2MEMBER_CURRENT_USER_IS_LOGGED_IN ? "true" : "false") . ",";
         echo "S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER = " . (S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER ? "true" : "false") . ",";
         /**/
         echo "S2MEMBER_CURRENT_USER_ACCESS_LEVEL = " . S2MEMBER_CURRENT_USER_ACCESS_LEVEL . ",";
         echo "S2MEMBER_CURRENT_USER_ACCESS_LABEL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_ACCESS_LABEL) . "',";
         /**/
         echo "S2MEMBER_CURRENT_USER_SUBSCR_ID = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_SUBSCR_ID) . "',";
         echo "S2MEMBER_CURRENT_USER_SUBSCR_OR_WP_ID = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_SUBSCR_OR_WP_ID) . "',";
         echo "S2MEMBER_CURRENT_USER_SUBSCR_GATEWAY = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_SUBSCR_GATEWAY) . "',";
         echo "S2MEMBER_CURRENT_USER_CUSTOM = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_CUSTOM) . "',";
         /**/
         echo "S2MEMBER_CURRENT_USER_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_REGISTRATION_TIME . ",";
         echo "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME . ",";
         /**/
         echo "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS . ",";
         echo "S2MEMBER_CURRENT_USER_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_REGISTRATION_DAYS . ",";
         /**/
         echo "S2MEMBER_CURRENT_USER_DISPLAY_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_DISPLAY_NAME) . "',";
         echo "S2MEMBER_CURRENT_USER_FIRST_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_FIRST_NAME) . "',";
         echo "S2MEMBER_CURRENT_USER_LAST_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_LAST_NAME) . "',";
         /**/
         echo "S2MEMBER_CURRENT_USER_LOGIN = '******',";
         echo "S2MEMBER_CURRENT_USER_EMAIL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_EMAIL) . "',";
         echo "S2MEMBER_CURRENT_USER_IP = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_IP) . "',";
         echo "S2MEMBER_CURRENT_USER_REGISTRATION_IP = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_REGISTRATION_IP) . "',";
         /**/
         echo "S2MEMBER_CURRENT_USER_ID = " . S2MEMBER_CURRENT_USER_ID . ",";
         echo "S2MEMBER_CURRENT_USER_FIELDS = " . S2MEMBER_CURRENT_USER_FIELDS . ",";
         /**/
         echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED = " . S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED . ",";
         echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED = " . (S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED ? "true" : "false") . ",";
         echo "S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY = " . S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY . ",";
         echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS = " . S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS . ",";
         /**/
         echo "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID = " . S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID . ",";
         echo "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID = " . S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID . ",";
         echo "S2MEMBER_LOGIN_WELCOME_PAGE_ID = " . S2MEMBER_LOGIN_WELCOME_PAGE_ID . ",";
         /**/
         echo "S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL) . "',";
         echo "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL) . "',";
         echo "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL) . "',";
         echo "S2MEMBER_LOGIN_WELCOME_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_LOGIN_WELCOME_PAGE_URL) . "',";
         echo "S2MEMBER_LOGOUT_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_LOGOUT_PAGE_URL) . "',";
         echo "S2MEMBER_LOGIN_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_LOGIN_PAGE_URL) . "',";
         /**/
         for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             if (defined($S2MEMBER_LEVELn_LABEL = "S2MEMBER_LEVEL" . $n . "_LABEL")) {
                 echo $S2MEMBER_LEVELn_LABEL . " = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(constant($S2MEMBER_LEVELn_LABEL)) . "',";
             }
         }
         /**/
         for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             if (defined($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED = "S2MEMBER_LEVEL" . $n . "_FILE_DOWNLOADS_ALLOWED")) {
                 echo $S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED . " = " . constant($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED) . ",";
             }
         }
         /**/
         for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             if (defined($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS = "S2MEMBER_LEVEL" . $n . "_FILE_DOWNLOADS_ALLOWED_DAYS")) {
                 echo $S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS . " = " . constant($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS) . ",";
             }
         }
         /**/
         echo "S2MEMBER_FILE_DOWNLOAD_INLINE_EXTENSIONS = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_FILE_DOWNLOAD_INLINE_EXTENSIONS) . "',";
         /**/
         echo "S2MEMBER_REG_EMAIL_FROM_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_REG_EMAIL_FROM_NAME) . "',";
         echo "S2MEMBER_REG_EMAIL_FROM_EMAIL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_REG_EMAIL_FROM_EMAIL) . "',";
         /**/
         echo "S2MEMBER_PAYPAL_NOTIFY_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_NOTIFY_URL) . "',";
         echo "S2MEMBER_PAYPAL_RETURN_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_RETURN_URL) . "',";
         /**/
         echo "S2MEMBER_PAYPAL_BUSINESS = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_BUSINESS) . "',";
         echo "S2MEMBER_PAYPAL_ENDPOINT = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_ENDPOINT) . "',";
         echo "S2MEMBER_PAYPAL_API_ENDPOINT = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_API_ENDPOINT) . "',";
         /**/
         echo "S2MEMBER_VALUE_FOR_PP_INV = Math.round (new Date ().getTime ()) + '~" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_IP) . "',";
         echo "S2MEMBER_VALUE_FOR_PP_INV_GEN = s2member_value_for_pp_inv_gen = function(){ var invoice = '', formatSeed = function(seed, reqWidth) { seed = parseInt(seed, 10).toString (16); if (reqWidth < seed.length) return seed.slice (seed.length - reqWidth); else if (reqWidth > seed.length) return Array(1 + (reqWidth - seed.length)).join ('0') + seed; return seed; }; if (typeof S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED === 'undefined') S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED = Math.floor (Math.random () * 0x75bcd15); S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED++; invoice = formatSeed(parseInt(new Date ().getTime () / 1000, 10), 8); invoice += formatSeed(S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED, 5); invoice += '~' + S2MEMBER_CURRENT_USER_IP; return invoice; },";
         /**/
         echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0) . "',";
         echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0) . "',";
         /**/
         echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON1 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON1) . "',";
         echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS1 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS1) . "';";
         /**/
         $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
         $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
         /**/
         echo "\n";
         /* Add a line break before inclusion. */
         /**/
         include_once dirname(dirname(__FILE__)) . "/s2member-min.js";
         /**/
         do_action("ws_plugin__s2member_during_js_w_globals", get_defined_vars());
         /**/
         exit;
         /* Clean exit. */
     }
     /**/
     do_action("ws_plugin__s2member_after_js_w_globals", get_defined_vars());
 }
 /**
  * Handles ClickBank® Return URL processing.
  *
  * @package s2Member\ClickBank
  * @since 1.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after redirection.
  */
 public static function clickbank_return()
 {
     global $current_site, $current_blog;
     /**/
     if (!empty($_GET["s2member_pro_clickbank_return"]) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_clickbank_username"]) {
         if (is_array($clickbank = c_ws_plugin__s2member_pro_clickbank_utilities::clickbank_postvars()) && ($_clickbank = $clickbank)) {
             $clickbank["s2member_log"][] = "Return-Data received on: " . date("D M j, Y g:i:s a T");
             $clickbank["s2member_log"][] = "s2Member POST vars verified with ClickBank®.";
             /**/
             $clickbank["s2member_log"][] = "Sleeping for 5 seconds. Giving ClickBank® a chance to finalize processing.";
             sleep(5);
             $clickbank["s2member_log"][] = "Awake. It's " . date("D M j, Y g:i:s a T") . ". Processing will continue.";
             /**/
             if (is_array($order = json_decode(c_ws_plugin__s2member_utils_urls::remote("https://api.clickbank.com/rest/1.2/orders/" . $clickbank["cbreceipt"], false, array_merge(c_ws_plugin__s2member_pro_clickbank_utilities::clickbank_api_headers(), array("timeout" => 20))), true)) && ($order = $order["orderData"])) {
                 $clickbank["s2member_log"][] = "Order API variables have been obtained from ClickBank®.";
                 /**/
                 $s2vars = c_ws_plugin__s2member_pro_clickbank_utilities::clickbank_parse_s2vars(http_build_query($clickbank), $order["txnType"]);
                 /**/
                 if (isset($s2vars["s2_p1"], $s2vars["s2_p3"]) && $s2vars["s2_p1"] === "0 D") {
                     $s2vars["s2_p1"] = $s2vars["s2_p3"];
                 }
                 /**/
                 $clickbank["s2vars"] = $s2vars;
                 /**/
                 if (strcasecmp($order["firstName"] . " " . $order["lastName"], $order["customerDisplayName"]) !== 0 && preg_match("/([^ ]+)( +)([^ ]+)/", $order["customerDisplayName"])) {
                     list($order["firstName"], $order["lastName"]) = preg_split("/ +/", $order["customerDisplayName"], 2);
                 }
                 /**/
                 if (preg_match("/^(TEST_)?SALE\$/i", $order["txnType"]) && !isset($s2vars["s2_p1"], $s2vars["s2_p3"])) {
                     $clickbank["s2member_log"][] = "ClickBank® transaction identified as ( `SALE/STANDARD` ).";
                     $clickbank["s2member_log"][] = "Return-Data reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `web_accept` ).";
                     $clickbank["s2member_log"][] = "Please check PayPal® RTN logs for further processing details.";
                     /**/
                     $rtn = array();
                     /* Reset. */
                     /**/
                     $rtn["txn_type"] = "web_accept";
                     /**/
                     $rtn["txn_id"] = $order["receipt"];
                     $rtn["custom"] = $s2vars["s2_custom"];
                     /**/
                     $rtn["mc_gross"] = number_format($order["amount"], 2, ".", "");
                     $rtn["mc_currency"] = strtoupper($order["currency"]);
                     $rtn["tax"] = "0.00";
                     /* No tax. */
                     /**/
                     $rtn["payer_email"] = $order["email"];
                     $rtn["first_name"] = ucwords(strtolower($order["firstName"]));
                     $rtn["last_name"] = ucwords(strtolower($order["lastName"]));
                     /**/
                     $rtn["option_name1"] = $s2vars["s2_referencing"] ? "Referencing Customer ID" : "Originating Domain";
                     $rtn["option_selection1"] = $s2vars["s2_referencing"] ? $s2vars["s2_referencing"] : $_SERVER["HTTP_HOST"];
                     /**/
                     $rtn["option_name2"] = "Customer IP Address";
                     $rtn["option_selection2"] = $s2vars["s2_customer_ip"];
                     /**/
                     $rtn["item_number"] = $s2vars["s2_invoice"];
                     $rtn["item_name"] = $s2vars["s2_desc"];
                     /**/
                     $rtn_q = "&s2member_paypal_proxy=clickbank&s2member_paypal_proxy_use=standard-emails";
                     if (!empty($_GET["s2member_pro_clickbank_return_success"])) {
                         $rtn_q .= "&s2member_paypal_return_success=" . rawurlencode(trim(stripslashes($_GET["s2member_pro_clickbank_return_success"])));
                     }
                     /**/
                     $rtn_r = add_query_arg(urlencode_deep($rtn), site_url("/?s2member_pro_clickbank_return&s2member_paypal_return=1" . $rtn_q));
                     $rtn_r = c_ws_plugin__s2member_utils_urls::add_s2member_sig($rtn_r, "s2member_paypal_proxy_verification");
                     /**/
                     $clickbank["s2member_log"][] = $rtn_r;
                     /**/
                     wp_redirect($rtn_r);
                 } else {
                     if (preg_match("/^(TEST_)?SALE\$/i", $order["txnType"]) && isset($s2vars["s2_p1"], $s2vars["s2_p3"])) {
                         $clickbank["s2member_log"][] = "ClickBank® transaction identified as ( `SALE/RECURRING` ).";
                         $clickbank["s2member_log"][] = "Return-Data reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `subscr_signup` ).";
                         $clickbank["s2member_log"][] = "Please check PayPal® RTN logs for further processing details.";
                         /**/
                         $rtn = array();
                         /* Reset. */
                         /**/
                         $rtn["txn_type"] = "subscr_signup";
                         $rtn["subscr_id"] = $s2vars["s2_subscr_id"];
                         $rtn["recurring"] = $order["futurePayments"] > 1 ? "1" : "0";
                         /**/
                         $rtn["txn_id"] = $order["receipt"];
                         $rtn["custom"] = $s2vars["s2_custom"];
                         /**/
                         $rtn["period1"] = $s2vars["s2_p1"];
                         $rtn["period3"] = $s2vars["s2_p3"];
                         /**/
                         $rtn["mc_amount1"] = number_format($order["amount"], 2, ".", "");
                         $rtn["mc_amount3"] = number_format($order["rebillAmount"], 2, ".", "");
                         /**/
                         $rtn["mc_currency"] = strtoupper($order["currency"]);
                         $rtn["tax"] = "0.00";
                         /* No tax. */
                         /**/
                         $rtn["payer_email"] = $order["email"];
                         $rtn["first_name"] = ucwords(strtolower($order["firstName"]));
                         $rtn["last_name"] = ucwords(strtolower($order["lastName"]));
                         /**/
                         $rtn["option_name1"] = $s2vars["s2_referencing"] ? "Referencing Customer ID" : "Originating Domain";
                         $rtn["option_selection1"] = $s2vars["s2_referencing"] ? $s2vars["s2_referencing"] : $_SERVER["HTTP_HOST"];
                         /**/
                         $rtn["option_name2"] = "Customer IP Address";
                         $rtn["option_selection2"] = $s2vars["s2_customer_ip"];
                         /**/
                         $rtn["item_number"] = $s2vars["s2_invoice"];
                         $rtn["item_name"] = $s2vars["s2_desc"];
                         /**/
                         $rtn_q = "&s2member_paypal_proxy=clickbank&s2member_paypal_proxy_use=standard-emails";
                         if (!empty($_GET["s2member_pro_clickbank_return_success"])) {
                             $rtn_q .= "&s2member_paypal_return_success=" . rawurlencode(trim(stripslashes($_GET["s2member_pro_clickbank_return_success"])));
                         }
                         /**/
                         $rtn_r = add_query_arg(urlencode_deep($rtn), site_url("/?s2member_pro_clickbank_return&s2member_paypal_return=1" . $rtn_q));
                         $rtn_r = c_ws_plugin__s2member_utils_urls::add_s2member_sig($rtn_r, "s2member_paypal_proxy_verification");
                         /**/
                         $clickbank["s2member_log"][] = $rtn_r;
                         /**/
                         wp_redirect($rtn_r);
                     } else {
                         $clickbank["s2member_log"][] = "Unexpected txnType. The ClickBank® txnType did not match a required action.";
                         /**/
                         $clickbank["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
                         /**/
                         echo '<script type="text/javascript">' . "\n";
                         echo "alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("ERROR: Unexpected txnType. Please contact Support for assistance.\n\nThe ClickBank® txnType did not match a required action.", "s2member-front", "s2member")) . "');" . "\n";
                         echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(home_url("/")) . "';";
                         echo '</script>' . "\n";
                     }
                 }
             } else {
                 $clickbank["s2member_log"][] = "Unable to obtain API vars. The ClickBank® API may NOT have data for this order yet. Or, your ClickBank® API Keys are NOT configured properly under `s2Member -> ClickBank® Options`.";
                 $clickbank["s2member_log"][] = var_export($_REQUEST, true);
                 /* Recording ``$_POST`` + ``$_GET`` vars for analysis and debugging. */
                 /**/
                 $clickbank["s2member_log"][] = "Return-Data reformulated. Piping through s2Member's core/standard PayPal® processor with `proxy_use` ( `ty-email` ).";
                 $clickbank["s2member_log"][] = "Please check PayPal® RTN logs for further processing details.";
                 /**/
                 $rtn_q = "&s2member_paypal_proxy=clickbank&s2member_paypal_proxy_use=standard-emails,ty-email";
                 if (!empty($_GET["s2member_pro_clickbank_return_success"])) {
                     $rtn_q .= "&s2member_paypal_return_success=" . rawurlencode(trim(stripslashes($_GET["s2member_pro_clickbank_return_success"])));
                 }
                 /**/
                 $rtn_r = site_url("/?s2member_pro_clickbank_return&s2member_paypal_return=1" . $rtn_q);
                 $rtn_r = c_ws_plugin__s2member_utils_urls::add_s2member_sig($rtn_r, "s2member_paypal_proxy_verification");
                 /**/
                 $clickbank["s2member_log"][] = $rtn_r;
                 /**/
                 wp_redirect($rtn_r);
             }
         } else {
             $clickbank["s2member_log"][] = "Unable to verify POST vars. This is most likely related to an invalid ClickBank® configuration. Please check: s2Member -> ClickBank® Options.";
             $clickbank["s2member_log"][] = "If you're absolutely SURE that your ClickBank® configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to ClickBank® over an HTTPS connection.";
             $clickbank["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows® server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows® server.";
             $clickbank["s2member_log"][] = var_export($_REQUEST, true);
             /* Recording _POST + _GET vars for analysis and debugging. */
             /**/
             $clickbank["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
             /**/
             echo '<script type="text/javascript">' . "\n";
             echo "alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("ERROR: Unable to verify POST vars. Please contact Support for assistance.\n\nThis is most likely related to an invalid ClickBank® configuration. If you are the site owner, please check: s2Member -> ClickBank® Options.", "s2member-front", "s2member")) . "');" . "\n";
             echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(home_url("/")) . "';";
             echo '</script>' . "\n";
         }
         /**/
         $logv = c_ws_plugin__s2member_utilities::ver_details();
         $logm = c_ws_plugin__s2member_utilities::mem_details();
         $log4 = $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] . "\nUser-Agent: " . $_SERVER["HTTP_USER_AGENT"];
         $log4 = is_multisite() && !is_main_site() ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
         $log2 = is_multisite() && !is_main_site() ? "clickbank-rtn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "clickbank-rtn.log";
         /**/
         if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) {
             if (is_dir($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])) {
                 if (is_writable($logs_dir) && c_ws_plugin__s2member_utils_logs::archive_oversize_log_files()) {
                     file_put_contents($logs_dir . "/" . $log2, $logv . "\n" . $logm . "\n" . $log4 . "\n" . var_export($clickbank, true) . "\n\n", FILE_APPEND);
                 }
             }
         }
         /**/
         exit;
         /* Exit now. */
     }
 }
Пример #16
0
 /**
  * Handles AliPay Return URL processing.
  *
  * @package s2Member\AliPay
  * @since 1.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after redirection.
  */
 public static function alipay_return()
 {
     global $current_site, $current_blog;
     if (!empty($_GET["s2member_pro_alipay_return"]) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_alipay_seller_email"]) {
         if (is_array($alipay = c_ws_plugin__s2member_pro_alipay_utilities::alipay_postvars()) && ($_alipay = $alipay)) {
             $alipay["s2member_log"][] = "Return-Data received on: " . date("D M j, Y g:i:s a T");
             $alipay["s2member_log"][] = "s2Member POST vars verified through a POST back to AliPay.";
             if (preg_match("/^(TRADE_FINISHED|TRADE_SUCCESS)\$/i", $alipay["trade_status"]) && !$alipay["refund_status"]) {
                 $alipay["s2member_log"][] = "AliPay transaction identified as ( `TRADE_FINISHED|TRADE_SUCCESS` ).";
                 $alipay["s2member_log"][] = "Return-Data reformulated. Piping through s2Member's core/standard PayPal processor as `txn_type` ( `web_accept` ).";
                 $alipay["s2member_log"][] = "Please check PayPal RTN logs for further processing details.";
                 list($alipay["invoice"], $alipay["item_number"], $alipay["referencing"], $alipay["customer_ip"]) = preg_split("/~/", $alipay["out_trade_no"]);
                 list($alipay["first_name"], $alipay["last_name"]) = preg_split("/@/", $alipay["buyer_email"], 2);
                 $rtn = array();
                 $rtn["txn_type"] = "web_accept";
                 $rtn["txn_id"] = $alipay["trade_no"];
                 $rtn["custom"] = $alipay["extra_common_param"];
                 $rtn["mc_gross"] = number_format($alipay["total_fee"], 2, ".", "");
                 $rtn["mc_currency"] = "CNY";
                 // Yuan.
                 $rtn["tax"] = "0";
                 // No tax.
                 $rtn["payer_email"] = $alipay["buyer_email"];
                 $rtn["first_name"] = $alipay["first_name"];
                 $rtn["last_name"] = $alipay["last_name"];
                 $rtn["option_name1"] = $alipay["referencing"] ? "Referencing Customer ID" : "Originating Domain";
                 $rtn["option_selection1"] = $alipay["referencing"] ? $alipay["referencing"] : $_SERVER["HTTP_HOST"];
                 $rtn["option_name2"] = "Customer IP Address";
                 $rtn["option_selection2"] = $alipay["customer_ip"];
                 $rtn["item_number"] = $alipay["item_number"];
                 $rtn["item_name"] = $alipay["body"];
                 $rtn_q = "&s2member_paypal_proxy=alipay&s2member_paypal_proxy_use=standard-emails";
                 if (!empty($_GET["s2member_pro_alipay_return_success"])) {
                     $rtn_q .= "&s2member_paypal_return_success=" . rawurlencode(trim(stripslashes($_GET["s2member_pro_alipay_return_success"])));
                 }
                 $rtn_r = add_query_arg(urlencode_deep($rtn), site_url("/?s2member_pro_alipay_return&s2member_paypal_return=1" . $rtn_q));
                 $rtn_r = c_ws_plugin__s2member_utils_urls::add_s2member_sig($rtn_r, "s2member_paypal_proxy_verification");
                 $alipay["s2member_log"][] = $rtn_r;
                 wp_redirect($rtn_r);
             } else {
                 $alipay["s2member_log"][] = "Unexpected status. The AliPay status did not match a required action.";
                 $alipay["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
                 echo '<script type="text/javascript">' . "\n";
                 echo "alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("ERROR: Unexpected status. Please contact Support for assistance.\n\nThe AliPay status did NOT match a required action.", "s2member-front", "s2member")) . "');" . "\n";
                 echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(home_url("/")) . "';";
                 echo '</script>' . "\n";
             }
         } else {
             $alipay["s2member_log"][] = "Unable to verify POST vars. This is most likely related to an invalid AliPay configuration. Please check: s2Member -› AliPay Options.";
             $alipay["s2member_log"][] = "If you're absolutely SURE that your AliPay configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to AliPay over an HTTPS connection.";
             $alipay["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows server.";
             $alipay["s2member_log"][] = var_export($_REQUEST, true);
             // Recording _POST + _GET vars for analysis and debugging.
             $alipay["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
             echo '<script type="text/javascript">' . "\n";
             echo "alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("ERROR: Unable to verify POST vars. Please contact Support for assistance.\n\nThis is most likely related to an invalid AliPay configuration. If you are the site owner, please check: s2Member -› AliPay Options.", "s2member-front", "s2member")) . "');" . "\n";
             echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(home_url("/")) . "';";
             echo '</script>' . "\n";
         }
         $logt = c_ws_plugin__s2member_utilities::time_details();
         $logv = c_ws_plugin__s2member_utilities::ver_details();
         $logm = c_ws_plugin__s2member_utilities::mem_details();
         $log4 = $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] . "\nUser-Agent: " . $_SERVER["HTTP_USER_AGENT"];
         $log4 = is_multisite() && !is_main_site() ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
         $log2 = is_multisite() && !is_main_site() ? "alipay-rtn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "alipay-rtn.log";
         if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) {
             if (is_dir($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])) {
                 if (is_writable($logs_dir) && c_ws_plugin__s2member_utils_logs::archive_oversize_log_files()) {
                     file_put_contents($logs_dir . "/" . $log2, "LOG ENTRY: " . $logt . "\n" . $logv . "\n" . $logm . "\n" . $log4 . "\n" . c_ws_plugin__s2member_utils_logs::conceal_private_info(var_export($alipay, true)) . "\n\n", FILE_APPEND);
                 }
             }
         }
         exit;
         // Exit now.
     }
 }
Пример #17
0
 /**
  * Builds a reCAPTCHA™ JavaScript `script` tag for display.
  *
  * @package s2Member\Utilities
  * @since 3.5
  *
  * @param string $theme Optional. The theme used in display. Defaults to `clean`.
  * @param string $tabindex Optional. Value of `tabindex=""` attribute. Defaults to `-1`.
  * @param string $error Optional. An error message to display.
  * @return string HTML markup for JavaScript tag.
  */
 public static function recaptcha_script_tag($theme = '', $tabindex = '', $error = '')
 {
     $theme = $theme ? $theme : 'clean';
     $tabindex = strlen($tabindex) ? (int) $tabindex : -1;
     $keys = c_ws_plugin__s2member_utils_captchas::recaptcha_keys();
     if (self::recaptcha_version() === '2') {
         $theme = !$theme || in_array($theme, array('red', 'white', 'clean', 'blackglass'), TRUE) ? 'light' : $theme;
         return '<div class="g-recaptcha" data-sitekey="' . esc_attr($keys['public']) . '" data-size="normal" data-theme="' . esc_attr($theme) . '" data-tabindex="' . esc_attr($tabindex) . '"></div>' . '<script src="https://www.google.com/recaptcha/api.js"></script>';
     }
     $options = '<script type="text/javascript">' . "if(typeof RecaptchaOptions !== 'object'){ var RecaptchaOptions = {theme: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($theme) . "', lang: '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($GLOBALS['WS_PLUGIN__']['s2member']['c']['recaptcha']['lang']) . "', tabindex: " . $tabindex . " }; }" . '</script>' . "\n";
     $no_tabindex_icons = '<script type="text/javascript">' . "if(typeof jQuery === 'function'){ jQuery('td a[id^=\"recaptcha\"]').removeAttr('tabindex'); }" . '</script>';
     $adjustments = !apply_filters('c_ws_plugin__s2member_utils_tabindex_recaptcha_icons', false, get_defined_vars()) ? $no_tabindex_icons : '';
     return $options . '<script type="text/javascript" src="' . esc_attr('https://www.google.com/recaptcha/api/challenge?k=' . urlencode($keys['public'])) . ($error ? '&amp;error=' . urlencode($error) : '') . '"></script>' . $adjustments;
 }
Пример #18
0
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     echo '<div class="ws-menu-page-toolbox">' . "\n";
     c_ws_plugin__s2member_menu_pages_tb::display();
     echo '</div>' . "\n";
     echo '<h2>Download Options</h2>' . "\n";
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form" action="' . esc_attr(remove_query_arg('ws_plugin__s2member_cf_options_reset')) . '" autocomplete="off">' . "\n";
     echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr(wp_create_nonce("ws-plugin--s2member-options-save")) . '" />' . "\n";
     echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" id="ws-plugin--s2member-amazon-cf-files-distros-auto-config-status" value="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"]) . '" />' . "\n";
     echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
     do_action("ws_plugin__s2member_during_down_ops_page_before_left_sections", get_defined_vars());
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_restrictions", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_restrictions", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Basic Download Restrictions">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-restrictions-section">' . "\n";
         echo '<h3>File Download Restrictions (required, if providing access to protected files)</h3>' . "\n";
         echo '<p>If your Membership offering allows access to restricted files, you\'ll want to configure these options.</p>' . "\n";
         echo '<p class="info"><strong>NOTE:</strong> If you intend to offer File Downloads in one way or another, you must configure at least one of the options below. For security purposes, s2Member\'s File Download functionality is disabled unless &amp; until at least one of the options below have been configured; i.e., s2Member expects you to configure Basic Downloads for at least one Membership Level before any sort of download-related functionality will work. This includes functionality associated with the <code>[s2File /]</code> and <code>[s2Stream /]</code> Shortcodes also.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_restrictions", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><strong>Upload restricted files to this security-enabled directory:</strong><br /><code>' . esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '</code></p>' . "\n";
         echo '<p>- Now, you can link to any protected file, using this special format:<br />&nbsp;&nbsp;<code>' . esc_html(home_url("/?s2member_file_download=example-file.zip")) . '</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download</strong> = file, relative to the /' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/ directory. In other words, just the file name.</em></small></p>' . "\n";
         echo '<p>- Or, use: <code>[s2File download="example-file.zip" /]</code> <em>(easier Shortcode if you prefer)</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL for you, easier.</em></small></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p>s2Member will allow access to these protected files, based on the configuration you specify below. Repeated downloads of the same exact file are NOT tabulated against the totals below. Once a file has been downloaded, future downloads of the same exact file, by the same exact Member will not be counted against them. In other words, if a Member downloads the same file three times, the system only counts that as one unique download. In addition, multiple variations of popular media formats are only counted once. This is because many site owners provide multiple download options to their Users/Members, for compatibility purposes. Files that have the same exact name, with one of these extensions, will only be counted ONE time: <code>' . esc_html(implode(",", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"])) . '</code>.</p>' . "\n";
         echo '<p>s2Member will automatically detect links, anywhere in your content, and/or anywhere in your theme files, that contain <code>s2member_file_download</code> or <code>s2member-files</code>. Whenever a logged-in Member clicks a link that contains <code>s2member_file_download</code> or <code>s2member-files</code>, the system will politely ask the user to confirm the download using a very intuitive JavaScript confirmation prompt, which contains specific details about your configured download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not. If you want to suppress this JavaScript confirmation prompt, you can add this to the end of your links: <code>&amp;s2member_skip_confirmation</code>. Shortcode alternative: <code>[s2File skip_confirmation="yes" /]</code>.</p>' . "\n";
         echo '<p><em>* The above only applies to Users who are logged in as Members. For all other visitors in the general public, the <code>?s2member_file_download</code> links will redirect them your Membership Options Page, so that new visitors can signup, in order to gain access, by becoming a Member. You may also want to have a look down below at s2Member\'s "Advanced Download Restrictions", which provides a greater degree of flexibility.</em></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             echo '<tr>' . "\n";
             echo '<th style="padding-top:0;">' . "\n";
             echo '<label for="ws-plugin--s2member-level' . $n . '-file-downloads-allowed">' . "\n";
             echo $n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? 'File Downloads (Highest Level #' . $n . '):' . "\n" : 'File Downloads (Level #' . $n . ' Or Higher):' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td>' . "\n";
             echo '<input type="text" maxlength="9" autocomplete="off" name="ws_plugin__s2member_level' . $n . '_file_downloads_allowed" id="ws-plugin--s2member-level' . $n . '-file-downloads-allowed" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed"]) . '" style="width:200px;" /> every <input type="text" maxlength="3" autocomplete="off" name="ws_plugin__s2member_level' . $n . '_file_downloads_allowed_days" id="ws-plugin--s2member-level' . $n . '-file-downloads-allowed-days" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed_days"]) . '" style="width:200px;" onkeyup="if(this.value > 365){ alert(\'(365 days is the maximum).\\nThis keeps the logs optimized.\'); this.value = 365; }" /> day(s).<br />' . "\n";
             echo 'Only this many unique downloads will be permitted every X day(s), at ' . ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? 'highest Level #' . $n : 'Level #' . $n . ' or higher') . '.<br />' . "\n";
             echo '<em>* To allow UNLIMITED downloads, use: <code>999999999</code> (i.e., <code>999999999</code> = unlimited).</em>' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo $n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? '<tr><td><div class="ws-menu-page-hr" style="margin:10px 0 10px 0;"></div></td></tr>' : '';
         }
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_restrictions", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_limit_exceeded_page", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_limit_exceeded_page", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Download Limit Exceeded Page">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-limit-exceeded-page-section">' . "\n";
         echo '<h3>Download Limit Exceeded Page (required, if providing access to protected files)</h3>' . "\n";
         echo '<p>This Page will be shown when/if a Member reaches their download limit, based on your configuration of <strong>Basic Download Restrictions</strong> above. This Page should be created by you, in WordPress. This Page should provide an informative message to the Member, describing your file access restrictions. Just tell them a little bit about your policy on file downloads, and why they might have reached this Page.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_limit_exceeded_page", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-file-download-limit-exceeded-page">' . "\n";
         echo 'Download Limit Exceeded Page:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_file_download_limit_exceeded_page" id="ws-plugin--s2member-file-download-limit-exceeded-page">' . "\n";
         echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
         foreach ($ws_plugin__s2member_temp_a = array_merge((array) get_pages()) as $ws_plugin__s2member_temp_o) {
             echo '<option value="' . esc_attr($ws_plugin__s2member_temp_o->ID) . '"' . ($ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] ? ' selected="selected"' : '') . '>' . esc_html($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
         }
         echo '</select><br />' . "\n";
         echo 'We recommend the following title: <code>Download Limit Exceeded</code>.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_limit_exceeded_page", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_advanced_restrictions", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_advanced_restrictions", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Advanced Download Restrictions">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-restrictions-section">' . "\n";
         echo '<h3>Advanced Download Restrictions (optional, for greater flexibility)</h3>' . "\n";
         echo '<p>By default, s2Member uses your Basic Download Restrictions, as configured above. However, you can force s2Member to allow File Downloads, using an extra query string parameter: <code>&amp;s2member_file_download_key=[Key]</code>. A File Download `Key` is passed through this parameter; it tells s2Member to allow the download of this particular file, regardless of Membership Level; and WITHOUT checking any Basic Restrictions, that you may or may not have configured above. The creation of a File Download `Key`, requires a small PHP code snippet. In order to use PHP scripting inside your Posts/Pages, you\'ll need to install this handy plugin (<a href="http://s2member.com/r/ezphp/" target="_blank" rel="external">ezPHP</a>). There is also a Shortcode equivalent, which does NOT require PHP at all, as seen below.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_advanced_restrictions", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p>' . esc_html(home_url("/?s2member_file_download=example-file.zip")) . '<code>&amp;s2member_file_download_key=&lt;?php echo s2member_file_download_key("example-file.zip"); ?&gt;</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download_key</strong> = &lt;?php echo s2member_file_download_key("file, relative to the /' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/ directory"); ?&gt;</em></small></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p>' . esc_html(home_url("/?s2member_file_download=example-file.zip")) . '<code>&amp;s2member_file_download_key=[s2Key file_download="example-file.zip" /]</code><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2Key file_download="example-file.zip" /]</code></em></small></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><code>[s2File download="example-file.zip" download_key="true" /]</code> <em>(Key is auto-generated in this case)</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL, no need to generate a Key yourself.</em></small></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p>The function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_key()" target="_blank" rel="external">s2member_file_download_key()</a>, is part of the s2Member API. It produces a time-sensitive File Download Key that is unique to each and every visitor. Each Key it produces <em>(at the time it is produced)</em>, will be valid for the current day, and only for a specific IP address and User-Agent string; as detected by s2Member. This makes it possible for you to create links on your site, which provide access to protected file downloads; and without having to worry about one visitor sharing their link with another. So let\'s take a quick look at what <code>s2member_file_download_key()</code> actually produces.</p>' . "\n";
         echo '<p><code>s2member_file_download_key("example-file.zip")</code> = a site-specific hash of: <code>date("Y-m-d").$_SERVER["REMOTE_ADDR"].$_SERVER["HTTP_USER_AGENT"].$file</code></p>' . "\n";
         echo '<p>When <code>s2member_file_download_key = <em>a valid Key</em></code>, it works independently from Member Level Access. That is, a visitor does NOT have to be logged in to receive access; they just need a valid Key. Using this advanced technique, you could extend s2Member\'s file protection routines, or even combine them with Specific Post/Page Access, and more. The possibilities are limitless really.</p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_advanced_restrictions", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_inline_extensions", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_inline_extensions", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Inline File Extensions">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-inline-extensions-section">' . "\n";
         echo '<h3>Inline File Extensions (optional, for content-disposition)</h3>' . "\n";
         echo '<p>There are two ways to serve files. Inline, or as an Attachment. By default, s2Member will serve all of your protected files, as downloadable attachments. Meaning, visitors will be given a file download prompt. Otherwise known as <code>Content-Disposition: attachment</code>. In some cases though, you may wish to serve files inline. For example, PDF files and images should usually be served inline. When you serve a file inline, it is displayed in your browser immediately, rather than your browser prompting you to download the file as an attachment.</p>' . "\n";
         echo '<p>Using the field below, you can list all of the extensions that you want s2Member to serve inline (ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png,mp3,mp4,flv,ogg,webm</code>). Please understand, some files just cannot be displayed inline. For instance, there is no way to display an <code>exe</code> file inline. So only specify extensions that can, and should be displayed inline by a web browser. Alternatively, if you would rather handle this on a case-by-case basis, you can simply add the following to the end of your download links: <code>&amp;s2member_file_inline=yes</code>. Shortcode alternative: <code>[s2File download="example-file.zip" inline="yes" /]</code>.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_inline_extensions", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-file-download-inline-extensions">' . "\n";
         echo 'Default Inline File Extensions (comma-delimited):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_file_download_inline_extensions" id="ws-plugin--s2member-file-download-inline-extensions" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]) . '" /><br />' . "\n";
         echo 'Inline extensions, comma-delimited. Ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png,mp3,mp4,flv,ogg,webm</code>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_inline_extensions", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_remote_authorization", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_remote_authorization", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Remote Auth / Podcasting">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-remote-authorization-section">' . "\n";
         echo '<h3>Remote Header Authorization (optional)</h3>' . "\n";
         echo '<p>This can be enabled on a case-by-case basis. Just add this to the end of your download links: <code>&amp;s2member_file_remote=yes</code></p>' . "\n";
         echo '<p>Shortcode alternative: <code>[s2File download="example-file.zip" remote="yes" /]</code></p>' . "\n";
         echo '<p>Remote Header Authorization allows access to file downloads through an entirely different approach. Instead of asking the Member to log into your site through a browser, a Member will be prompted automatically, to log in through HTTP Header Authorization prompts; which is the same technique used in more traditional security systems via .htaccess files. In other words, Remote Header Authorization makes it possible for your Members to access files through remote applications that may NOT use a browser. This is often the case when a Member needs to access protected files through a software client like iTunes; typical with podcasts. See <a href="http://www.s2member.com/videos/71F49478D6983A9C/" target="_blank" rel="external">tutorial video here</a> for details about how to setup a Podcast for iTunes.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_remote_authorization", get_defined_vars());
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_remote_authorization", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_amazon_s3", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_amazon_s3", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Amazon S3/CDN Storage Option"' . (!empty(c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' default-state="open"' : '') . '>' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-amazon-s3-section">' . "\n";
         echo '<h3>Amazon S3/CDN Storage &amp; Delivery (optional)</h3>' . "\n";
         echo '<iframe width="560" height="315" src="https://www.youtube.com/embed/Gr87ZBJQE0I" frameborder="0" allowscriptaccess="always" allowfullscreen="true" style="float:right; margin:0 0 20px 20px; width:300px; height:200px;"></iframe>' . "\n";
         echo '<a href="http://s2member.com/r/amazon-s3/" target="_blank"><img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/amazon-logo.png" class="ws-menu-page-right" style="width:250px; height:100px; border:0;" alt="." /></a>' . "\n";
         echo '<p>Please note, all of this is optional. s2Member can be configured here to ONLY use Amazon S3 <em>(i.e., without Amazon CloudFront)</em>. Or, s2Member can be configured to use BOTH Amazon S3 and Amazon CloudFront together. If you want to use Amazon S3 Storage, but you don\'t care about Amazon CloudFront, feel free to leave the entire Amazon CloudFront section empty. The configuration options in the Amazon CloudFront section are ONLY required if you are planning to use both Amazon S3 and Amazon CloudFront together.</p>' . "\n";
         echo '<p>Amazon Simple Storage Service (<a href="http://s2member.com/r/amazon-s3/" target="_blank" rel="external">Amazon S3</a>). Amazon S3 is storage for the Internet. It is designed to make web-scale computing easier for developers. Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives developers access to the same highly scalable, reliable, secure, fast, inexpensive infrastructure that Amazon uses to run its own global network of web sites. s2Member has been integrated with Amazon S3, so that <em>(if you wish)</em>, instead of using the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory, you can store all of your protected files inside an Amazon S3 Bucket.</p>' . "\n";
         echo '<p>If you configure the options below, s2Member will assume all protected files are inside your Amazon S3 Bucket; and the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory is no longer used at all. That being said, all other aspects of s2Member\'s File Download protection remain the same. The only thing that changes, is the location of your protected files. In other words, Basic Download Restrictions, Download Keys, Inline Extensions, Custom Capability and/or Membership Level Files will all continue to work just as before. The only difference is that s2Member will use your Amazon S3 Bucket as a CDN <em>(i.e., Content Delivery Network)</em> instead of the local <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory.</p>' . "\n";
         echo '<p>s2Member assumes that you\'re creating a new Amazon S3 Bucket, specifically for this installation; and that your Bucket is NOT available publicly. In other words, if you type this URL into your browser <em>(i.e., <code>http://your-bucket-name.s3.amazonaws.com/</code>)</em>, you should get an error that says: <code>Access Denied</code>. That\'s good, that\'s exactly what you want. You can create your Amazon S3 Bucket using the <a href="http://s2member.com/r/amazon-s3-console/" target="_blank" rel="external">Amazon interface</a>. Or, some people prefer to use this popular Firefox extension (<a href="http://s2member.com/r/s3-fox-organizer/" target="_blank" rel="external">S3 Fox Organizer</a>).</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_amazon_s3", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Digitally Signed URLs", authenticated by the Amazon S3 API. Documented for developers <a href="http://s2member.com/r/amazon-s3-digital-signing-process/" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon S3 URLs (internally); which allow Customers temporary access to specific files inside your S3 Bucket. s2Member\'s Digitally Signed URLs leading to Amazon S3, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason (not likely), you can use this WordPress Filter: <code>ws_plugin__s2member_amazon_s3_file_expires_time</code>.</em></p>' . "\n";
         echo '<p><em><strong>Linking To Protected Files:</strong> Nothing changes. s2Member\'s integration with Amazon S3 serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>' . esc_html(home_url("/?s2member_file_download=example-file.zip")) . '</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon S3 URL, which allows them access to a particular file via Amazon S3. For further details, please review this section of your Dashboard: <strong>s2Member → Download Options → Basic Download Restrictions</strong>. Also see: <strong>s2Member → Download Options → Advanced Mod-Rewrite Linkage</strong>.</em></p>' . "\n";
         echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> The query string parameter <code>&amp;s2member_file_inline=yes</code> DOES work for files served directly through Amazon S3. s2Member DOES have control over the <code>Content-Type</code> and <code>Content-Disposition</code> headers for files being served through Amazon S3. However, Amazon CloudFront servers do NOT automatically determine the MIME type for the objects they serve. If you integrate both Amazon S3 and CloudFront, s2Member will NOT have control over headers. Therefore, when you upload a file to your Amazon S3 Bucket, you should set its Content-Type header. Again, with the Amazon S3/CloudFront combination, you MUST configure headers yourself (such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code>) that you want Amazon CloudFront to send for a particular file. It\'s quite easy. You do this by setting <strong>Properties → Metadata (i.e., headers)</strong> on a per-file basis, from inside your Amazon S3 Management Console. In short, when you upload a file to your Amazon S3 Bucket, if you want that file to be served a certain way, be sure to configure its <strong>Properties → Metadata</strong> accordingly.</em></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th style="padding-top:0;">' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-s3-files-bucket-region">' . "\n";
         echo 'Amazon S3 File Bucket Region (please choose):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_amazon_s3_files_bucket_region" id="ws-plugin--s2member-amazon-s3-files-bucket-region">' . "\n";
         echo '<option value="us-east-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'us-east-1' ? ' selected="selected"' : '') . '>us-east-1</option>' . "\n";
         echo '<option value="us-west-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'us-west-1' ? ' selected="selected"' : '') . '>us-west-1</option>' . "\n";
         echo '<option value="us-west-2"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'us-west-2' ? ' selected="selected"' : '') . '>us-west-2</option>' . "\n";
         echo '<option value="eu-west-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'eu-west-1' ? ' selected="selected"' : '') . '>eu-west-1</option>' . "\n";
         echo '<option value="eu-central-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'eu-central-1' ? ' selected="selected"' : '') . '>eu-central-1</option>' . "\n";
         echo '<option value="ap-southeast-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'ap-southeast-1' ? ' selected="selected"' : '') . '>ap-southeast-1</option>' . "\n";
         echo '<option value="ap-southeast-2"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'ap-southeast-2' ? ' selected="selected"' : '') . '>ap-southeast-2</option>' . "\n";
         echo '<option value="ap-northeast-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'ap-northeast-1' ? ' selected="selected"' : '') . '>ap-northeast-1</option>' . "\n";
         echo '<option value="sa-east-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'sa-east-1' ? ' selected="selected"' : '') . '>sa-east-1</option>' . "\n";
         echo '<option value="us-gov-west-1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket_region"] === 'us-gov-west-1' ? ' selected="selected"' : '') . '>us-gov-west-1</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'See: <a href="http://s2member.com/r/aws-s3-region-codes/" target="_blank">http://s2member.com/r/aws-s3-region-codes/</a>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th style="padding-top:0;">' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-s3-files-bucket">' . "\n";
         echo 'Amazon S3 File Bucket Name (where protected files are):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_bucket" id="ws-plugin--s2member-amazon-s3-files-bucket" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]) . '" /><br />' . "\n";
         echo 'Your Amazon S3 Bucket will be used, instead of the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory.<br />' . "\n";
         echo 'Please type the name of your Bucket. Ex: <code>mys3bucket</code>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-s3-files-access-key">' . "\n";
         echo 'Amazon Access Key (Access Key ID):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_access_key" id="ws-plugin--s2member-amazon-s3-files-access-key" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]) . '" /><br />' . "\n";
         echo 'See: <strong>Amazon Web Services Account → Security Credentials → Access Keys</strong><br />' . "\n";
         echo '<em><small>Amazon suggests creating a new IAM user. Use the Keys for that IAM user here.</small></em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-s3-files-secret-key">' . "\n";
         echo 'Amazon Secret Key (Secret Access Key):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_secret_key" id="ws-plugin--s2member-amazon-s3-files-secret-key" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]) . '" /><br />' . "\n";
         echo 'See: <strong>Amazon Web Services Account → Security Credentials → Access Keys</strong><br />' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_amazon_s3", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_amazon_cf", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_amazon_cf", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Amazon S3/CloudFront CDN Storage Option"' . (!empty(c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' default-state="open"' : '') . '>' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-amazon-cf-section">' . "\n";
         echo '<h3>Amazon S3/CloudFront CDN Storage &amp; Delivery (optional)</h3>' . "\n";
         echo '<iframe width="560" height="315" src="https://www.youtube.com/embed/Gr87ZBJQE0I" frameborder="0" allowscriptaccess="always" allowfullscreen="true" style="float:right; margin:0 0 20px 20px; width:300px; height:200px;"></iframe>' . "\n";
         echo '<a href="http://s2member.com/r/amazon-cloudfront/" target="_blank"><img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/amazon-logo.png" class="ws-menu-page-right" style="width:250px; height:100px; border:0;" alt="." /></a>' . "\n";
         echo '<p>Please note, all of this is optional. s2Member can be configured to ONLY use Amazon S3 <em>(i.e., without Amazon CloudFront)</em>. Or, s2Member can be configured to use BOTH Amazon S3 and Amazon CloudFront together. If you don\'t want to use Amazon CloudFront, please leave this entire section empty. The configuration options in this section are ONLY required if you are planning to use both Amazon S3 and Amazon CloudFront together.</p>' . "\n";
         echo '<p>Amazon Simple Storage Service (<a href="http://s2member.com/r/amazon-s3/" target="_blank" rel="external">Amazon S3</a>) combined with <a href="http://s2member.com/r/amazon-cloudfront/" target="_blank" rel="external">Amazon CloudFront</a>. Amazon CloudFront is a web service for content delivery. It integrates with other Amazon Web Services <em>(i.e., Amazon S3 Storage)</em> to give developers and businesses an easy way to distribute content to end users with low latency, and with high data transfer speeds. Amazon CloudFront delivers your static and streaming content using a global network of edge locations. Requests for your Amazon S3 Bucket Objects <em>(i.e., your protected files)</em> are automatically routed to the nearest edge location, so content is delivered with the best possible performance. s2Member has been integrated with both Amazon S3 and with Amazon CloudFront. So <em>(if you wish)</em>, instead of using the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory, you can store all of your protected files inside an Amazon S3 Bucket and serve them via Amazon CloudFront. But again, please understand, the configuration options in this section are ONLY required if you\'re going to use both Amazon S3 &amp; CloudFront together.</p>' . "\n";
         echo '<p><strong>One of the great things about Amazon CloudFront</strong>, is its ability to <strong>stream/seek media files</strong> in the truest sense of the word. For sites delivering protected <em>FLV/MP4/OGG/WEBM</em> and other streaming audio/video file types over the <em>RTMP</em> protocol, Amazon CloudFront is our recommendation. Once you\'ve successfully configured s2Member to use both Amazon S3 and Amazon CloudFront together, please review the section below regarding <code>JW Player &amp; RTMP Protocol Examples</code>. s2Member will automatically serve your protected files over the <em>RTMP</em> protocol using an Amazon CloudFront Streaming Distribution.</p>' . "\n";
         echo '<p>If you configure the options below, s2Member will assume all protected files are inside your Amazon S3 Bucket; and the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory is no longer used at all. That being said, all other aspects of s2Member\'s File Download protection remain the same. The only thing that changes, is the location of your protected files. In other words, Basic Download Restrictions, Download Keys, Custom Capability and/or Membership Level Files will all continue to work just as before. The only difference is that s2Member will use your Amazon S3 Bucket, automatically connecting it to both of the Amazon CloudFront Distributions, which s2Member auto-configures for you <em>(see below)</em>. In this way, s2Member uses Amazon CloudFront as a CDN <em>(i.e., Content Delivery Network)</em> for your protected files.</p>' . "\n";
         echo '<p>s2Member assumes that you\'re creating a new Amazon S3 Bucket, specifically for this installation; and that your Bucket is NOT available publicly. In other words, if you type this URL into your browser <em>(i.e., <code>http://your-bucket-name.s3.amazonaws.com/</code>)</em>, you should get an error that says: <code>Access Denied</code>. That\'s good, that\'s exactly what you want. You can create your Amazon S3 Bucket using the <a href="http://s2member.com/r/amazon-s3-console/" target="_blank" rel="external">Amazon interface</a>. Or, some people prefer to use this popular Firefox extension (<a href="http://s2member.com/r/s3-fox-organizer/" target="_blank" rel="external">S3 Fox Organizer</a>). You will also need to enable CloudFront inside your Web Services account at Amazon. Don\'t worry about creating or configuring any CloudFront Distributions, s2Member will auto-create and auto-configure those for you, allowing you to serve protected files.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_amazon_cf", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member\'s auto-configuration routines for Amazon CloudFront (below), are designed to create &amp; configure various components on your Amazon Web Services account, which are all requirements for you to <a href="http://s2member.com/r/amazon-cloudfront-digitally-signed-urls/" target="_blank" rel="external">serve protected files through the Amazon S3/CloudFront combination</a>. These components include: an Origin Access Identity, read permissions for the Origin Access Identity, and two private content Distributions. One private content Distribution for file downloads, and another private content Distribution for streaming media files; both connected to and sourced by your Amazon S3 Bucket. In addition, s2Member will automatically configure an ACL &amp; Policy (i.e., permissions) on your Amazon S3 Bucket to make sure your protected object/files are NOT available to the public.</em></p>' . "\n";
         echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Digitally Signed URLs", authenticated by the Amazon CloudFront API. Documented for developers <a href="http://s2member.com/r/amazon-cloudfront-protected-files-for-developers/" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon CloudFront URLs (internally); which allow Customers temporary access to specific files inside your S3 Bucket—via CloudFront Distributions. s2Member\'s Digitally Signed URLs leading to Amazon S3/CloudFront, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason (not likely), you can use this WordPress Filter: <code>ws_plugin__s2member_amazon_cf_file_expires_time</code>.</em></p>' . "\n";
         echo '<p><em><strong>Linking To Protected Files:</strong> RTMP streams are special, but nothing else changes. s2Member\'s integration with Amazon S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>' . esc_html(home_url("/?s2member_file_download=example-file.zip")) . '</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon CloudFront URL, which allows them access to a particular file via Amazon CloudFront. For further details, please review this section of your Dashboard: <strong>s2Member → Download Options → Basic Download Restrictions</strong>. Also see: <strong>s2Member → Download Options → Advanced Mod-Rewrite Linkage</strong>. If you\'re streaming audio/video files over the RTMP protocol, please review the section below: <code>JW Player &amp; RTMP Protocol Examples</code>.</em></p>' . "\n";
         echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself (such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code>) that you want Amazon CloudFront to send for a particular file. It\'s quite easy. You do this by setting <strong>Properties → Metadata (i.e., headers)</strong> on a per-file basis, from inside your Amazon S3 Management Console. In short, when you upload a file to your Amazon S3 Bucket, if you want that file to be served a certain way, be sure to configure its <strong>Properties → Metadata</strong> accordingly.</em></p>' . "\n";
         echo stripos(PHP_OS, "win") === 0 && c_ws_plugin__s2member_utils_conds::is_localhost() ? '<p><em><strong>Localhost Developers:</strong> s2Member\'s Amazon CloudFront integration requires the <a href="http://php.net/manual/en/function.openssl-sign.php" target="_blank" rel="external">openssl_sign()</a> function in PHP so it can digitially sign CloudFront URLs. This function is sometimes problematic on localhost servers such as WAMP &amp; EasyPHP. We recommend installing <a href="http://www.slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="external">this lightweight alternative for Windows</a> while you\'re developing. s2Member will automatically find it here: <code>C:\\OpenSSL-Win[32/64]\\bin\\openssl.exe</code>.' . (file_exists("c:\\openssl-win32\\bin\\openssl.exe") || file_exists("c:\\openssl-win64\\bin\\openssl.exe") ? ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] IS installed in the correct location, thank you! )</strong>' : ' <strong class="ws-menu-page-hilite">(s2Member has detected that OpenSSL-Win[32/64] is NOT currently available)</strong>') . '</em></p>' . "\n" : '';
         if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"] === "configured") {
             echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon CloudFront Distributions are: ( ALREADY configured! )</strong></em>' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"] ? '<br /><em class="ws-menu-page-hilite">Downloads Distribution CNAME:</em> <em><code>' . esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . ' &mdash;&raquo; ' . esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_dname"]) . '</code></em>' : '') . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"] ? '<br /><em class="ws-menu-page-hilite">Streaming Distribution CNAME:</em> <em><code>' . esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . ' &mdash;&raquo; ' . esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_dname"]) . '</code></em>' : '') . '</p>' . "\n";
         } else {
             if (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"]) {
                 echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon CloudFront Distributions are: (NOT yet auto-configured).</strong></em></p>' . "\n";
             }
         }
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th style="padding-top:0;">' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-cf-files-private-key-id">' . "\n";
         echo 'Amazon CloudFront Key Pair ID (your Key Pair ID):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_private_key_id" id="ws-plugin--s2member-amazon-cf-files-private-key-id" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key_id"]) . '" data-s-prev-config-value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key_id"]) . '" /><br />' . "\n";
         echo 'See: <strong>Amazon Web Services Account → Security Credentials → CloudFront Key Pairs</strong>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-cf-files-private-key-entry">' . "\n";
         echo 'Amazon CloudFront Private Key (contents of your <code>pk-[***].pem</code> file):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_private_key" id="ws-plugin--s2member-amazon-cf-files-private-key" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]) . '" data-s-prev-config-value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]) . '" />' . "\n";
         echo '<textarea name="ws_plugin__s2member_amazon_cf_files_private_key_entry" id="ws-plugin--s2member-amazon-cf-files-private-key-entry" rows="3" wrap="off" spellcheck="false">' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]) . '</textarea><br />' . "\n";
         echo 'See: <strong>Amazon Web Services Account → Security Credentials → CloudFront Key Pairs</strong><br />' . "\n";
         echo '<em>* Note, s2Member needs your <strong>Private Key file</strong>, NOT your Public Key file.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros">' . "\n";
         echo 'Auto-Configure your Amazon S3/CloudFront combination?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="checkbox" name="ws_plugin__s2member_amazon_cf_files_auto_configure_distros" id="ws-plugin--s2member-amazon-cf-files-auto-configure-distros" value="' . esc_attr(wp_create_nonce("ws-plugin--s2member-amazon-cf-files-auto-configure-distros")) . '"' . (!empty(c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros"><strong>Yes</strong>, automatically configure my Amazon CloudFront Distributions &amp; Amazon S3 ACLs for me.</label><br />' . "\n";
         echo '<em>s2Member will auto-configure and/or delete &amp; re-configure your Amazon CloudFront Distributions for you.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="checkbox" name="ws_plugin__s2member_amazon_cf_files_auto_configure_distros_w_cnames" id="ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames" value="' . esc_attr(wp_create_nonce("ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames")) . '"' . (!empty(c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) && ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"] || $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames"><strong>Yes</strong>, I want s2Member to auto-configure using custom CNAMES that I\'ll setup.</label><br />' . "\n";
         echo '<em>* Optional, do NOT check this box unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div id="ws-plugin--s2member-amazon-cf-files-auto-configure-distro-cnames" style="display:none;">' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname">' . "\n";
         echo 'Amazon CloudFront CNAME for File Downloads (optional):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_downloads_cname" id="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . '" /><br />' . "\n";
         echo 'Example: <code>s2-file-downloads.' . esc_html(c_ws_plugin__s2member_utils_urls::parse_url(home_url(), PHP_URL_HOST)) . '</code>.<br />' . "\n";
         echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname">' . "\n";
         echo 'Amazon CloudFront CNAME for Streaming Files (optional):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_streaming_cname" id="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . '" /><br />' . "\n";
         echo 'Example: <code>s2-streaming-files.' . esc_html(c_ws_plugin__s2member_utils_urls::parse_url(home_url(), PHP_URL_HOST)) . '</code>.<br />' . "\n";
         echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<h3>Completely Reset CloudFront Configuration?</h3>' . "\n";
         echo '<div style="float:right; margin:0 0 0 25px;">' . "\n";
         echo '   <button type="button" onclick="if(confirm(\'Are you sure?\')) location.href = \'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(add_query_arg(urlencode_deep(array('ws_plugin__s2member_cf_options_reset' => wp_create_nonce('ws-plugin--s2member-cf-options-reset'))))) . '\';">Reset CloudFront Configuration</button>' . "\n";
         echo '</div>' . "\n";
         echo '<p>If you need to start all over again, you can click this button to reset your existing s2Member/CloudFront configuration. <em><strong>However, please note:</strong> you will still need to log into your AWS CloudFront Console (at some point) and remove any existing CloudFront Distributions and/or Origin Access Identities that were previously generated with s2Member; i.e., resetting your configuration here will allow you to start over with s2Member using a new set of CF Distros, but it does NOT delete anything on the AWS side.</em></p>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_amazon_cf", get_defined_vars());
     }
     /*			if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_amazon_s3_comp", TRUE, get_defined_vars()))
     						{
     							do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_amazon_s3_comp", get_defined_vars());
     
     							echo '<div class="ws-menu-page-group" title="S3-Compatible Content Delivery (e.g., DreamObjects, etc.)">'."\n";
     
     							echo '<div class="ws-menu-page-section ws-plugin--s2member-amazon-s3-comp-section">'."\n";
     							echo '<h3>S3-Compatible Content Delivery (optional)</h3>'."\n";
     							echo '<p>[Documentation goes here.]</p>'."\n";
     
     							echo '<div class="ws-menu-page-hr"></div>'."\n";
     
     							echo '<table class="form-table" style="margin-top:0;">'."\n";
     							echo '<tbody>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<th style="padding-top:0;">'."\n";
     							echo '<label for="ws-plugin--s2member-amazon-s3-comp-files-bucket">'."\n";
     							echo 'API Endpoint URL:'."\n";
     							echo '</label>'."\n";
     							echo '</th>'."\n";
     
     							echo '</tr>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<td>'."\n";
     							echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_s3_comp_api_endpoint" id="ws-plugin--s2member-amazon-s3-comp-api-endpoint" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_comp_api_endpoint"]).'" /><br />'."\n";
     							echo 'Please type the S3-Compatible API Endpoint URL'."\n";
     							echo '</td>'."\n";
     
     							echo '</tr>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<th style="padding-top:0;">'."\n";
     							echo '<label for="ws-plugin--s2member-amazon-s3-comp-files-bucket">'."\n";
     							echo 'S3-Compatible Bucket Name (where protected files are):'."\n";
     							echo '</label>'."\n";
     							echo '</th>'."\n";
     
     							echo '</tr>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<td>'."\n";
     							echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_s3_comp_files_bucket" id="ws-plugin--s2member-amazon-s3-comp-files-bucket" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_comp_files_bucket"]).'" /><br />'."\n";
     							echo 'Your S3-Compatible Bucket will be used, instead of the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory.<br />'."\n";
     							echo 'Please type the name of your Bucket. Ex: <code>mys3compbucket</code>'."\n";
     							echo '</td>'."\n";
     
     							echo '</tr>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<th>'."\n";
     							echo '<label for="ws-plugin--s2member-amazon-s3-comp-files-access-key">'."\n";
     							echo 'Access Key (Access Key ID):'."\n";
     							echo '</label>'."\n";
     							echo '</th>'."\n";
     
     							echo '</tr>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<td>'."\n";
     							echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_amazon_s3_comp_files_access_key" id="ws-plugin--s2member-amazon-s3-comp-files-access-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_comp_files_access_key"]).'" /><br />'."\n";
     							echo 'Please type the Access Key.'."\n";
     							echo '</td>'."\n";
     
     							echo '</tr>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<th>'."\n";
     							echo '<label for="ws-plugin--s2member-amazon-s3-comp-files-secret-key">'."\n";
     							echo 'Secret Key (Secret Access Key):'."\n";
     							echo '</label>'."\n";
     							echo '</th>'."\n";
     
     							echo '</tr>'."\n";
     							echo '<tr>'."\n";
     
     							echo '<td>'."\n";
     							echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_amazon_s3_comp_files_secret_key" id="ws-plugin--s2member-amazon-s3-comp-files-secret-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_comp_files_secret_key"]).'" /><br />'."\n";
     							echo 'Please type the Secret Key.'."\n";
     							echo '</td>'."\n";
     
     							echo '</tr>'."\n";
     							echo '</tbody>'."\n";
     							echo '</table>'."\n";
     							echo '</div>'."\n";
     
     							echo '</div>'."\n";
     
     							do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_amazon_s3_comp", get_defined_vars());
     						}*/
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_rtmp_streaming", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rtmp_streaming", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="JW Player v6 &amp; RTMP Protocol Examples">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-rtmp-streaming-section">' . "\n";
         echo '<h3>JW Player v6 &amp; RTMP Protocol Examples</h3>' . "\n";
         echo '<iframe width="560" height="315" src="https://www.youtube.com/embed/ZTopRQQAELw" frameborder="0" allowscriptaccess="always" allowfullscreen="true" style="float:right; margin:0 0 20px 20px; width:300px; height:200px;"></iframe>' . "\n";
         echo '<p>While it is possible to serve audio/video files protected by s2Member, without needing to integrate Amazon S3 or CloudFront; we DO highly recommend that you integrate both Amazon S3 and Amazon CloudFront in order to maximize speed and compatibility across various viewing platforms. That being said, there are code samples below that will serve audio/video files both with and without Amazon S3/CloudFront. You can also check the <a href="' . esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Forum URI")) . '" target="_blank" rel="external">s2Member Support Forums</a> for tips/tricks if you like.</p>' . "\n";
         echo '<p><strong>One of the great things about Amazon CloudFront</strong>, is its ability to <strong>stream/seek media files</strong> in the truest sense of the word. For sites delivering protected <em>FLV/MP4/OGG/WEBM</em> and other streaming audio/video file types over the <em>RTMP</em> protocol, Amazon CloudFront is our recommendation. Once you\'ve successfully configured s2Member to use both Amazon S3 and Amazon CloudFront together, please review the code samples below. s2Member can automatically serve your protected files over the <em>RTMP</em> protocol using an Amazon CloudFront Streaming Distribution.</p>' . "\n";
         echo '<p><strong>See also:</strong> This KB article: <a href="http://www.s2member.com/kb/jwplayer-s2stream-shortcodes/" target="_blank" rel="external">JW Player w/ <code>[s2Stream /]</code> Shortcodes</a>.</p>' . "\n";
         if (stripos(wp_get_theme(), 'infocus') !== FALSE) {
             echo '<p><strong>Note:</strong> It appears that you\'re using the inFocus WordPress theme. If you experience trouble with the shortcodes below, try wrapping the shortcode in <code>[raw][/raw]</code> tags (e.g., <code>[raw][s2Stream ... /][/raw]</code>).</p>' . "\n";
         }
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_rtmp_streaming", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3><code>[s2Stream /]</code> Video Shortcode Examples (recommended—it\'s the easiest way)</h3>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player (MP4 file, via Rewrite URLs. Amazon S3/CloudFront NOT required)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />Works with any audio/video file. This does NOT require s2Member to be integrated with Amazon S3/CloudFront.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-s2stream-mp4.x-php")) . '</p>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp\').toggle(); return false;" class="ws-dotted-link">JW Player (RTMP streaming MP4, via s2Member\'s Amazon S3/CloudFront integration)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />Streams with the RTMP protocol, plus there is a full download fallback of the MP4 source file if streaming is not possible on a particular device.<br />This requires s2Member to be integrated with Amazon S3/CloudFront.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-s2stream-mp4-rtmp.x-php")) . '</p>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp-only\').toggle(); return false;" class="ws-dotted-link">JW Player (RTMP streaming MP4 only, via s2Member\'s Amazon S3/CloudFront integration)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp-only" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />Streams with the RTMP protocol only, with no access to the source file, only to the RTMP stream.<br />This requires s2Member to be integrated with Amazon S3/CloudFront.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-s2stream-mp4-rtmp-only.x-php")) . '</p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3><code>[s2Stream /]</code> Audio Shortcode Examples (recommended—it\'s the easiest way)</h3>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3\').toggle(); return false;" class="ws-dotted-link">JW Player (MP3 file, via Rewrite URLs. Amazon S3/CloudFront NOT required)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />Works with any audio/video file. This does NOT require s2Member to be integrated with Amazon S3/CloudFront.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-s2stream-mp3.x-php")) . '</p>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp\').toggle(); return false;" class="ws-dotted-link">JW Player (RTMP streaming MP3, via s2Member\'s Amazon S3/CloudFront integration)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />Streams with the RTMP protocol, plus there is a full download fallback of the MP3 source file if streaming is not possible on a particular device.<br />This requires s2Member to be integrated with Amazon S3/CloudFront.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-s2stream-mp3-rtmp.x-php")) . '</p>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp-only\').toggle(); return false;" class="ws-dotted-link">JW Player (RTMP streaming MP3 only, via s2Member\'s Amazon S3/CloudFront integration)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp-only" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />Streams with the RTMP protocol only, with no access to the source file, only to the RTMP stream.<br />This requires s2Member to be integrated with Amazon S3/CloudFront.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-s2stream-mp3-rtmp-only.x-php")) . '</p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>PHP Code Examples (for more advanced integrations via PHP—in WordPress themes)</h3>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-standard-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player (MP4 file, via Rewrite URLs. Amazon S3/CloudFront NOT required)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-standard-mp4" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This does NOT require s2Member to be integrated with Amazon S3/CloudFront.<br />Also see: <strong>s2Member → Download Options → Advanced Mod Rewrite Linkage</strong>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-standard-mp4.x-php")) . '</p>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player (RTMP streaming MP4, via s2Member\'s Amazon S3/CloudFront integration)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon S3/CloudFront.<br />Also see: <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-summary/" target="_blank" rel="external">s2Member Codex → API Functions</a>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-streaming-mp4.x-php")) . '</p>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-sca\').toggle(); return false;" class="ws-dotted-link">JW Player (RTMP streaming MP4, via s2Member\'s JSON/Shortcode alternative)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-sca" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon S3/CloudFront.<br />Also see: <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-summary/" target="_blank" rel="external">s2Member Codex → API Functions</a>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-streaming-mp4-sca.x-php")) . '</p>' . "\n";
         echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-webm\').toggle(); return false;" class="ws-dotted-link">JW Player (RTMP streaming MP4, advanced w/ multiple fallbacks)</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-webm" style="display:none;">Download <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">JW Player here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon S3/CloudFront.<br />Also see: <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-summary/" target="_blank" rel="external">s2Member Codex → API Functions</a>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/jwplayer-streaming-mp4-webm.x-php")) . '</p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_rtmp_streaming", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_rewrite_linkage", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rewrite_linkage", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Advanced Mod-Rewrite Linkage">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-rewrite-linkage-section">' . "\n";
         echo '<h3>Advanced Mod-Rewrite Linkage</h3>' . "\n";
         echo '<p>s2Member automatically creates <code>mod_rewrite</code> rules inside your <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory, which provide additional flexibility in the way protected files can be served to your Customers. With s2Member\'s <code>mod_rewrite</code> rules, it is now possible to link directly to a protected file, avoiding the use of query string variables <em>(it\'s completely optional though, i.e., NOT required)</em>.</p>' . "\n";
         echo '<p>This new flexibility may come in handy for site owners serving files through media playback devices that have issues with query string variables. For instance, it is now possible to link to an s2Member-protected file directly, like this: <code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/example-file.zip</code> instead of <code>... /?s2member_file_download=example-file.zip</code>. Either way works, but the direct link might be easier for some.</p>' . "\n";
         echo '<p>It is also possible to pass query string parameters through a direct link:<br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/example-file.zip?s2member_file_inline=yes&amp;s2member_file_download_key=[key]</code>.</p>' . "\n";
         echo '<p>That being said, s2Member\'s <code>mod_rewrite</code> rules allow for more advanced control over s2Member-specific parameters.</p>' . "\n";
         echo '<p>For example, you could just do this for inline files:<br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline</strong>/example-file.zip</code></p>' . "\n";
         echo '<p>Or, if you really want to get advanced, you could do something like this:<br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline-[yes|no]/s2member-file-download-key-[key]</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline-yes/s2member-file-download-key-xS54df5ER4d5x</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline-yes/s2member-skip-confirmation</strong>/example-file.zip</code></p>' . "\n";
         echo '<p>Or even this, if you\'re using Remote Header Authorization:<br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-remote</strong>/example-file.zip</code></p>' . "\n";
         echo '<p>Specifying storage location option dynamically:<br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-storage-[local|s3|cf]</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-storage-cf</strong>/example-cloudfront-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-storage-s3/s2member-file-inline</strong>/example-s3-file.html</code></p>' . "\n";
         echo '<p><em>* Note, the order of your s2Member-specific parameters with Advanced Mod-Rewrite Linkage is irrelevant. Feel free to add/remove, or even change the order. Everything discussed here is also Multisite compatible. Everything discussed here is also compatible when/if combined with Amazon S3/CDN Storage. However, NONE of this will work on servers that do NOT support <code>mod_rewrite</code>. Almost all web servers do though.</em></p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_rewrite_linkage", get_defined_vars());
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_rewrite_linkage", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_shortcode_attrs", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_shortcode_attrs", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Shortcode Attributes &amp; API Functions (Explained)">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-shortcode-attrs-section">' . "\n";
         echo '<h3>Shortcode Attributes &amp; API Functions (Explained In Full Detail)</h3>' . "\n";
         echo '<p>s2Member makes <a href="http://s2member.com/r/shortcode-reference/" target="_blank" rel="external">Shortcodes</a> available to you, which allow you to generate File Download URLs and/or File Download Keys. Like most Shortcodes for WordPress, s2Member reads Attributes in your Shortcode. Many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h4 style="margin:0;"><code>[s2File /]</code> &amp; <code>[s2Stream /]</code> Shortcode Attributes:</h4>' . "\n";
         echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_url()" target="_blank" rel="external">s2member_file_download_url()</a> for PHP integration.</p>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr style="padding-top:0;">' . "\n";
         echo '<td style="padding-top:0;">' . "\n";
         echo '<ul class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>download="file.zip"</code> Location of the file, relative to the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory; or, relative to the root of your Amazon S3 Bucket, when applicable.</li>' . "\n";
         echo '<li><code>download_key="no"</code> Defaults to <code>no</code>. If <code>download_key="1|on|yes|true|ip-forever|universal"</code>, s2Member will return a URL with an s2Member-generated File Download Key. You don\'t need to generate the File Download Key yourself, s2Member does it for you. If you set <code>download_key="ip-forever"</code>, the File Download Key that s2Member generates will last forever, for a specific IP Address; otherwise, by default, all File Download Keys expire after 24 hours automatically. If you set <code>download_key="universal"</code>, s2Member will generate a File Download Key that is good for anyone/everyone forever, with NO restrictions on who/where/when a file is accessed <em>(i.e., be careful with this one)</em>.</li>' . "\n";
         echo '<li><code>stream="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. If <code>stream="1|on|yes|true"</code>, s2Member will return a URL containing a parameter/directive, which forces the File Download to take place over the RTMP protocol if at all possible. This ONLY works when/if s2Member is configured to run with both Amazon S3/CloudFront. Please note however, it\'s better to use the example code provided in the section above, regarding: <code>JW Player and the RTMP Protocol</code>. Also note, if <code>get_streamer_json="1|on|yes|true"</code>, s2Member will automatically force <code>stream="yes"</code> for you.</li>' . "\n";
         echo '<li><code>inline=""</code> Defaults to <code>[empty]</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. If <code>inline="1|on|yes|true"</code>, s2Member will serve the file inline, instead of as an actual File Download. If empty, s2Member will look at your <code>Inline File Extensions</code> configuration above, and serve the file inline; if, and only if, its extension matches one found in your configuration. By default, s2Member serves all files as attachments <em>(i.e., downloads)</em>, except in the case of the <code>[s2Stream /]</code> Shortcode where this defaults to <code>yes</code>. Please read the section above regarding <code>Inline File Extensions</code> for further details. Also note, this Shortcode Attribute does NOTHING for files served via Amazon CloudFront. See the tech-notes listed in the Amazon CloudFront section for further details and workarounds.</li>' . "\n";
         echo '<li><code>storage=""</code> Defaults to <code>[empty]</code>. If <code>storage="local|s3|cf"</code>, s2Member will serve the file from a specific source location, based on the value of this Shortcode Attribute. For example, if you\'ve configured Amazon S3 and/or CloudFront; but, there are a few files that you want to upload locally to the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory; you can force s2Member to serve a file from local storage by setting <code>storage="local"</code> explicitly.</li>' . "\n";
         echo '<li><code>remote="no"</code> Defaults to <code>no</code>. If <code>remote="1|on|yes|true"</code>, s2Member will authenticate access to the File Download via Remote Header Authorization, instead of through your web site. This is similar to <code>.htaccess</code> protection routines of yester-year</code>. Please check the <code>Remote Authorization and Podcasting</code> section for further details about how this works.</li>' . "\n";
         echo '<li><code>ssl=""</code> Defaults to <code>[empty]</code>. If <code>ssl="1|on|yes|true"</code>, s2Member will generate a File Download URL with an SSL protocol <em>(i.e., the URL will start with <code>https://</code> or <code>rtmpe://</code>)</em>. If empty, s2Member will only generate a File Download URL with an SSL protocol, when/if the Post/Page/URL firing the Shortcode itself, is also being viewed over SSL. Otherwise, s2Member will use a non-SSL protocol by default.</li>' . "\n";
         echo '<li><code>rewrite="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. If <code>rewrite="1|on|yes|true"</code>, s2Member will generate a File Download URL that takes full advantage of s2Member\'s Advanced Mod Rewrite functionality. If you\'re running an Apache web server, or another server that supports <code>mod_rewrite</code>, we highly recommend turning this on. s2Member\'s <code>mod_rewrite</code> URLs do NOT contain query string parameters, making them more portable/compatible with other software applications and/or plugins for WordPress. If you\'re integrating with JW Player, you MUST use <code>rewrite="yes"</code>.</li>' . "\n";
         echo '<li><code>rewrite_base=""</code> Defaults to <code>[empty]</code>. If <code>rewrite_base="' . esc_attr(site_url("/")) . '"</code>, s2Member will generate a File Download URL that takes full advantage of s2Member\'s Advanced Mod Rewrite functionality, and it will use the rewrite base URL as a prefix. This could be useful on some WordPress installations that use advanced directory structures. It could also be useful for site owners using virtual directories that point to <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code>. Note, if <code>rewrite_base</code> is set, s2Member will automatically force <code>rewrite="yes"</code> for you.</li>' . "\n";
         echo '<li><code>skip_confirmation="no"</code> Defaults to <code>no</code>. If <code>skip_confirmation="1|on|yes|true"</code>, s2Member will generate a File Download URL which contains a directive, telling s2Member NOT to introduce any JavaScript confirmation prompts on your site, for this File Download URL. Please note, s2Member will automatically detect links, anywhere in your content, and/or anywhere in your theme files, that contain <code>s2member_file_download</code> or <code>s2member-files</code>. Whenever a logged-in Member clicks a link that contains <code>s2member_file_download</code> or <code>s2member-files</code>, the system will politely ask the User to confirm the download using a very intuitive JavaScript confirmation prompt, which contains specific details about your configured download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not.</li>' . "\n";
         echo '<li><code>url_to_storage_source="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. If <code>url_to_storage_source="1|on|yes|true"</code>, s2Member will generate a File Download URL which points directly to the storage source. This is only functional with Amazon S3 and/or CloudFront integrations. If you create a URL that points directly to the storage source <em>(i.e., points directly to Amazon S3 or CloudFront)</em>, s2Member will NOT be able to further authenticate the current User/Member; and, s2Member will NOT be able to count the File Download against the current User\'s account record, because the URL being generated does not pass back through s2Member at all, it points directly to the storage source. For this reason, if you set <code>url_to_storage_source="true"</code>, you should also set <code>check_user="******"</code> and <code>count_against_user="******"</code>, telling s2Member to authenticate the current User, and if authenticated, count this File Download URL against the current User\'s account record in real-time <em>(i.e., as the URL is being generated) </em>, while it still has a chance to do so. This Shortcode Attribute is useful when you stream files over the RTMP protocol; where an <code>http://</code> URL is not feasible. It also helps in situations where a 3rd-party software application will not work as intended, with s2Member\'s internal redirection to Amazon S3/CloudFront files. Important, when <code>check_user="******"</code> and/or <code>count_against_user="******"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>' . "\n";
         echo '<li><code>count_against_user="******"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. If <code>count_against_user="******"</code>, it will automatically force <code>check_user="******"</code> as well. In other words, s2Member will authenticate the current User, and if authenticated, count this File Download URL against the current User\'s account record in real-time <em>(i.e., as the URL is being generated) </em>. This is off by default with the <code>[s2File /]</code> Shortcode. By default, s2Member will simply generate a File Download URL, and upon a User/Member clicking the URL, s2Member will authenticate the User/Member at that time, count the File Download against their account record, and serve the File Download. In other words, under normal circumstances, there is no reason to set <code>check_user="******"</code> and/or <code>count_against_user="******"</code> when generating the URL itself. However, this is a useful Shortcode Attribute when <code>url_to_storage_source="true"</code>. Please note, when <code>check_user="******"</code> and/or <code>count_against_user="******"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>' . "\n";
         echo '<li><code>check_user="******"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. If <code>check_user="******"</code>, s2Member will authenticate the current User before allowing the File Download URL to be generated. This is off by default with the <code>[s2File /]</code> Shortcode. By default, s2Member will simply generate a File Download URL, and upon a User/Member clicking the URL, s2Member will authenticate the User/Member at that time, and serve the File Download to the User/Member. In other words, under normal circumstances, there is no reason to set <code>check_user="******"</code> and/or <code>count_against_user="******"</code> when generating the URL itself. However, this IS a useful Shortcode Attribute when <code>url_to_storage_source="true"</code>. Please note, when <code>check_user="******"</code> and/or <code>count_against_user="******"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>' . "\n";
         echo '<li><code>get_streamer_json="no"</code> Defaults to <code>no</code>. N/A with <code>[s2Stream /]</code> Shortcode. If <code>get_streamer_json="1|on|yes|true"</code>, the <code>[s2File /]</code> Shortcode will return a JSON object for JavaScript notation, making it possible to integrate the <code>[s2File /]</code> Shortcode into JavaScript routines that configure streaming media players. For further details, please review the section above: <code>JW Player &amp; RTMP Protocol Examples</code>. Note, if you set <code>get_streamer_json="true"</code>, s2Member will automatically force <code>url_to_storage_source="true"</code> and <code>stream="true"</code>. For that reason, you should carefully review the details and warning above regarding <code>url_to_storage_source</code>. If you set <code>get_streamer_json="true"</code>, you should also set <code>check_user="******"</code> and <code>count_against_user="******"</code>.</li>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2file_lis", get_defined_vars());
         echo '</ul>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h4 style="margin:0;">Additional <code>[s2Stream /]</code> Shortcode Attributes:</h4>' . "\n";
         echo '<p style="margin:0;"><strong>See also:</strong> This KB article: <a href="http://www.s2member.com/kb/jwplayer-s2stream-shortcodes/" target="_blank" rel="external">JW Player w/ <code>[s2Stream /]</code> Shortcodes</a>.</p>' . "\n";
         echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_url()" target="_blank" rel="external">s2member_file_download_url()</a> for PHP integration.</p>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr style="padding-top:0;">' . "\n";
         echo '<td style="padding-top:0;">' . "\n";
         echo '<ul class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>file_download="video.mp4"</code> Location of the audio/video file, relative to the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory; or, relative to the root of your Amazon S3 Bucket, when applicable.</li>' . "\n";
         echo '<li><code>player="jwplayer-v6-rtmp"</code> Required. Current supported players in this Shortcode include: <code>jwplayer-v6</code> (works with any audio/video file, and you do NOT need to have Amazon  S3 or CloudFront integrated for this to work), <code>jwplayer-v6-rtmp</code> (streams with the RTMP protocol, plus there is a full download fallback of the source file if streaming is not possible on a particular device; this requires both Amazon S3 and CloudFront integration), <code>jwplayer-v6-rtmp-only</code> (streams with the RTMP protocol only, with no access to the source file, only to the RTMP stream; this requires both Amazon S3 and CloudFront integration).</li>' . "\n";
         echo '<li><code>player_id=""</code> Optional. HTML div ID for the audio/video player. Defaults to a unique ID generated by s2Member for each instance of your Shortcode.</li>' . "\n";
         echo '<li><code>player_path="/jwplayer/jwplayer.js"</code> Required. Path to the player\'s JavaScript file (ex: <code>/jwplayer/jwplayer.js</code>—you should upload the <a href="http://www.s2member.com/r/jw-player-download/" target="_blank" rel="external">/jwplayer</a> folder to the root of your web directory).</li>' . "\n";
         echo '<li><code>player_resolutions=""</code> Optional (requires s2Member Pro). This is a comma-delimited list of all available resolution options (should you decide to offer more than just one file download at a single resolution). Please review the full list of Shortcode Attributes (i.e., click the "Shortcode Attributes (Explained)" tab) in <a href="http://www.s2member.com/kb/jwplayer-s2stream-shortcodes/#using-s2stream-shortcodes" target="_blank" rel="external">this KB article</a> for further details, requirements, and an example of use.</li>' . "\n";
         echo '<li><code>player_{setting}=""</code> Optional. Any additional configuration attributes supported by your audio/video player, prefixed with <code>player_</code>. For JW Player v6, see <a href="http://www.s2member.com/r/jw-player-config-options/" target="_blank" rel="external">this article please</a>. Examples: <code>player_width="480"</code>, <code>player_height="270"</code>, <code>player_title="My Video"</code>, <code>player_description="A video about something."</code>, <code>player_image="http://www.example.com/wp-content/uploads/video-preview.jpg"</code>, <code>player_mediaid="video_ei0wsx23"</code>, <code>player_autostart="true"</code>, <code>player_skin="/jwplayer/my-skin.xml"</code>, <code>player_key="my-license-key"</code>, <code>player_captions="{file:\'/assets/captions-en.vtt\',label:\'English\'}"</code> (<em>With <a href="http://www.s2member.com/r/jw-player-video-captions/" target="_blank" rel="external">Captions</a>, you can exclude the square array brackets to avoid Shortcode parsing issues. s2Member will automatically wrap your Caption objects with square array brackets.</em>). Please note that "Advanced Options Blocks" listed on <a href="http://www.s2member.com/r/jw-player-config-options/" target="_blank" rel="external">this page</a> are NOT supported here. For those, please use: <code>player_option_blocks=""</code> (see below).</li>' . "\n";
         echo '<li><code>player_option_blocks=""</code> Optional. Any "Advanced Option Blocks" supported by your audio/video player. For JW Player v6, see <a href="http://www.s2member.com/r/jw-player-config-options/" target="_blank" rel="external">this article please</a>. Here are some examples: <code>player_option_blocks="sharing:{}"</code>, <code>player_option_blocks="sharing:{}, logo: {file: \'/logo.png\', link: \'http://example.com\'}"</code>. Or: <code>player_option_blocks="c2hhcmluZzoge30="</code> (base64 encoded version of <code>sharing:{}</code>). Please note that "Advanced Options Blocks" can be defined in plain text or with a <a href="http://s2member.com/r/base64-encoding/" target="_blank" rel="external">base64 encoded string</a>. Advanced Option Blocks are JavaScript objects with properties. If you have trouble defining JavaScript object properties inside a Shortcode Attribute, please use <a href="http://s2member.com/r/base64-encoding/" target="_blank" rel="external">this tool</a> to base64 encode your Advanced Option Blocks, so that you end up with a string that\'s compatible with Shortcode Attributes.</li>' . "\n";
         echo '<li>Please check the <strong>Shortcode Attributes</strong> Tab in <a href="http://www.s2member.com/kb/jwplayer-s2stream-shortcodes/#using-s2stream-shortcodes" target="_blank" rel="external">this KB article</a> for further details on everything here.</li>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2stream_lis", get_defined_vars());
         echo '</ul>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h4 style="margin:0;"><code>[s2Key /]</code> Shortcode Attributes:</h4>' . "\n";
         echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_key()" target="_blank" rel="external">s2member_file_download_key()</a> for PHP integration.</p>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr style="padding-top:0;">' . "\n";
         echo '<td style="padding-top:0;">' . "\n";
         echo '<ul class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>file_download="file.zip"</code> Location of the file, relative to the <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory; or, relative to the root of your Amazon S3 Bucket, when applicable.</li>' . "\n";
         echo '<li><code>directive=""</code> Defaults to <code>[empty]</code>. If <code>directive="ip-forever|universal"</code>, s2Member will return a special File Download Key. If you set <code>directive="ip-forever"</code>, the File Download Key that s2Member generates will last forever, for a specific IP Address; otherwise, by default, all File Download Keys expire after 24 hours automatically. If you set <code>directive="universal"</code>, s2Member will generate a File Download Key that is good for anyone/everyone forever, with NO restrictions on who/where/when a file is accessed <em>(be careful with this one)</em>.</li>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2key_lis", get_defined_vars());
         echo '</ul>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_shortcode_attrs", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_gzip_conflicts", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_gzip_conflicts", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Preventing GZIP Conflicts On Server">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-gzip-conflicts-section">' . "\n";
         echo '<h3>Preventing GZIP Conflicts On Server (Instructions)</h3>' . "\n";
         echo '<p>Protected files served by s2Member through PHP scripts, are already compressed. Therefore, <a href="http://s2member.com/r/gzip-compression-explained/" target="_blank" rel="nofollow external xlink">GZIP compression</a> is not needed during protected file delivery. Some web servers (i.e., Apache, LiteSpeed, and similar) include GZIP compression rules through server-side extensions, like <code>mod_deflate</code> for example. While s2Member encourages the use of extensions like <code>mod_deflate</code>, it is best to disable GZIP automatically (i.e., temporarily) during s2Member\'s delivery of a protected file through a PHP script. This avoids conflicts on the server which might otherwise lead to corrupted file downloads. s2Member makes a valiant effort to accomplish this via PHP, all on its own. However, it never hurts to add this section of code to the root <code>.htaccess</code> file for your WordPress installation. Optional, but highly recommended.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_gzip_conflicts", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p style="margin:0; font-weight:bold;">s2Member automatically adds this to your <code>.htaccess</code> file upon activation of the plugin.</p>' . "\n";
         echo '<p style="margin:0;">The following <code>mod_rewrite</code> rule goes inside this file: <code>' . esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path(ABSPATH . ".htaccess")) . '</code></p>' . "\n";
         echo '<pre class="code"><code>' . esc_html(trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_no_gzip_htaccess"])))) . '</code></pre>';
         echo '<p><strong>* Tip:</strong> this covers all types of integration with s2Member File Downloads, even if you\'re using s2Member\'s Advanced Mod Rewrite Linkage.</p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-file-download-content-encodong-none">' . "\n";
         echo 'Also Force a <code>Content-Encoding: none</code> Header?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_file_download_content_encodong_none" id="ws-plugin--s2member-file-download-content-encodong-none">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_content_encodong_none"] ? ' selected="selected"' : '') . '>No (remain standards-compliant; I will configure my server properly)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_content_encodong_none"] ? ' selected="selected"' : '') . '>Yes (my web server is stubborn; downloads are corrupted without this)</option>' . "\n";
         echo '</select>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<p><code>Content-Encoding: none</code> can be forced by s2Member in order to workaround stubborn web server configurations. However, please note that <code>Content-Encoding: none</code> is an invalid header (NOT standards compliant), so don\'t enable this unless you absolutely need to. For instance, if files downloaded via s2Member are always corrupt, you could enable this to workaround the issue. The issue being... that your web server is ignoring all of s2Member\'s attempts to serve a file without Content-Encoding. While <code>Content-Encoding: none</code> is indeed a hack, it\'s a relatively common hack that most modern browsers will understand just fine; making this a viable solution when/if necessary.</p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_gzip_conflicts", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_custom_capability_files", !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site(), get_defined_vars())) {
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_custom_capability_files", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Custom Capability &amp; Member Level Files">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-custom-capability-files-section">' . "\n";
         echo '<h3>Restricting Files, Based On Custom Capabilities</h3>' . "\n";
         echo '<p>If you\'re NOT familiar with Custom Capabilities yet, please read: <strong>Dashboard → s2Member → API Scripting → Custom Capability Packages</strong>. Once you understand the basic concept of Custom Capabilities &amp; Protected File Downloads, you\'ll see that (by default) s2Member does NOT handle File Download Protection with respect to Custom Capabilities. That\'s where Custom Capability Sub-directories come in.</p>' . "\n";
         echo '<p>You can create Custom Capability Sub-directories under: <code>' . esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '</code>. For instance, if you have a Custom Capability <code>music</code>, you can place protected files that should ONLY be accessible to Members with <code>access_s2member_ccap_music</code>, inside: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-ccap-music/</code>. Some examples are provided below.</p>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_custom_capability_files", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><strong>Custom Capabilities:</strong> (music,videos)</p>' . "\n";
         echo '<p>Sub-Directory: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-ccap-music</code><br />Sub-Directory: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-ccap-videos</code></p>' . "\n";
         echo '<p>Protected File: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-ccap-music/file.mp3</code><br />Protected File: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-ccap-videos/file.avi</code></p>' . "\n";
         echo '<p>Now, here are some link examples, using Custom Capability Sub-directories:</p>' . "\n";
         echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/ccap-file-downloads.x-php")) . '</p>' . "\n";
         echo '<p><em>These links will ONLY work for Members who are logged-in, with the proper Capabilities.</em></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><strong>Membership Levels:</strong> (this also works fine)</p>' . "\n";
         echo '<p>Sub-Directory: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level0</code><br />Sub-Directory: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level1</code><br />Sub-Directory: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level2</code><br />Sub-Directory: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level3</code><br />Sub-Directory: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level4</code></p>' . "\n";
         echo '<p>Protected File: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level0/tiger.doc</code><br />Protected File: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level1/zebra.pdf</code><br />Protected File: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level2/elephant.doc</code><br />Protected File: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level3/rhino.pdf</code><br />Protected File: <code>/' . esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/access-s2member-level4/lion.doc</code></p>' . "\n";
         echo '<p>Now, here are some link examples, using Member Level Sub-directories:</p>' . "\n";
         echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/level-file-downloads.x-php")) . '</p>' . "\n";
         echo '<p><em>These links will ONLY work for Members who are logged-in, with an adequate Membership Level.</em></p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_custom_capability_files", get_defined_vars());
     }
     do_action("ws_plugin__s2member_during_down_ops_page_after_left_sections", get_defined_vars());
     echo '<p class="submit"><input type="submit" value="Save All Changes" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
 }
Пример #19
0
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     echo '<div class="ws-menu-page-toolbox">' . "\n";
     c_ws_plugin__s2member_menu_pages_tb::display();
     echo '</div>' . "\n";
     echo '<h2>General Options</h2>' . "\n";
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
     echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr(wp_create_nonce("ws-plugin--s2member-options-save")) . '" />' . "\n";
     echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
     do_action("ws_plugin__s2member_during_gen_ops_page_before_left_sections", get_defined_vars());
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_uninstall", !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() || is_super_admin(), get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_uninstall", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Plugin Deletion Safeguards"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_uninstall_routines"] ? ' default-state="open"' : '') . '>' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-uninstall-section">' . "\n";
         echo '<h3>Plugin Deletion Safeguards (highly recommended)</h3>' . "\n";
         echo '<p>By default, s2Member will retain all of it\'s Roles, Capabilities, and your Configuration Options when/if you delete s2Member from the Plugins Menu in WordPress. However, if you would like for s2Member to erase itself completely, please choose: <code>No (upon deletion, erase all data/options)</code>.</p>';
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_uninstall", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-run-uninstall-routines">' . "\n";
         echo 'Safeguard s2Member Data/Options?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_run_uninstall_routines" id="ws-plugin--s2member-run-uninstall-routines">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_uninstall_routines"] ? ' selected="selected"' : '') . '>Yes (safeguard all data/options)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_uninstall_routines"] ? ' selected="selected"' : '') . '>No (upon deletion, erase all data/options)</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'Recommended setting: (<code>Yes, safeguard all data/options</code>)' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_uninstall", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_security", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_security", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Security Encryption Key">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-security-section">' . "\n";
         echo '<img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member (a Membership management system for WordPress)" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
         echo '<h3>Security Encryption Key (optional, for tighter security)</h3>' . "\n";
         echo '<p>Just like WordPress, s2Member is open-source software. Which is wonderful. However, this also makes it possible for anyone to grab a copy of the software, and try to learn their way around its security measures. In order to keep your installation of s2Member unique/secure, you should configure a Security Encryption Key. s2Member will use your Security Encryption Key to protect itself against hackers. It does this by encrypting all sensitive information with your Key. A Security Encryption Key is unique to your installation.</p>' . "\n";
         echo '<p>Once you configure this, you do NOT want to change it; not ever. In fact, it is a VERY good idea to keep this backed up in a safe place, just in case you need to move your site, or re-install s2Member in the future. Some of the sensitive data that s2Member stores, will be encrypted with this Key. If you change it, that data can no longer be read, even by s2Member itself. In other words, don\'t use s2Member for six months, then decide to change your Key. That would break your installation.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_security", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-sec-encryption-key">' . "\n";
         echo 'Security Encryption Key (at least 60 chars)' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key"] ? ' <a href="#" onclick="ws_plugin__s2member_enableSecurityKey(); return false;" title="(not recommended)">edit key</a>' : ' <a href="#" onclick="ws_plugin__s2member_generateSecurityKey(); return false;" title="Insert an auto-generated Key. (recommended)">auto-generate</a>') . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" maxlength="256" autocomplete="off" name="ws_plugin__s2member_sec_encryption_key" id="ws-plugin--s2member-sec-encryption-key" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key"]) . '"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key"] ? ' disabled="disabled"' : '') . ' />' . "\n";
         echo !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key"] ? '<br />This may contain letters, numbers, spaces; even punctuation. Up to 256 characters.<br /><em>Ex: <code>' . esc_html(strtoupper(c_ws_plugin__s2member_utils_strings::random_str_gen(64))) . '</code></em>' . "\n" : '';
         echo count($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"]) > 1 ? '<br /><a href="#" onclick="ws_plugin__s2member_securityKeyHistory(); return false;">Click here</a> for a history of your last 10 Encryption Keys.<div id="ws-plugin--s2member-sec-encryption-key-history" style="display:none;"><code>' . implode('</code><br /><code>', $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"]) . '</code></div>' . "\n" : '';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Additional Details Regarding this Key:</h3>' . "\n";
         echo '<p>Your Security Encryption Key is used throughout s2Member\'s source code for many different things. However, MOST (not all, but most) uses of this Key are related to transactional processing within a particular session; so changing the Key won\'t really impact these scenarios in any significant way. Your Security Encryption Key is simply there to enhance security of data that is being transmitted in these cases.</p>' . "\n";
         echo '<p>That said, there are a few scenarios where use of your Security Encryption Key is more long-term. These include: Specific Post/Page Access Links, Registration Access Links, and it can also have a long-term impact on IPN communication because some data analyzed by s2Member includes a checksum that depends on your Key. If the Key changes, it could cause future IPN data (i.e. data from your payment gateway) to fail validation.</p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_security", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_localhost_info", !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() || is_super_admin(), get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_localhost_info", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Localhost WAMP/MAMP Developers">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-localhost-info-section">' . "\n";
         echo '<h3>Localhost WAMP/MAMP Installs (are you a developer?)</h3>' . "\n";
         echo '<p>If you\'re developing your site in a <code>localhost</code> environment, running something like WAMP/MAMP, or <a href="http://www.easyphp.org/" target="_blank" rel="external">EasyPHP</a>, please add this line to your <code>/wp-config.php</code> file: <code><span style="color:#0000BB;">define</span><span style="color:#007700;">(</span><span style="color:#DD0000;">"LOCALHOST"</span>, <span style="color:#0000BB;">true</span><span style="color:#007700;">);</span></code>.</p>' . "\n";
         echo '<p>This lets s2Member know definitively that your site is in a <code>localhost</code> environment. s2Member will adjust itself accordingly, maximizing functionality during your developement. s2Member can usually auto-detect this, but in cases where your <code>localhost</code> installation runs on something other than <code>127.0.0.1/localhost</code>, you need to tell s2Member definitively, by adding that line to your <code>/wp-config.php</code> file. For instance, s2Member needs to know when your server IP is the same as all User IPs.</p>' . "\n";
         echo '<p><em>Once your site goes live, please remove the line. If you\'re already on a live server connected to the web, please ignore this section.</em></p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_localhost_info", get_defined_vars());
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_localhost_info", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_lazy_load", !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() || is_super_admin(), get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_lazy_load", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="CSS/JS Lazy Loading">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-lazy-load-section">' . "\n";
         echo '<h3>CSS/JS Lazy Loading (Client-Side Libraries)</h3>' . "\n";
         echo '<p>By default, s2Member will load it\'s CSS/JS libraries on every page of your site. However, you may wish to enable lazy-loading here (e.g. only load when absolutely necessary).</p>' . "\n";
         echo '<p><em><strong>Tip:</strong> Do you need s2Member\'s CSS/JS on every page? If not, you can turn lazy-loading on. If you need s2Member\'s CSS/JS on a given Post/Page, you can insert an HTML comment into the Post/Page content like this: <code>&lt;!--s2member--&gt;</code>. If a Post/Page contains the word <code>s2member</code> or an <code>[s2*</code> Shortcode, this will automatically trigger s2Member\'s lazy-load routine (no matter what you configure here). Thus, it\'s an easy way to force s2Member to load it\'s CSS/JS on specific Posts/Pages where you deem this necessary. There is also a WordPress filter available: <code>add_filter("ws_plugin__s2member_lazy_load_css_js", "__return_true");</code> for developers; this could be incorporated into more dynamic scenarios.</em></p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_lazy_load", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-lazy-load-css-js">' . "\n";
         echo 'Lazy-Load s2Member\'s CSS/JS Libraries?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_lazy_load_css_js" id="ws-plugin--s2member-lazy-load-css-js">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["lazy_load_css_js"] ? ' selected="selected"' : '') . '>No (always load the CSS/JS libraries; e.g. on every page of the site)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["lazy_load_css_js"] ? ' selected="selected"' : '') . '>Yes (lazy-load CSS/JS libraries; e.g. load only when absolutely necessary)</option>' . "\n";
         echo '</select>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_lazy_load", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_s_badge_wp_footer_code", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_s_badge_wp_footer_code", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="s2Member Security Badge">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-s-badge-wp-footer-code-section">' . "\n";
         echo '<h3>Security Badge &amp; Footer Configuration (optional)</h3>' . "\n";
         echo '<div class="ws-menu-page-right">' . c_ws_plugin__s2member_utilities::s_badge_gen("1", TRUE, TRUE) . '</div>' . "\n";
         echo '<p>An s2Member Security Badge <em>(optional)</em>, can be used to express your site\'s concern for security; demonstrating to all Users/Members that your site <em>(and the s2Member software)</em>, takes security seriously. However, in order to qualify your site, you MUST generate a Security Encryption Key <em>(previous section)</em>, and then click "Save All Changes". Only then, will s2Member officially verify your installation <em>(verification occurs automatically)</em>.</p>' . "\n";
         echo '<p>Once you\'ve <a href="http://www.s2member.com/kb/security-badges/" target="_blank" rel="external">properly configured all security aspects of s2Member</a>, your s2Member Security Badge will be verified. To see the "verified" version of your Security Badge, you might need to refresh your browser after saving all changes <em>(i.e. after you create a Security Encryption Key)</em>. Also, s2Member will NOT "verify" your site if you turn off Unique IP Restrictions, Brute Force Login Protection, or if your <code>/wp-config.php</code> file lacks <a href="http://codex.wordpress.org/Editing_wp-config.php#Security_Keys" target="_blank" rel="external">Security Keys</a> <em>(each at least 60 chars in length)</em>. In addition, it\'s NOT possible for s2Member to verify your Security Badge, if your site is in a <code>localhost</code> environment; i.e. not connected to the web.</p>' . "\n";
         echo '<p><strong>How does s2Member know when my site is secure?</strong><br />If enabled below, an API call for "Security Badge Status", will allow web service connections to determine your status. Clicking <a href="' . esc_attr(site_url("/?s2member_s_badge_status=1")) . '" target="_blank" rel="external">this link</a> will report <code>1</code> <em>(secure)</em>, <code>0</code> <em>(at risk)</em>, or <code>-</code> <em>(API disabled)</em>. Once all security considerations are satisfied, s2Member will report <code>1</code> <em>(secure)</em> for your installation. *Note, this simple API will NOT, and should not, report any other information. It will ONLY report the current status of your Security Badge, as determined by your installation of s2Member. When/if you install the s2Member Security Badge, s2Member will make a connection to your site "once per day", to test your status.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_s_badge_wp_footer_code", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-s-badge-status-enabled">' . "\n";
         echo 'Enable Security Badge Status API?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_s_badge_status_enabled" id="ws-plugin--s2member-s-badge-status-enabled">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["s_badge_status_enabled"] ? ' selected="selected"' : '') . '>No (default, Badge Status API is disabled)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["s_badge_status_enabled"] ? ' selected="selected"' : '') . '>Yes (enable Badge Status API for verification)</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'This must be enabled if you want s2Member to verify your Security Badge.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-wp-footer-code">' . "\n";
         echo 'Customize WordPress Footer:<br />' . "\n";
         echo '<small>[ <a href="#" onclick="this.$code = jQuery(\'textarea#ws-plugin--s2member-wp-footer-code\'); this.$code.val(jQuery.trim(unescape(\'' . rawurlencode('[s2Member-Security-Badge v="1" /]') . '\')+\'\\n\'+this.$code.val())); return false;">Click HERE to insert your Security Badge</a> ],<br />or use Shortcode <code>[s2Member-Security-Badge v="1" /]</code> in a Post/Page/Widget.<br />The <code>v="1"</code> attribute is a Security Badge style/variation. Try variations <code>1|2|3</code>.</small>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<textarea name="ws_plugin__s2member_wp_footer_code" id="ws-plugin--s2member-wp-footer-code" rows="8" wrap="off" spellcheck="false" class="monospace">' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["wp_footer_code"]) . '</textarea><br />' . "\n";
         echo 'Any valid XHTML / JavaScript' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' (or even PHP)') . ' code will work just fine here.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_s_badge_wp_footer_code", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_email_config", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_email_config", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Email Configuration">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-email-section">' . "\n";
         echo '<h3 style="margin:0;">Email From: ' . esc_html('"Name" <address>') . '</h3>' . "\n";
         echo '<p style="margin:0;">This is the name/address that will appear in outgoing email notifications sent by the s2Member plugin.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_email_from_name_config", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-reg-email-from-name">' . "\n";
         echo 'Email From Name:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_reg_email_from_name" id="ws-plugin--s2member-reg-email-from-name" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . '" /><br />' . "\n";
         echo 'We recommend that you use the name of your site here.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-reg-email-from-email">' . "\n";
         echo 'Email From Address:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_reg_email_from_email" id="ws-plugin--s2member-reg-email-from-email" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]) . '" /><br />' . "\n";
         echo 'Example: support@your-domain.com. <em class="ws-menu-page-hilite">Please read <a href="#" onclick="alert(\'Running WordPress with an SMTP mail plugin?\\n\\nPlease be advised. If you run an SMTP mail plugin with WordPress, be sure to configure s2Member with a valid `From:` address (i.e. one matching your SMTP configuration perhaps). Most free SMTP servers, such as Gmail and Yahoo, require that your `From:` header match the email address associated with your account. Please check with your SMTP service provider before attempting to configure plugins like s2Member to use a different `From:` address when sending email messages.\'); return false;">this IMPORTANT note</a></em>.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-reg-email-support-link">' . "\n";
         echo 'Email Support/Contact Link:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_reg_email_support_link" id="ws-plugin--s2member-reg-email-support-link" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_support_link"]) . '" /><br />' . "\n";
         echo 'Ex: <code>mailto:support@your-domain.com</code> (<em>mailto link</em>).<br />' . "\n";
         echo 'Or: <code>' . esc_html(site_url("/contact-us/")) . '</code>.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3 style="margin:0;">New User Email Configuration</h3>' . "\n";
         echo '<input type="hidden" id="ws-plugin--s2member-pluggables-wp-new-user-notification" value="' . esc_attr(empty($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["pluggables"]["wp_new_user_notification"]) ? '0' : '1') . '" />' . "\n";
         echo empty($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["pluggables"]["wp_new_user_notification"]) ? '<p class="ws-menu-page-error" style="margin:0;"><em><strong>Conflict warning:</strong> You have another theme or plugin installed that is preventing s2Member from controlling this aspect of your installation. When the pluggable function <code><a href="http://codex.wordpress.org/Function_Reference/wp_new_user_notification" target="_blank" rel="external">wp_new_user_notification()</a></code> is handled by another plugin, it\'s not possible for s2Member to allow customization of New User Emails. This is NOT a major issue. In fact, in some cases, it might be desirable. That being said, if you DO want to use s2Member\'s customization of New User Emails, you will need to deactivate one plugin at a time until this conflict warning goes away.</em></p>' . "\n" : '';
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_new_user_emails", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_new_user_emails_enabled" id="ws-plugin--s2member-new-user-emails-enabled">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["new_user_emails_enabled"] ? ' selected="selected"' : '') . '>No (default, use WordPress defaults)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["new_user_emails_enabled"] ? ' selected="selected"' : '') . '>Yes (customize New User Emails with s2Member)</option>' . "\n";
         echo '</select>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div id="ws-plugin--s2member-new-user-emails">' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3 style="margin:0;">New User Email Message (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-new-user-email-details\').toggle(); return false;" class="ws-dotted-link">click to customize</a>)</h3>' . "\n";
         echo '<p style="margin:0;">This email is sent to all new Users/Members. It should always contain their Username/Password. In addition to this email, s2Member will also send new paying Customers a Signup Confirmation Email, which you can customize from your Dashboard, under: <code>s2Member -› PayPal Options</code>. You may wish to customize these emails further, by providing details that are specifically geared to your site.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_new_user_email", get_defined_vars());
         echo '<div id="ws-plugin--s2member-new-user-email-details" style="display:none;">' . "\n";
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<p><em><strong>BuddyPress:</strong> please note that BuddyPress does NOT send this email to Users that register through the BuddyPress registration system. This is because BuddyPress sends each User an activation link; eliminating the need for this email all together. However, you CAN still customize s2Member\'s separate email to paying Members. See: <code>s2Member -› PayPal Options -› Signup Confirmation Email</code>.</em></p>' . "\n" : '';
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-new-user-email-subject">' . "\n";
         echo 'New User Email Subject:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_new_user_email_subject" id="ws-plugin--s2member-new-user-email-subject" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["new_user_email_subject"]) . '" /><br />' . "\n";
         echo 'Subject Line used in the email sent to new Users/Members.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-new-user-email-message">' . "\n";
         echo 'New User Email Message:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<textarea name="ws_plugin__s2member_new_user_email_message" id="ws-plugin--s2member-new-user-email-message" rows="10">' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["new_user_email_message"]) . '</textarea><br />' . "\n";
         echo 'Message Body used in the email sent to new Users/Members.<br /><br />' . "\n";
         echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
         echo '<ul>' . "\n";
         echo '<li><code>%%role%%</code> = The Role ID <code>(subscriber, s2member_level[0-9]+, administrator, editor, author, contributor)</code>.</li>' . "\n";
         echo '<li><code>%%label%%</code> = The Role ID Label <code>(Subscriber, s2Member Level 1, s2Member Level 2; or your own custom Labels — if configured)</code>.</li>' . "\n";
         echo '<li><code>%%level%%</code> = The Level number <code>(0, 1, 2, 3, 4)</code>. (<em>deprecated, no longer recommended; use <code>%%role%%</code></em>)</li>' . "\n";
         echo '<li><code>%%ccaps%%</code> = Custom Capabilities. Ex: <code>music,videos,free_gift</code> (<em>in comma-delimited format</em>).</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name (First &amp; Last) of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username the Member selected during registration.</li>' . "\n";
         echo '<li><code>%%user_pass%%</code> = The Password selected or generated during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The User\'s IP Address, detected via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress User ID generated during registration.</li>' . "\n";
         echo '<li><code>%%wp_login_url%%</code> = The full URL where Users can get logged into your site.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Registration/Profile Fields are also supported in this email:</strong>' . "\n";
         echo '<ul>' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -› General Options -› Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul>' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>(The campaign (i.e. christmas-promo) could be referenced using <code>%%cv1%%</code>)</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<div class="ws-menu-page-hr"></div>' . "\n" . '<p style="margin:0;"><strong>PHP Code:</strong> It is also possible to use PHP tags — optional (for developers). If you use PHP tags, please run a test email with <code>&lt;?php print_r(get_defined_vars()); ?&gt;</code>. This will give you a full list of all PHP variables available to you in this email. The <code>$user</code> variable is the most important one. It\'s an instance of the <a href="http://codex.wordpress.org/Class_Reference/WP_User" target="_blank" rel="external"><code>WP_User</code></a> class (e.g. <code>$user->ID</code>, <code>$user->has_cap()</code>, etc). Please note that all Replacement Codes will be parsed first, and then any PHP tags that you\'ve included. Also, please remember that emails are sent in plain text format.</p>' . "\n" : '';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3 style="margin:0;">Administrative: New User Notification (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-new-user-admin-email-details\').toggle(); return false;" class="ws-dotted-link">click to customize</a>)</h3>' . "\n";
         echo '<p style="margin:0;">This email notification is sent to you, each time a new User/Member registers.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_new_user_admin_email", get_defined_vars());
         echo '<div id="ws-plugin--s2member-new-user-admin-email-details" style="display:none;">' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-new-user-admin-email-recipients">' . "\n";
         echo 'New User Notification Recipients:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_new_user_admin_email_recipients" id="ws-plugin--s2member-new-user-admin-email-recipients" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["new_user_admin_email_recipients"]) . '" /><br />' . "\n";
         echo 'This is a semicolon ( ; ) delimited list of Recipients. Here is an example:<br />' . "\n";
         echo '<code>"Name" &lt;user@example.com&gt;; admin@example.com; "Webmaster" &lt;webmaster@example.com&gt;</code>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-new-user-admin-email-subject">' . "\n";
         echo 'New User Notification Subject:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_new_user_admin_email_subject" id="ws-plugin--s2member-new-user-admin-email-subject" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["new_user_admin_email_subject"]) . '" /><br />' . "\n";
         echo 'Subject Line used in the email notification sent to Administrator.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-new-user-admin-email-message">' . "\n";
         echo 'New User Notification Message:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<textarea name="ws_plugin__s2member_new_user_admin_email_message" id="ws-plugin--s2member-new-user-admin-email-message" rows="10">' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["new_user_admin_email_message"]) . '</textarea><br />' . "\n";
         echo 'Message Body used in the email notification sent to Administrator.<br /><br />' . "\n";
         echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
         echo '<ul>' . "\n";
         echo '<li><code>%%role%%</code> = The Role ID <code>(subscriber, s2member_level[0-9]+, administrator, editor, author, contributor)</code>.</li>' . "\n";
         echo '<li><code>%%label%%</code> = The Role ID Label <code>(Subscriber, s2Member Level 1, s2Member Level 2; or your own custom Labels — if configured)</code>.</li>' . "\n";
         echo '<li><code>%%level%%</code> = The Level number <code>(0, 1, 2, 3, 4)</code>. (<em>deprecated, no longer recommended; use <code>%%role%%</code></em>)</li>' . "\n";
         echo '<li><code>%%ccaps%%</code> = Custom Capabilities. Ex: <code>music,videos,free_gift</code> (<em>in comma-delimited format</em>).</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name (First &amp; Last) of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username the Member selected during registration.</li>' . "\n";
         echo '<li><code>%%user_pass%%</code> = The Password selected or generated during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The User\'s IP Address, detected via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress User ID generated during registration.</li>' . "\n";
         echo '<li><code>%%wp_login_url%%</code> = The full URL where Users can get logged into your site.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Registration/Profile Fields are also supported in this email:</strong>' . "\n";
         echo '<ul>' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -› General Options -› Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul>' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>(The campaign (i.e. christmas-promo) could be referenced using <code>%%cv1%%</code>)</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<div class="ws-menu-page-hr"></div>' . "\n" . '<p style="margin:0;"><strong>PHP Code:</strong> It is also possible to use PHP tags — optional (for developers). If you use PHP tags, please run a test email with <code>&lt;?php print_r(get_defined_vars()); ?&gt;</code>. This will give you a full list of all PHP variables available to you in this email. The <code>$user</code> variable is the most important one. It\'s an instance of the <a href="http://codex.wordpress.org/Class_Reference/WP_User" target="_blank" rel="external"><code>WP_User</code></a> class (e.g. <code>$user->ID</code>, <code>$user->has_cap()</code>, etc). Please note that all Replacement Codes will be parsed first, and then any PHP tags that you\'ve included. Also, please remember that emails are sent in plain text format.</p>' . "\n" : '';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_email_config", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_open_registration", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_open_registration", get_defined_vars());
         if (is_multisite() && is_main_site()) {
             echo '<div class="ws-menu-page-group" title="Open Registration">' . "\n";
             echo '<div class="ws-menu-page-section ws-plugin--s2member-open-registration-section">' . "\n";
             echo '<h3>Open Registration / Free Subscribers (optional)</h3>' . "\n";
             echo '<p>On the Main Site of a Multisite Network, the settings for Open Registration are consolidated into the <code>s2Member -› Multisite (Config)</code> panel.</p>' . "\n";
             do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_open_registration", get_defined_vars());
             echo '</div>' . "\n";
             echo '</div>' . "\n";
         } else {
             echo '<div class="ws-menu-page-group" title="Open Registration">' . "\n";
             echo '<div class="ws-menu-page-section ws-plugin--s2member-open-registration-section">' . "\n";
             echo '<h3>Open Registration / Free Subscribers (optional)</h3>' . "\n";
             echo '<p>s2Member supports Free Subscribers (at Level #0), along with four Primary Levels [1-4] of paid Membership. If you want your visitors to be capable of registering absolutely free, you will want to "allow" Open Registration. Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0.</p>' . "\n";
             do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_open_registration", get_defined_vars());
             echo '<table class="form-table">' . "\n";
             echo '<tbody>' . "\n";
             echo '<tr>' . "\n";
             echo '<th>' . "\n";
             echo '<label for="ws-plugin--s2member-allow-subscribers-in">' . "\n";
             echo 'Allow Open Registration? (Free Subscribers)' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td>' . "\n";
             echo '<select name="ws_plugin__s2member_allow_subscribers_in" id="ws-plugin--s2member-allow-subscribers-in">' . "\n";
             echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"] ? ' selected="selected"' : '') . '>No (do NOT allow Open Registration)</option>' . "\n";
             echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"] ? ' selected="selected"' : '') . '>Yes (allow Open Registration; Free Subscribers at Level #0)</option>' . "\n";
             echo '</select><br />' . "\n";
             echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">/wp-login.php?action=register</a>. When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.' . "\n";
             echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<br /><br /><em><strong>BuddyPress:</strong> BuddyPress will use its own Registration Form <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::bp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your BuddyPress Registration Form.\\n* However, you will probably be redirected away from this BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.\');">here</a>.<br />s2Member integrates with BuddyPress, and the above setting will control Open Regisration for BuddyPress too.</em>' . "\n" : '';
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
         }
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_open_registration", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_membership_levels", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_membership_levels", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Membership Levels/Labels">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-membership-levels-section">' . "\n";
         echo '<h3>Membership Levels (required, please customize these)</h3>' . "\n";
         echo '<p>The default Membership Levels are labeled generically; feel free to modify them as needed. s2Member supports Free Subscribers <em>(at Level #0)</em>, along with several Primary Roles for paid Membership <em>(i.e. Levels 1-4)</em>, created by the s2Member plugin.' . (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? ' s2Member also supports unlimited Custom Capability Packages <em>(see <code>s2Member -› API Scripting -› Custom Capabilities</code>)</em>' : '') . '. That being said, you don\'t have to use all of the Membership Levels if you don\'t want to. To use only 1 or 2 of these Levels, just design your Membership Options Page, so it only includes Payment Buttons for the Levels being used.</p>' . "\n";
         echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<p><em><strong>TIP:</strong> <strong>Unlimited Membership Levels</strong> are only possible with <a href="' . esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Pro Module / Prices")) . '" target="_blank" rel="external">s2Member Pro</a>. However, Custom Capabilities are possible in all versions of s2Member, including the free version. Custom Capabilities are a great way to extend s2Member in creative ways. If you\'re an advanced site owner, a theme designer, or a web developer integrating s2Member for a client, please check your Dashboard, under: <code>s2Member -› API Scripting -› Custom Capabilities</code>. We also recommend <a href="http://www.s2member.com/videos/A2C07377CF60025E/" target="_blank" rel="external">this video tutorial</a>.</em></p>' . "\n" : '';
         echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<p><strong>See also:</strong> These KB articles: <a href="http://www.s2member.com/kb/roles-caps/" target="_blank" rel="external">s2Member Roles/Capabilities</a> and <a href="http://www.s2member.com/kb/simple-shortcode-conditionals/" target="_blank" rel="external">Simple Shortcode Conditionals</a>.</p>' . "\n" : '';
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_membership_levels", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             echo '<tr>' . "\n";
             echo '<th>' . "\n";
             echo '<label for="ws-plugin--s2member-level' . $n . '-label">' . "\n";
             echo $n === 0 ? 'Level #' . $n . ' <em>(Free Subscribers)</em>:' . "\n" : 'Level #' . $n . ' Members:' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td>' . "\n";
             echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level' . $n . '_label" id="ws-plugin--s2member-level' . $n . '-label" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) . '" /><br />' . "\n";
             echo 'This is the Label for Level #' . $n . ($n === 0 ? ' (Free Subscribers)' : ' Members') . '.<br />' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
         }
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th style="padding-top:0;">' . "\n";
         echo '<label for="ws-plugin--s2member-apply-label-translations">' . "\n";
         echo 'Force WordPress to use your Labels?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="radio" name="ws_plugin__s2member_apply_label_translations" id="ws-plugin--s2member-apply-label-translations-0" value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["apply_label_translations"] ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-apply-label-translations-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_apply_label_translations" id="ws-plugin--s2member-apply-label-translations-1" value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["apply_label_translations"] ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-apply-label-translations-1">Yes, force WordPress to use my Labels.</label><br />' . "\n";
         echo 'This affects your administrative Dashboard only <em>(i.e. your list of Users)</em>.<br />s2Member can force WordPress to use your Labels instead of referencing Roles by `s2Member Level #`. If this is your first installation of s2Member, we suggest leaving this set to <code>no</code> until you\'ve had a chance to get acclimated with s2Member\'s functionality. In fact, many site owners choose to leave this off, because they find it less confusing when Roles are referred to by their s2Member Level #.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<input type="button" value="Reset Roles/Capabilities" class="ws-menu-page-right ws-plugin--s2member-reset-roles-button" style="min-width:175px;" />' . "\n";
         echo '<p>The button to the right, is a nifty tool, which allows you to reset s2Member\'s internal Roles and Capabilities that integrate with WordPress. If you, or a developer working with you, has made attempts to alter the default <em>internal</em> Role/Capability sets that come with s2Member, and you need to reset them back to the way s2Member expects them to be, please use this tool. <em>Attn Developers: it is also possible lock-in your modified Roles/Capabilities with an s2Member Filter. Please see <a href="http://www.s2member.com/kb/roles-caps/#modifying-roles-caps" target="_blank" rel="external">this KB article for details</a>.</em></p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_membership_levels", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_login_registration", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_login_registration", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Login/Registration Design">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-login-registration-section">' . "\n";
         echo '<h3>Login/Registration Page Customization (optional)</h3>' . "\n";
         echo '<p>These settings customize your Standard Login/Registration Pages:<br />(<a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">' . esc_html(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '</a>)</p>' . "\n";
         echo is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site() ? '<p><em>The Main Site of a Multisite Blog Farm uses this Form instead, powered by your theme.<br />(<a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_signup_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">' . esc_html(c_ws_plugin__s2member_utils_urls::wp_signup_url()) . '</a>)</em></p>' . "\n" : '';
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<p><em><strong>BuddyPress:</strong> BuddyPress will use its own Registration Form, powered by your theme.<br />(<a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::bp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your BuddyPress Registration Form.\\n* However, you will probably be redirected away from this BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.\');">' . esc_html(c_ws_plugin__s2member_utils_urls::bp_register_url()) . '</a>)</em></p>' . "\n" : '';
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_login_registration", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<h3 style="margin:0;">Enable This Functionality?</h3>' . "\n";
         echo '<select name="ws_plugin__s2member_login_reg_design_enabled" id="ws-plugin--s2member-login-reg-design-enabled">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_design_enabled"] ? ' selected="selected"' : '') . '>No (default, use WordPress defaults)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_design_enabled"] ? ' selected="selected"' : '') . '>Yes (customize Login/Registration with s2Member)</option>' . "\n";
         echo '</select>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div id="ws-plugin--s2member-login-reg-design"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_design_enabled"] ? ' style="display:none;"' : '') . '>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<h3 style="margin:0;">Overall Font/Size Configuration</h3>' . "\n";
         echo '<p style="margin:0;">These settings are all focused on your Login/Registration Fonts.</p>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-font-size">' . "\n";
         echo 'Overall Font Size:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_font_size" id="ws-plugin--s2member-login-reg-font-size" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_size"]) . '" /><br />' . "\n";
         echo 'Set this to a numeric value, calculated in pixels.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-font-family">' . "\n";
         echo 'Overall Font Family:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_font_family" id="ws-plugin--s2member-login-reg-font-family" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_family"]) . '" /><br />' . "\n";
         echo 'Set this to a web-safe font family.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-font-field-size">' . "\n";
         echo 'Form Field Font Size:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_font_field_size" id="ws-plugin--s2member-login-reg-font-field-size" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_field_size"]) . '" /><br />' . "\n";
         echo 'Set this to a numeric value, calculated in pixels.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<h3 style="margin:0;">Background Configuration</h3>' . "\n";
         echo '<p style="margin:0;">These settings are all focused on your Login/Registration Background.</p>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-background-color">' . "\n";
         echo 'Background Color:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_background_color" id="ws-plugin--s2member-login-reg-background-color" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"]) . '" /><br />' . "\n";
         echo 'Set this to a 6-digit hex color code.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-background-image">' . "\n";
         echo 'Background Image:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_background_image" id="ws-plugin--s2member-login-reg-background-image" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"]) . '" /><br />' . "\n";
         echo '<input type="button" id="ws-plugin--s2member-login-reg-background-image-media-btn" value="Open Media Library" class="ws-menu-page-media-btn" rel="ws-plugin--s2member-login-reg-background-image" />' . "\n";
         echo 'Set this to the URL of your Background Image. (this is optional)<br />';
         echo 'If supplied, your Background Image will be tiled.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-background-image-repeat">' . "\n";
         echo 'Background Image Tile:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_login_reg_background_image_repeat" id="ws-plugin--s2member-login-reg-background-image-repeat">' . "\n";
         echo '<option value="repeat"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image_repeat"] === "repeat" ? ' selected="selected"' : '') . '>Seamless Tile ( background-repeat: repeat; )</option>' . "\n";
         echo '<option value="repeat-x"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image_repeat"] === "repeat-x" ? ' selected="selected"' : '') . '>Tile Horizontally ( background-repeat: repeat-x; )</option>' . "\n";
         echo '<option value="repeat-y"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image_repeat"] === "repeat-y" ? ' selected="selected"' : '') . '>Tile Vertically ( background-repeat: repeat-y; )</option>' . "\n";
         echo '<option value="no-repeat"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image_repeat"] === "no-repeat" ? ' selected="selected"' : '') . '>No Tiles ( background-repeat: no-repeat; )</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'This controls the way your Background Image is styled with CSS. [ <a href="http://www.w3schools.com/css/pr_background-repeat.asp" target="_blank" rel="external">learn more</a> ]' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-background-text-color">' . "\n";
         echo 'Color of Text on top of your Background:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_background_text_color" id="ws-plugin--s2member-login-reg-background-text-color" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"]) . '" /><br />' . "\n";
         echo 'Set this to a 6-digit hex color code.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-background-text-shadow-color">' . "\n";
         echo 'Shadow Color for Text on top of your Background:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_background_text_shadow_color" id="ws-plugin--s2member-login-reg-background-text-shadow-color" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"]) . '" /><br />' . "\n";
         echo 'Set this to a 6-digit hex color code.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-background-box-shadow-color">' . "\n";
         echo 'Shadow Color for Boxes on top of your Background:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_background_box_shadow_color" id="ws-plugin--s2member-login-reg-background-box-shadow-color" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"]) . '" /><br />' . "\n";
         echo 'Set this to a 6-digit hex color code.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<h3 style="margin:0;">Logo Image Configuration</h3>' . "\n";
         echo '<p style="margin:0;">These settings are all focused on your Login/Registration Logo.</p>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-logo-src">' . "\n";
         echo 'Logo Image Location:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_logo_src" id="ws-plugin--s2member-login-reg-logo-src" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"]) . '" /><br />' . "\n";
         echo '<input type="button" id="ws-plugin--s2member-login-reg-logo-src-media-btn" value="Open Media Library" class="ws-menu-page-media-btn" rel="ws-plugin--s2member-login-reg-logo-src" />' . "\n";
         echo 'Set this to the URL of your Logo Image.<br />' . "\n";
         echo 'Suggested size is around 500 x 100.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-logo-src-width">' . "\n";
         echo 'Logo Image Width:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_logo_src_width" id="ws-plugin--s2member-login-reg-logo-src-width" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"]) . '" /><br />' . "\n";
         echo 'The pixel Width of your Logo Image. <em>* This ALSO affects the overall width of your Login/Registration forms. If you want wider form fields, use a wider Logo.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-logo-src-height">' . "\n";
         echo 'Logo Image Height:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_logo_src_height" id="ws-plugin--s2member-login-reg-logo-src-height" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_height"]) . '" /><br />' . "\n";
         echo 'The pixel Height of your Logo Image.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-logo-url">' . "\n";
         echo 'Logo Image Click URL:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_logo_url" id="ws-plugin--s2member-login-reg-logo-url" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_url"]) . '" /><br />' . "\n";
         echo 'Set this to the Click URL for your Logo Image.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-logo-title">' . "\n";
         echo 'Logo Image Title Attribute:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_reg_logo_title" id="ws-plugin--s2member-login-reg-logo-title" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_title"]) . '" /><br />' . "\n";
         echo 'Used as the <code>title=""</code> attribute for your Logo Image.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-footer-backtoblog">' . "\n";
         echo 'Display [Back to Home Page] Link At Bottom?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_login_reg_footer_backtoblog" id="ws-plugin--s2member-login-reg-footer-backtoblog">' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_footer_backtoblog"] ? ' selected="selected"' : '') . '>Yes, display link at bottom pointing visitors back to the home page</option>' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_footer_backtoblog"] ? ' selected="selected"' : '') . '>No, hide this link (I\'ll create my own custom footer w/ the details I prefer)</option>' . "\n";
         echo '</select>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<h3 style="margin:0;">Footer Design (i.e. Bottom)</h3>' . "\n";
         echo '<p style="margin:0;">This field accepts raw HTML' . (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? ' (and/or PHP)' : '') . ' code.</p>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-reg-footer-design">' . "\n";
         echo 'Login/Registration Footer Design (optional):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<textarea name="ws_plugin__s2member_login_reg_footer_design" id="ws-plugin--s2member-login-reg-footer-design" rows="3" wrap="off" spellcheck="false">' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_footer_design"]) . '</textarea><br />' . "\n";
         echo 'This optional HTML' . (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? ' (and/or PHP)' : '') . ' code will appear at the very bottom of your Login/Registration Forms.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_login_registration", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_custom_reg_fields", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_custom_reg_fields", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Registration/Profile Fields &amp; Options">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-custom-reg-fields-section">' . "\n";
         echo '<h3>Custom Registration/Profile Fields (optional, for further customization)</h3>' . "\n";
         echo '<p>Some fields are already built-in by default. The defaults are: <code>*Username*, *Email*, *First Name*, *Last Name*</code>.</p>' . "\n";
         echo '<p>Custom Fields will appear in your Standard Registration Form, and in User/Member Profiles:<br />(<a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">' . esc_html(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '</a>)</p>' . "\n";
         echo is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site() ? '<p><em>The Main Site of a Multisite Blog Farm uses this Form. s2Member supports Custom Fields here too.<br />(<a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_signup_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">' . esc_html(c_ws_plugin__s2member_utils_urls::wp_signup_url()) . '</a>)</em></p>' . "\n" : '';
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<p><em><strong>BuddyPress:</strong> BuddyPress will use its own Registration Form <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::bp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your BuddyPress Registration Form.\\n* However, you will probably be redirected away from this BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.\');">here</a>.<br />s2Member can integrate your Custom Fields with BuddyPress too, please see options below.</em></p>' . "\n" : '';
         echo '<p><strong>Regarding registration...</strong> Custom Fields do NOT appear during repeat registration and/or checkout attempts (e.g. they do NOT appear for any user that is currently logged into the site). Please make sure that you test registration and/or checkout forms while NOT logged in (e.g. please test as a first-time customer). Existing users/members/customers may update Custom Fields by editing their Profile.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_custom_reg_fields", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label>' . "\n";
         echo 'Custom Registration/Profile Fields:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="hidden" name="ws_plugin__s2member_custom_reg_fields" id="ws-plugin--s2member-custom-reg-fields" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) . '" />' . "\n";
         echo '<div id="ws-plugin--s2member-custom-reg-field-configuration"></div>' . "\n";
         // This is filled by JavaScript routines.
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-custom-reg-names">' . "\n";
         echo 'Collect First/Last Names during Registration?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_custom_reg_names" id="ws-plugin--s2member-custom-reg-names">' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"] ? ' selected="selected"' : '') . '>Yes (always collect First/Last Names during registration)</option>' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_names"] ? ' selected="selected"' : '') . '>No (do NOT collect First/Last Names during registration)</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'Recommended setting (<code>Yes</code>). It\'s usually a good idea to leave this on.' . "\n";
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<br /><em>* Has NO affect on BuddyPress registration form (BuddyPress always collects a full <code>Name</code> field).</em>' . "\n" : '';
         echo c_ws_plugin__s2member_utils_conds::pro_is_installed() ? '<br /><em>* s2Member Pro (Checkout) Forms always require a First/Last Name for billing.</em>' . "\n" : '';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-custom-reg-display-name">' . "\n";
         echo 'Set "Display Name" during Registration?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_custom_reg_display_name" id="ws-plugin--s2member-custom-reg-display-name">' . "\n";
         echo '<option value="full"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_display_name"] === "full" ? ' selected="selected"' : '') . '>Yes (set Display Name to User\'s Full Name)</option>' . "\n";
         echo '<option value="first"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_display_name"] === "first" ? ' selected="selected"' : '') . '>Yes (set Display Name to User\'s First Name)</option>' . "\n";
         echo '<option value="last"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_display_name"] === "last" ? ' selected="selected"' : '') . '>Yes (set Display Name to User\'s Last Name)</option>' . "\n";
         echo '<option value="login"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_display_name"] === "login" ? ' selected="selected"' : '') . '>Yes (set Display Name to User\'s Username)</option>' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_display_name"] ? ' selected="selected"' : '') . '>No (leave Display Name at default WordPress value)</option>' . "\n";
         echo '</select>' . "\n";
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<br /><em>* Has NO affect on BuddyPress registration form (BuddyPress always uses its full <code>Name</code> field).</em>' . "\n" : '';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-custom-reg-password">' . "\n";
         echo 'Allow Custom Passwords during Registration?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_custom_reg_password" id="ws-plugin--s2member-custom-reg-password"' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site() && !c_ws_plugin__s2member_utils_conds::pro_is_installed() ? ' disabled="disabled"' : '') . '>' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"] ? ' selected="selected"' : '') . '>No (send auto-generated passwords via email; after registration)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"] ? ' selected="selected"' : '') . '>Yes (allow members to create their own password during registration)</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'Auto-generated Passwords are recommended for best security; because, this also serves as a form of email confirmation.' . "\n";
         echo is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site() ? '<br /><em>* For security purposes, Custom Passwords are NOT possible on the Main Site of a Blog Farm. <a href="#" onclick="alert(\'For security purposes, Custom Passwords are NOT possible on the Main Site of a Blog Farm. A User MUST wait for the activation/confirmation email; where a randomly generated Password will be assigned. Please note, this limitation only affects your Main Site, via `/wp-signup.php`. In other words, your Customers (i.e. other Blog Owners) will still have the ability to allow Custom Passwords with s2Member. YOU are affected by this limitation, NOT them.\\n\\n* NOTE: s2Member (Pro) removes this limitation.\\nIf you install the s2Member Pro Module, you WILL be able to allow Custom Passwords through s2Member Pro Forms; even on a Multisite Blog Farm.\'); return false;" tabindex="-1">[?]</a></em>' . "\n" : '';
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<br /><em>* Does NOT affect BuddyPress registration form (always <code>yes</code> with BuddyPress registration).</em>' . "\n" : '';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-custom-reg-force-personal-emails">' . "\n";
         echo 'Force Personal Emails during Registration?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_custom_reg_force_personal_emails" id="ws-plugin--s2member-custom-reg-force-personal-emails" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_force_personal_emails"]) . '" /><br />' . "\n";
         echo 'To force personal email addresses, provide a comma-delimited list of email users to reject. <a href="#" onclick="alert(\'s2Member will reject [user]@ (based on your configuration here). A JavaScript alert message will be issued, asking the User to, `please use a personal email address`.\'); return false;" tabindex="-1">[?]</a><br />' . "\n";
         echo 'Ex: <code>info,help,admin,webmaster,hostmaster,sales,support,spam</code><br />' . "\n";
         echo 'See: <a href="http://kb.mailchimp.com/article/what-role-addresses-does-mailchimp-specifically-block-from-bulk-importing/" target="_blank" rel="external">this article</a> for a more complete list.' . "\n";
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<br /><em>* Affects BuddyPress registration form too.</em>' . "\n" : '';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-custom-reg-fields-4bp">' . "\n";
         echo 'Integrate Custom Registration/Profile Fields with BuddyPress?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<div class="ws-menu-page-scrollbox" style="height:65px;">' . "\n";
         echo '<input type="hidden" name="ws_plugin__s2member_custom_reg_fields_4bp[]" value="update-signal"' . (!c_ws_plugin__s2member_utils_conds::bp_is_installed() ? ' disabled="disabled"' : '') . ' />' . "\n";
         foreach (array("profile-view" => "Yes, integrate with BuddyPress Public Profiles.", "registration" => "Yes, integrate with BuddyPress Registration Form.", "profile" => "Yes, integrate with BuddyPress Profile Editing Panel.") as $ws_plugin__s2member_temp_s_value => $ws_plugin__s2member_temp_s_label) {
             echo '<input type="checkbox" name="ws_plugin__s2member_custom_reg_fields_4bp[]" id="ws-plugin--s2member-custom-reg-fields-4bp-' . esc_attr(preg_replace("/[^a-z0-9_\\-]/", "-", $ws_plugin__s2member_temp_s_value)) . '" value="' . esc_attr($ws_plugin__s2member_temp_s_value) . '"' . (in_array($ws_plugin__s2member_temp_s_value, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields_4bp"]) ? ' checked="checked"' : '') . (!c_ws_plugin__s2member_utils_conds::bp_is_installed() ? ' disabled="disabled"' : '') . ' /> <label for="ws-plugin--s2member-custom-reg-fields-4bp-' . esc_attr(preg_replace("/[^a-z0-9_\\-]/", "-", $ws_plugin__s2member_temp_s_value)) . '">' . $ws_plugin__s2member_temp_s_label . '</label><br />' . "\n";
         }
         echo '</div>' . "\n";
         echo !c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<em>* BuddyPress is NOT installed; which is perfectly OK. BuddyPress is NOT a requirement.</em>' . "\n" : '<em>* The options above, make it possible to integrate Custom Registration/Profile Fields (i.e. those configured with s2Member) into BuddyPress as well. However, if you configure Profile Fields with BuddyPress, those will NOT be integrated with s2Member. Therefore, if you need Custom Registration/Profile Fields to work with both s2Member and with BuddyPress, please configure them with s2Member.</em>';
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_custom_reg_fields", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_login_welcome_page", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_login_welcome_page", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Login Welcome Page">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-login-welcome-page-section">' . "\n";
         echo '<h3>Login Welcome Page (required, please customize this)</h3>' . "\n";
         echo '<p>Please create and/or choose an existing Page to use as the first page Members will see after logging in.</p>' . "\n";
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<p><em><strong>BuddyPress:</strong> s2Member integrates with BuddyPress. Your Login Welcome Page affects BuddyPress too.</em></p>' . "\n" : '';
         echo '<p><em><strong>*Tips*</strong> This special Page will be protected from public access (automatically) by s2Member. Also, please remember this option CANNOT be set to your Front Page (e.g. your Home Page), or to your Posts Page (e.g. your main Blog page). Please create a separate Page in WordPress &amp; designate it here as your Login Welcome Page.</em></p>' . "\n";
         echo '<p><strong>See also:</strong> This KB article: <a href="http://www.s2member.com/kb/customizing-your-lwp/" target="_blank" rel="external">Customizing Your Login Welcome Page</a>.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_login_welcome_page", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-welcome-page">' . "\n";
         echo 'Login Welcome Page:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_login_welcome_page" id="ws-plugin--s2member-login-welcome-page">' . "\n";
         echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
         foreach ($ws_plugin__s2member_temp_a = array_merge((array) get_pages()) as $ws_plugin__s2member_temp_o) {
             echo '<option value="' . esc_attr($ws_plugin__s2member_temp_o->ID) . '"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && $ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] ? ' selected="selected"' : '') . '>' . esc_html($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
         }
         echo '</select><br />' . "\n";
         echo 'Please choose a Page to be used as the first page Members will see after logging in. This Page can contain anything you like. We recommend the following title: <code>Welcome To Our Members Area</code>.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-redirection-override">' . "\n";
         echo 'Or, a Special Redirection URL?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_redirection_override" id="ws-plugin--s2member-login-redirection-override" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"]) . '" /><br />' . "\n";
         echo 'Or, you may configure a Special Redirection URL, if you prefer. You\'ll need to type in the full URL, starting with: <code>http://</code>. <em>A few <a href="#" onclick="alert(\'Replacement Codes:\\n\\n%%current_user_login%% = The current User\\\'s Username, lowercase (deprecated, please use %%current_user_nicename%%).\\n\\n%%current_user_nicename%% = The current User\\\'s Nicename in lowercase format (i.e. a cleaner version of the username for URLs; recommended for best compatibility).\\n\\n%%current_user_id%% = The current User\\\'s ID.\\n\\n%%current_user_level%% = The current User\\\'s s2Member Level.\\n\\n%%current_user_role%% = The current User\\\'s WordPress Role.' . (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '\\n\\n%%current_user_ccaps%% = The current User\\\'s Custom Capabilities.' : '') . '\\n\\n%%current_user_logins%% = Number of times the current User has logged in.\\n\\nFor example, if you\\\'re using BuddyPress, and you want to redirect Members to their BuddyPress Profile page after logging in, you would setup a Special Redirection URL, like this: ' . site_url("/members/%%current_user_nicename%%/profile/") . '\\n\\nOr ... using %%current_user_level%%, you could have a separate Login Welcome Page for each Membership Level that you plan to offer. BuddyPress not required.\'); return false;">Replacement Codes</a> are also supported here.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table" style="margin-top:0;">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-login-redirection-always-http">' . "\n";
         echo 'Always Redirect non-Administrative Users (after login) using HTTP?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_login_redirection_always_http" id="ws-plugin--s2member-login-redirection-always-http">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_always_http"] ? ' selected="selected"' : '') . '>No, do NOT modify (use WordPress default behavior; e.g. detect URL scheme automatically)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_always_http"] ? ' selected="selected"' : '') . '>Yes, always redirect non-administrative users to non-SSL version (e.g. always use http://)</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'Recommended setting: <code>Yes</code>. This is compatible w/ <a href="http://codex.wordpress.org/Administration_Over_SSL" target="_blank" rel="external"><code>FORCE_SSL_LOGIN</code></a> and/or <a href="http://codex.wordpress.org/Administration_Over_SSL" target="_blank" rel="external"><code>FORCE_SSL_ADMIN</code></a>.' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_login_welcome_page", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_membership_options_page", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_membership_options_page", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Membership Options Page">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-membership-options-page-section">' . "\n";
         echo '<h3>Membership Options Page (required, please customize this)</h3>' . "\n";
         echo '<p>Please create and/or choose an existing Page that showcases your Membership subscription options. This special Page is where you will insert the Payment Button(s) generated for you by s2Member. This Page serves as your lead-in signup page <em>(i.e. you\'ll give visitors one or more registration options here, and they\'ll be redirected to your Payment Gateway, to pay for the option they choose)</em>.</p>' . "\n";
         echo '<p>Your Membership Options Page should detail all of the features that come with Membership to your site, and provide a Payment Button for each Level of access you plan to offer. This is also the Page that anyone could be redirected to <em>(by s2Member)</em>, should they attempt to access an area of your site, which may require access to something they\'re NOT currenty allowed to view.' . (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? ' For more on this advanced topic, please check your Dashboard here: <code>s2Member -› API Scripting -› Membership Options Page / Variables</code>.' : '') . '</p>' . "\n";
         echo '<p><em><strong>*Tip*</strong> If you allow Open Registration (i.e. Free Subscribers), you might want to place a link on your Membership Options Page, which points directly to your free Registration Form, instead of routing a Customer through your Payment Gateway first. It\'s a matter of preference though. For further details, please check the section above: <code>s2Member -› General Options -› Open Registration</code>.</em></p>' . "\n";
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<p><em><strong>BuddyPress:</strong> Even with BuddyPress, s2Member still needs a Membership Options Page. This is where your Payment Button(s) will go, giving people the ability to pay you. And again, this is also the Page that anyone could be redirected to <em>(by s2Member)</em>, should they attempt to access an area of your site, which may require access to something they are currenty NOT allowed to view.' . (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? ' For more on this advanced topic, please check your Dashboard here: <code>s2Member -› API Scripting -› Membership Options Page / Variables</code>.' : '') . '</em></p>' . "\n" : '';
         echo '<p><em><strong>*Tip*</strong> s2Member will NEVER allow this Page to be protected from public access.</em></p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_membership_options_page", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-membership-options-page">' . "\n";
         echo 'Membership Options Page:' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_membership_options_page" id="ws-plugin--s2member-membership-options-page">' . "\n";
         echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
         foreach ($ws_plugin__s2member_temp_a = array_merge((array) get_pages()) as $ws_plugin__s2member_temp_o) {
             echo '<option value="' . esc_attr($ws_plugin__s2member_temp_o->ID) . '"' . ($ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] ? ' selected="selected"' : '') . '>' . esc_html($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
         }
         echo '</select><br />' . "\n";
         echo 'Please choose a Page that provides Users a way to signup for Membership. This Page should also contain your Payment Button(s). We recommend the following title: <code>Membership Signup</code>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-membership-options-page-vars-enable">' . "\n";
         echo 'Enable MOP Vars (i.e. Membership Options Page Variables)?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_membership_options_page_vars_enable" id="ws-plugin--s2member-membership-options-page-vars-enable">' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page_vars_enable"] ? ' selected="selected"' : '') . '>Yes (enable MOP Vars in all redirections; recommended behavior)</option>' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page_vars_enable"] ? ' selected="selected"' : '') . '>No (don\'t include the additional details provided by MOP Vars)</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'See: <code>Dashboard ⥱ s2Member ⥱ API / Scripting ⥱ Membership Options Page / Variables</code><br />' . "\n";
         echo 'Recommended setting: (<code>Yes, enable MOP Vars</code>)' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_membership_options_page", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_profile_modifications", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_profile_modifications", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="Member Profile Modifications">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-profile-modifications-section">' . "\n";
         echo '<h3>Giving Members The Ability To Modify Their Profile</h3>' . "\n";
         echo '<p>s2Member can be configured to redirect Members away from the <a href="' . esc_attr(admin_url("/profile.php")) . '" target="_blank" rel="external">default Profile Editing Panel</a> that is built into WordPress. When/if a Member attempts to access the default Profile Editing Panel, they\'ll instead, be redirected to the Login Welcome Page that you\'ve configured through s2Member. <strong>Why would I redirect?</strong> Unless you\'ve made some drastic modifications to your WordPress installation, the default Profile Editing Panel that ships with WordPress, is NOT really suited for public access, even by a Member.</p>' . "\n";
         echo '<p>So instead of using this default Profile Editing Panel; s2Member creates an added layer of functionality, on top of WordPress. It does this by providing you <em>(as the site owner)</em>, with a special Shortcode: <code>[s2Member-Profile /]</code> that you can place into your Login Welcome Page, or any Post/Page for that matter <em>(even into a Text Widget)</em>. This Shortcode produces an Inline Profile Editing Form that supports all aspects of s2Member, including Password changes; and any Custom Registration/Profile Fields that you\'ve configured with s2Member.</p>' . "\n";
         echo '<p>Alternatively, s2Member also gives you the ability to send your Members to a <a href="' . esc_attr(site_url("/?s2member_profile=1")) . '" target="_blank" rel="external">special Stand-Alone version</a>. This Stand-Alone version has been designed <em>(with a bare-bones format)</em>, intentionally. This makes it possible for you to <a href="#" onclick="if(!window.open(\'' . site_url("/?s2member_profile=1") . '\', \'_popup\', \'width=600,height=400,left=100,screenX=100,top=100,screenY=100,location=0,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1\')) alert(\'Please disable popup blockers and try again!\'); return false;" rel="external">open it up in a popup window</a>, or embed it into your Login Welcome Page using an IFRAME. Code samples are provided below.</p>' . "\n";
         echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<p><em><strong>BuddyPress:</strong> BuddyPress already provides Users/Members with a Profile Editing Panel, powered by your theme. If you\'ve configured Custom Registration/Profile Fields with s2Member, you can also enable s2Member\'s Profile Field integration with BuddyPress (recommended). For further details, see: <code>s2Member -› General Options -› Registration/Profile Fields</code>.</em></p>' . "\n" : '';
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_profile_modifications", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-force-admin-lockouts">' . "\n";
         echo 'Redirect Members away from the Default Profile Panel?' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_force_admin_lockouts" id="ws-plugin--s2member-force-admin-lockouts">' . "\n";
         echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["force_admin_lockouts"] ? ' selected="selected"' : '') . '>No (I want to use the WordPress default methodologies)</option>' . "\n";
         echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["force_admin_lockouts"] ? ' selected="selected"' : '') . '>Yes (redirect to Login Welcome Page; locking all /wp-admin/ areas)</option>' . "\n";
         echo '</select><br />' . "\n";
         echo 'Recommended setting (<code>Yes</code>). <em><strong>*Note*</strong> When this is set to (<code>Yes</code>), s2Member will take an initiative to further safeguard ALL <code>/wp-admin/</code> areas of your installation; not just the Default Profile Panel.</em>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><strong>Shortcode (copy/paste)</strong>, for an Inline Profile Modification Form:<br />' . "\n";
         echo '<p><input type="text" autocomplete="off" value="' . format_to_edit('[s2Member-Profile /]') . '" class="monospace" onclick="this.select ();" /></p>' . "\n";
         echo '<p style="margin-top:20px;"><strong>Stand-Alone (copy/paste)</strong>, for popup window:</p>' . "\n";
         echo '<p><input type="text" autocomplete="off" value="' . format_to_edit(preg_replace("/\\<\\?php echo S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL; \\?\\>/", c_ws_plugin__s2member_utils_strings::esc_refs(site_url("/?s2member_profile=1")), file_get_contents(dirname(__FILE__) . "/code-samples/current-user-profile-modification-page-url-2-ops.x-php"))) . '" class="monospace" onclick="this.select ();" /></p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_profile_modifications", get_defined_vars());
     }
     if (apply_filters("ws_plugin__s2member_during_gen_ops_page_during_left_sections_display_url_shortening", TRUE, get_defined_vars())) {
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_before_url_shortening", get_defined_vars());
         echo '<div class="ws-menu-page-group" title="URL Shortening Service Preference">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-url-shortening-section">' . "\n";
         echo '<h3>URL Shortening Service API (Preference)</h3>' . "\n";
         echo '<p>In a few special cases, long URLs generated by s2Member, containing encrypted authentication details, will be shortened; using one of the URL Shortening APIs <em>(listed below)</em>. A shortened URL prevents issues with VERY long links becoming corrupted by a Customer\'s email application. For instance, the Signup Confirmation Email that s2Member sends out to a new paying Customer, may contain a link which is shortened to prevent corruption by email applications. By default, s2Member uses the tinyURL API, which has proven itself to be the most reliable. However, in cases where an API service call fails, s2Member will automatically use one or more of its other APIs as a backup. The option below, allows you to configure which URL Shortening API s2Member should try first <em>(i.e. the one you prefer)</em>.</p>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_url_shortening", get_defined_vars());
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-default-url-shortener">' . "\n";
         echo 'URL Shortening Service API (Preference):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<select name="ws_plugin__s2member_default_url_shortener" id="ws-plugin--s2member-default-url-shortener">' . "\n";
         echo '<option value="tiny_url"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["default_url_shortener"] === "tiny_url" ? ' selected="selected"' : '') . '>tinyurl.com (free tinyURL API service)</option>' . "\n";
         echo '<option value="goo_gl"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["default_url_shortener"] === "goo_gl" ? ' selected="selected"' : '') . '>goo.gl (free Google URL Shortening API service)</option>' . "\n";
         echo '</select>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<th>' . "\n";
         echo '<label for="ws-plugin--s2member-default-custom-str-url-shortener">' . "\n";
         echo 'Custom URL Shortening Service API (Optional/Advanced):' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_default_custom_str_url_shortener" id="ws-plugin--s2member-default-custom-str-url-shortener" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["default_custom_str_url_shortener"]) . '" /><br />' . "\n";
         echo 'Your own custom URL <code>(i.e. GET request)</code>, with <code>%%s2_long_url%%</code> Replacement Code. [ <a href="#" onclick="alert(\'s2Member makes it possible for advanced site owners to use a custom URL shortening service they prefer, over the ones currently pre-integrated with s2Member. In order for this to work, your URL shortening service MUST support basic GET requests through its API (sometimes referred to as a REST or NVP API). In addition, your URL shortening service MUST be capable of returning a simple URL in the response that s2Member receives, as a result of s2Member processing the GET request you formulate. See example below.\\n\\nBitly example GET request with format=txt:\\nhttp://api.bitly.com/v3/shorten?login=demo&apiKey=2d71bf07&format=txt&longUrl=%%s2_long_url%%\\n(s2Member expects a shortened URL in the response from Bitly)\\n\\n* If you configure s2Member to use your own custom URL shortening service, s2Member will try your configuration first, and if anything fails, it will fall back on its own pre-integrated backups. When configuring your URL for the GET request, s2Member makes two Replacement Codes available:\\n\\n%%s2_long_url%% = The full URL that needs to be shortened (raw URL-encoded).\\n%%s2_long_url_md5%% = An MD5 hash of the full URL (might be useful in some APIs).\\n\\n* If you have any trouble getting your URL shortening service integrated with s2Member in this way, you might take a look at this WordPress Filter ( `ws_plugin__s2member_url_shorten` ), which s2Member makes available for advanced circumstances. Search s2Member\\\'s source code for `ws_plugin__s2member_url_shorten`.\'); return false;" tabindex="-1">click for details</a> ]<br />' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_after_url_shortening", get_defined_vars());
     }
     do_action("ws_plugin__s2member_during_gen_ops_page_after_left_sections", get_defined_vars());
     echo '<div class="ws-menu-page-hr"></div>' . "\n";
     echo '<p class="submit"><input type="submit" value="Save All Changes" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
 }
 /**
  * Outputs the JS for administrative menu pages.
  *
  * @package s2Member\Admin_CSS_JS
  * @since 3.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after loading JS.
  */
 public static function menu_pages_js()
 {
     do_action("ws_plugin__s2member_before_menu_pages_js", get_defined_vars());
     if (!empty($_GET["ws_plugin__s2member_menu_pages_js"]) && is_user_logged_in() && current_user_can("create_users")) {
         status_header(200);
         // 200 OK status header.
         header("Content-Type: application/x-javascript; charset=UTF-8");
         header("Expires: " . gmdate("D, d M Y H:i:s", strtotime("-1 week")) . " GMT");
         header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
         header("Cache-Control: no-cache, must-revalidate, max-age=0");
         header("Pragma: no-cache");
         while (@ob_end_clean()) {
         }
         // Clean any existing output buffers.
         $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
         $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
         for ($n = 0, $labels = ""; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
             $labels .= "labels['level" . $n . "'] = '" . (!empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) ? str_replace('"', "", c_ws_plugin__s2member_utils_strings::esc_js_sq($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"], 3)) : "") . "';";
         }
         unset($n);
         include_once dirname(dirname(__FILE__)) . "/menu-pages/menu-pages-min.js";
         echo "\n";
         // Add a line break before inclusion of this file.
         @(include_once dirname(dirname(__FILE__)) . "/menu-pages/menu-pages-s-min.js");
         do_action("ws_plugin__s2member_during_menu_pages_js", get_defined_vars());
         exit;
         // Clean exit.
     }
     do_action("ws_plugin__s2member_after_menu_pages_js", get_defined_vars());
 }
Пример #21
0
 /**
  * Handles Profile modifications.
  *
  * @package s2Member\Profiles
  * @since 3.5
  *
  * @attaches-to ``add_action('init');``
  */
 public static function handle_profile_modifications()
 {
     global $current_user;
     // We'll need to update this global object.
     $user =& $current_user;
     // Shorter reference to the $current_user object.
     do_action('ws_plugin__s2member_before_handle_profile_modifications', get_defined_vars());
     if (!empty($_POST['ws_plugin__s2member_profile_save']) && is_user_logged_in() && is_object($user) && !empty($user->ID) && ($user_id = $user->ID)) {
         if (($nonce = $_POST['ws_plugin__s2member_profile_save']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-profile-save')) {
             $GLOBALS['ws_plugin__s2member_profile_saved'] = TRUE;
             // Global flag as having been saved/updated successfully.
             $_p = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST));
             // Clean ``$_POST`` vars.
             $userdata['ID'] = $user_id;
             // Needed for database update.
             if (!empty($_p['ws_plugin__s2member_profile_email'])) {
                 if (is_email($_p['ws_plugin__s2member_profile_email']) && !email_exists($_p['ws_plugin__s2member_profile_email'])) {
                     $userdata['user_email'] = $_p['ws_plugin__s2member_profile_email'];
                     if (strcasecmp($userdata['user_email'], $user->user_email) !== 0) {
                         $email_change = TRUE;
                     }
                 }
             }
             if (!empty($_p['ws_plugin__s2member_profile_password1'])) {
                 if ($user->user_login !== 'demo') {
                     // No pass change on demo!
                     $userdata['user_pass'] = $_p['ws_plugin__s2member_profile_password1'];
                 }
             }
             if (!empty($_p['ws_plugin__s2member_profile_first_name'])) {
                 $userdata['first_name'] = $_p['ws_plugin__s2member_profile_first_name'];
             }
             if (!empty($_p['ws_plugin__s2member_profile_display_name'])) {
                 $userdata['display_name'] = $_p['ws_plugin__s2member_profile_display_name'];
             }
             if (!empty($_p['ws_plugin__s2member_profile_last_name'])) {
                 $userdata['last_name'] = $_p['ws_plugin__s2member_profile_last_name'];
             }
             wp_update_user(wp_slash($userdata));
             // OK. Now send this array for an update.
             if ($GLOBALS['WS_PLUGIN__']['s2member']['o']['custom_reg_fields']) {
                 if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level('auto-detection', 'profile')) {
                     $fields = array();
                     // Initialize the array of fields.
                     $_existing_fields = get_user_option('s2member_custom_fields', $user_id);
                     foreach (json_decode($GLOBALS['WS_PLUGIN__']['s2member']['o']['custom_reg_fields'], TRUE) as $field) {
                         $field_var = preg_replace('/[^a-z0-9]/i', '_', strtolower($field['id']));
                         $field_id_class = preg_replace('/_/', '-', $field_var);
                         if (!in_array($field['id'], $fields_applicable) || strpos($field['editable'], 'no') === 0) {
                             if (isset($_existing_fields[$field_var]) && (is_array($_existing_fields[$field_var]) && !empty($_existing_fields[$field_var]) || is_string($_existing_fields[$field_var]) && strlen($_existing_fields[$field_var]))) {
                                 $fields[$field_var] = $_existing_fields[$field_var];
                             } else {
                                 unset($fields[$field_var]);
                             }
                         } else {
                             if ($field['required'] === 'yes' && (!isset($_p['ws_plugin__s2member_profile_' . $field_var]) || !is_array($_p['ws_plugin__s2member_profile_' . $field_var]) && !is_string($_p['ws_plugin__s2member_profile_' . $field_var]) || is_array($_p['ws_plugin__s2member_profile_' . $field_var]) && empty($_p['ws_plugin__s2member_profile_' . $field_var]) || is_string($_p['ws_plugin__s2member_profile_' . $field_var]) && !strlen($_p['ws_plugin__s2member_profile_' . $field_var])) || isset($_p['ws_plugin__s2member_profile_' . $field_var]) && c_ws_plugin__s2member_custom_reg_fields::validation_errors(array($field_var => $_p['ws_plugin__s2member_profile_' . $field_var]), array($field))) {
                                 if (isset($_existing_fields[$field_var]) && (is_array($_existing_fields[$field_var]) && !empty($_existing_fields[$field_var]) || is_string($_existing_fields[$field_var]) && strlen($_existing_fields[$field_var]))) {
                                     $fields[$field_var] = $_existing_fields[$field_var];
                                 } else {
                                     unset($fields[$field_var]);
                                 }
                             } else {
                                 if (isset($_p['ws_plugin__s2member_profile_' . $field_var])) {
                                     if ((is_array($_p['ws_plugin__s2member_profile_' . $field_var]) && !empty($_p['ws_plugin__s2member_profile_' . $field_var]) || is_string($_p['ws_plugin__s2member_profile_' . $field_var]) && strlen($_p['ws_plugin__s2member_profile_' . $field_var])) && !c_ws_plugin__s2member_custom_reg_fields::validation_errors(array($field_var => $_p['ws_plugin__s2member_profile_' . $field_var]), array($field))) {
                                         $fields[$field_var] = $_p['ws_plugin__s2member_profile_' . $field_var];
                                     } else {
                                         unset($fields[$field_var]);
                                     }
                                 } else {
                                     unset($fields[$field_var]);
                                 }
                             }
                         }
                     }
                     if (!empty($fields)) {
                         update_user_option($user_id, 's2member_custom_fields', $fields);
                     } else {
                         // Else delete their Custom Fields?
                         delete_user_option($user_id, 's2member_custom_fields');
                     }
                 }
             }
             foreach (array_keys(get_defined_vars()) as $__v) {
                 $__refs[$__v] =& ${$__v};
             }
             do_action('ws_plugin__s2member_during_handle_profile_modifications', get_defined_vars());
             unset($__refs, $__v);
             clean_user_cache($user_id);
             wp_cache_delete($user_id, 'user_meta');
             $user = new WP_User($user_id);
             // Fresh object.
             if (function_exists('setup_userdata')) {
                 setup_userdata();
             }
             $role = c_ws_plugin__s2member_user_access::user_access_role($user);
             $level = c_ws_plugin__s2member_user_access::user_access_role_to_level($role);
             if (!empty($_p['ws_plugin__s2member_profile_opt_in']) && $role && $level >= 0) {
                 c_ws_plugin__s2member_list_servers::process_list_servers($role, $level, $user->user_login, !empty($userdata['user_pass']) ? $userdata['user_pass'] : '', $user->user_email, $user->first_name, $user->last_name, $_SERVER['REMOTE_ADDR'], TRUE, TRUE, $user_id);
             } else {
                 if ($role && $level >= 0 && $GLOBALS['WS_PLUGIN__']['s2member']['o']['custom_reg_opt_in']) {
                     c_ws_plugin__s2member_list_servers::process_list_server_removals($role, $level, $user->user_login, !empty($userdata['user_pass']) ? $userdata['user_pass'] : '', $user->user_email, $user->first_name, $user->last_name, $_SERVER['REMOTE_ADDR'], TRUE, $user_id);
                 }
             }
             $lwp = c_ws_plugin__s2member_login_redirects::login_redirection_url($user);
             $lwp = !$lwp ? get_page_link($GLOBALS['WS_PLUGIN__']['s2member']['o']['login_welcome_page']) : $lwp;
             if (empty($_p['ws_plugin__s2member_sc_profile_save'])) {
                 echo '<script type="text/javascript">' . "\n";
                 echo "if(window.parent && window.parent != window) { window.parent.alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x('Profile updated successfully.', 's2member-front', 's2member')) . "'); window.parent.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($lwp) . "'; }";
                 echo "else if(window.opener) { window.alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x('Profile updated successfully.', 's2member-front', 's2member')) . "'); window.opener.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($lwp) . "'; window.close(); }";
                 echo "else { alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x('Profile updated successfully.', 's2member-front', 's2member')) . "'); window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq($lwp) . "'; }";
                 echo '</script>' . "\n";
                 exit;
             }
         }
     }
     do_action('ws_plugin__s2member_after_handle_profile_modifications', get_defined_vars());
 }
 /**
  * Widget display.
  *
  * @package s2Member\Widgets
  * @since 1.5
  *
  * @param array $args Optional. An array of basic settings.
  * @param array $instance Optional. An array of options for this instance.
  * @return null
  */
 public function widget($args = FALSE, $instance = FALSE)
 {
     $options = c_ws_plugin__s2member_pro_login_widget::configure_options_and_their_defaults((array) $instance);
     /**/
     eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
     do_action("ws_plugin__s2member_pro_login_widget_before_display", get_defined_vars(), $this);
     unset($__refs, $__v);
     /* Unset defined __refs, __v. */
     /**/
     echo $args["before_widget"];
     /* OK, here we go into this widget. */
     /**/
     if (is_user_logged_in() && strlen($options["profile_title"]) || !is_user_logged_in() && strlen($options["title"])) {
         echo $args["before_title"] . apply_filters("widget_title", $options[is_user_logged_in() ? "profile_title" : "title"]) . $args["after_title"];
     }
     /**/
     eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
     do_action("ws_plugin__s2member_pro_login_widget_during_display_before", get_defined_vars(), $this);
     unset($__refs, $__v);
     /* Unset defined __refs, __v. */
     /**/
     if (!is_user_logged_in()) {
         $links = c_ws_plugin__s2member_cache::cached_page_links();
         /**/
         $ops_page = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"];
         /**/
         if ($ops_page && is_page($ops_page) && !empty($_GET["_s2member_seeking"]["_uri"])) {
             $seeking = trim(base64_decode(trim(stripslashes((string) $_GET["_s2member_seeking"]["_uri"]))));
         }
         /**/
         $options["login_redirect"] = $options["login_redirect"] === "%%previous%%" && $ops_page && is_page($ops_page) && empty($seeking) ? "" : $options["login_redirect"];
         /**/
         $redirect_to = preg_replace("/%%previous%%/i", !empty($seeking) ? $seeking : $_SERVER["REQUEST_URI"], $redirect_to = $options["login_redirect"]);
         $redirect_to = preg_replace("/%%home%%/i", home_url("/"), $redirect_to);
         /**/
         echo '<div class="ws-plugin--s2member-pro-login-widget">' . "\n";
         /**/
         echo '<form method="post" action="' . esc_attr(wp_login_url()) . '" class="ws-plugin--s2member-pro-login-widget-form">' . "\n";
         /**/
         echo '<div class="ws-plugin--s2member-pro-login-widget-username">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-login-widget-username">' . _x("Username", "s2member-front", "s2member") . ':</label><br />' . "\n";
         echo '<input type="text" name="log" id="ws-plugin--s2member-pro-login-widget-username" title="Username" />' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-plugin--s2member-pro-login-widget-password">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-login-widget-password">' . _x("Password", "s2member-front", "s2member") . ':</label><br />' . "\n";
         echo '<input type="password" name="pwd" id="ws-plugin--s2member-pro-login-widget-password" title="Password" />' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-plugin--s2member-pro-login-widget-lost-password">' . "\n";
         $reg_cookies_ok_url = is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site() ? c_ws_plugin__s2member_utils_urls::wp_signup_url() : c_ws_plugin__s2member_utils_urls::wp_register_url();
         echo $options["signup_url"] ? '<a href="' . esc_attr($options["signup_url"] !== "%%automatic%%" ? $options["signup_url"] : (c_ws_plugin__s2member_register_access::reg_cookies_ok() ? $reg_cookies_ok_url : $links["membership_options_page"])) . '" tabindex="-1">' . _x("signup now", "s2member-front", "s2member") . '</a> | ' : '';
         echo '<a href="' . esc_attr(wp_lostpassword_url()) . '" tabindex="-1">' . _x("forgot password?", "s2member-front", "s2member") . '</a>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-plugin--s2member-pro-login-widget-remember-me">' . "\n";
         echo '<label><input type="checkbox" name="rememberme" value="forever" />' . _x("Remember Me", "s2member-front", "s2member") . '</label>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '<div class="ws-plugin--s2member-pro-login-widget-submit">' . "\n";
         echo $redirect_to ? '<input type="hidden" name="redirect_to" value="' . esc_attr($redirect_to) . '" />' . "\n" : '';
         echo '<input type="submit" value="' . esc_attr(_x("Log Me In", "s2member-front", "s2member")) . '" />' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '</form>' . "\n";
         /**/
         echo '<div class="ws-plugin--s2member-pro-login-widget-code">' . "\n";
         /**/
         if (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) {
             echo do_shortcode(trim($options["logged_out_code"]));
         } else {
             /* Otherwise, it's OK to execute PHP code. */
             echo do_shortcode(c_ws_plugin__s2member_utilities::evl(trim($options["logged_out_code"])));
         }
         /**/
         echo '</div>' . "\n";
         /**/
         echo '<div style="clear:both;"></div>' . "\n";
         /**/
         echo '</div>' . "\n";
     } else {
         if (is_user_logged_in() && is_object($user = wp_get_current_user()) && !empty($user->ID) && ($user_id = $user->ID)) {
             $links = c_ws_plugin__s2member_cache::cached_page_links();
             /**/
             $ops_page = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"];
             $welcome_page = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"];
             /**/
             $options["logout_redirect"] = $options["logout_redirect"] === "%%previous%%" && $ops_page && is_page($ops_page) ? "" : $options["logout_redirect"];
             $options["logout_redirect"] = $options["logout_redirect"] === "%%previous%%" && $welcome_page && is_page($welcome_page) ? "" : $options["logout_redirect"];
             /**/
             $redirect_to = preg_replace("/%%previous%%/i", $_SERVER["REQUEST_URI"], $redirect_to = $options["logout_redirect"]);
             $redirect_to = preg_replace("/%%home%%/i", home_url("/"), $redirect_to);
             /**/
             echo '<div id="ws-plugin--s2member-pro-login-widget" class="ws-plugin--s2member-pro-login-widget">' . "\n";
             /**/
             echo '<div class="ws-plugin--s2member-pro-login-widget-profile-summary">' . "\n";
             /**/
             echo $options["display_gravatar"] ? ($options["link_gravatar"] ? '<a href="http://www.gravatar.com/" target="_blank">' : '') . get_avatar($user_id, 48) . ($options["link_gravatar"] ? '</a>' : '') . "\n" : '';
             /**/
             echo $options["display_name"] ? '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-name">' . esc_html($user->display_name) . '</div>' . "\n" : '';
             /**/
             echo '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-code">' . "\n";
             /**/
             if (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) {
                 echo do_shortcode(trim($options["logged_in_code"]));
             } else {
                 /* Otherwise, it's OK to execute PHP code. */
                 echo do_shortcode(c_ws_plugin__s2member_utilities::evl(trim($options["logged_in_code"])));
             }
             /**/
             echo '</div>' . "\n";
             /**/
             echo $options["my_account_url"] ? '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-my-account"><a href="' . esc_attr($options["my_account_url"] !== "%%automatic%%" ? c_ws_plugin__s2member_login_redirects::fill_login_redirect_rc_vars($options["my_account_url"]) : (($login_redirection_url = c_ws_plugin__s2member_login_redirects::login_redirection_url($user)) ? $login_redirection_url : $links["login_welcome_page"])) . '">' . _x("My Account", "s2member-front", "s2member") . '</a></div>' . "\n" : '';
             echo $options["my_profile_url"] ? '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-edit-profile"><a href="' . ($options["my_profile_url"] !== "%%automatic%%" ? esc_attr(c_ws_plugin__s2member_login_redirects::fill_login_redirect_rc_vars($options["my_profile_url"])) : esc_attr(site_url("/?s2member_profile=1")) . '" onclick="if(!window.open(\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr(site_url("/?s2member_profile=1"))) . '\',\'_profile\', \'width=600,height=400,left=\'+((screen.width/2)-(600/2))+\',screenX=\'+((screen.width/2)-(600/2))+\',top=\'+((screen.height/2)-(400/2))+\',screenY=\'+((screen.height/2)-(400/2))+\',location=0,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1\')) alert(\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x("Please disable popup blockers and try again!", "s2member-front", "s2member")) . '\'); return false;') . '">' . _x("Edit My Profile", "s2member-front", "s2member") . '</a></div>' . "\n" : '';
             echo '<div class="ws-plugin--s2member-pro-login-widget-profile-summary-logout"><a href="' . esc_attr(wp_logout_url($redirect_to)) . '">' . _x("Logout", "s2member-front", "s2member") . '</a></div>' . "\n";
             /**/
             echo '<div style="clear:both;"></div>' . "\n";
             /**/
             echo '</div>' . "\n";
             /**/
             echo '</div>' . "\n";
         }
     }
     /**/
     eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
     do_action("ws_plugin__s2member_pro_login_widget_during_display_after", get_defined_vars(), $this);
     unset($__refs, $__v);
     /* Unset defined __refs, __v. */
     /**/
     echo $args["after_widget"];
     /**/
     do_action("ws_plugin__s2member_pro_login_widget_after_display", get_defined_vars(), $this);
     /**/
     return;
     /* Return for uniformity. */
 }
Пример #23
0
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     echo '<div class="ws-menu-page-toolbox">' . "\n";
     c_ws_plugin__s2member_menu_pages_tb::display();
     echo '</div>' . "\n";
     echo '<h2>Multisite Config</h2>' . "\n";
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     if (is_multisite() && is_main_site()) {
         echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
         echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr(wp_create_nonce("ws-plugin--s2member-options-save")) . '" />' . "\n";
         echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
         do_action("ws_plugin__s2member_during_mms_ops_page_before_left_sections", get_defined_vars());
         if (apply_filters("ws_plugin__s2member_during_mms_ops_page_during_left_sections_display_mms_patches", true, get_defined_vars())) {
             do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_before_mms_patches", get_defined_vars());
             echo '<div class="ws-menu-page-group" title="Multisite WordPress Patches" default-state="open">' . "\n";
             echo '<div class="ws-menu-page-section ws-plugin--s2member-mms-patches-section">' . "\n";
             echo '<img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/small-icon.png" title="s2Member (a Membership management system for WordPress)" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
             echo '<h3>Multisite WordPress Patches (required for compatiblity)</h3>' . "\n";
             echo '<p>In order for s2Member to function properly in a Multisite environment, you MUST implement four patches. One goes into your <code>/wp-login.php</code> file, one into <code>/wp-includes/load.php</code>, one into <code>/wp-includes/ms-functions.php</code>, and another into <code>/wp-admin/user-new.php</code>. Please use the automatic patcher below. All you do is check the box &amp; click Save.</p>' . "\n";
             do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_during_mms_patches", get_defined_vars());
             echo '<table class="form-table">' . "\n";
             echo '<tbody>' . "\n";
             echo '<tr>' . "\n";
             echo '<th>' . "\n";
             echo '<label for="ws-plugin--s2member-mms-auto-patch">' . "\n";
             echo 'Patch Automatically? (the easiest way)' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td>' . "\n";
             if (defined("DISALLOW_FILE_MODS") && DISALLOW_FILE_MODS) {
                 echo '<select name="ws_plugin__s2member_mms_auto_patch" id="ws-plugin--s2member-mms-auto-patch" disabled="disabled">' . "\n";
                 echo '<option value="0" selected="selected">No (I\'ll patch WordPress myself)</option>' . "\n";
                 echo '</select><br />' . "\n";
                 echo '<em class="ws-menu-page-hilite">This is now locked. Your <code>/wp-config.php</code> file says: <code>DISALLOW_FILE_MODS = true</code></em>.' . "\n";
             } else {
                 echo '<select name="ws_plugin__s2member_mms_auto_patch" id="ws-plugin--s2member-mms-auto-patch">' . "\n";
                 echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_auto_patch"] ? ' selected="selected"' : '') . '>Yes (automatically patch WordPress)</option>' . "\n";
                 echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_auto_patch"] ? ' selected="selected"' : '') . '>No (I\'ll patch WordPress myself)</option>' . "\n";
                 echo '</select><br />' . "\n";
                 echo '<em class="ws-menu-page-hilite">These files MUST be patched, each time you upgrade the WordPress core. If you set this option to <code>Yes (Patch Automatically)</code>, s2Member will patch your installation now, and also in the future, should you upgrade to newer version. That way, you won\'t need to patch manually each time WordPress is upgraded.</em>' . "\n";
             }
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '<div class="ws-menu-page-hr"></div>' . "\n";
             echo '<div id="ws-plugin--s2member-mms-patches-details-wrapper">' . "\n";
             echo '<h3>Rather Do It Yourself? (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-patches-details\').toggle(); return false;" class="ws-dotted-link">manual instructions</a>)</h3>' . "\n";
             echo '<div id="ws-plugin--s2member-mms-patches-details" style="display:none;">' . "\n";
             echo '<p><strong>Patch #1</strong> ( /wp-login.php )</p>' . "\n";
             echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/mms-patch-wp-login.x-php")) . '</p>' . "\n";
             echo '<p><strong>Patch #2</strong> ( /wp-includes/load.php )</p>' . "\n";
             echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/mms-patch-load.x-php")) . '</p>' . "\n";
             echo '<p><strong>Patch #3</strong> ( /wp-admin/user-new.php )</p>' . "\n";
             echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/mms-patch-user-new.x-php")) . '</p>' . "\n";
             echo '<p><strong>Patch #4</strong> ( /wp-includes/ms-functions.php )</p>' . "\n";
             echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/mms-patch-ms-functions.x-php")) . '</p>' . "\n";
             echo '<p><em class="ws-menu-page-hilite">Don\'t forget to patch these files again, each time you upgrade the WordPress core.</em></p>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
             do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_after_mms_patches", get_defined_vars());
         }
         if (apply_filters("ws_plugin__s2member_during_mms_ops_page_during_left_sections_display_mms_registration", true, get_defined_vars())) {
             do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_before_mms_registration", get_defined_vars());
             echo '<div class="ws-menu-page-group" title="Multisite Registration Configuration" default-state="open">' . "\n";
             echo '<div class="ws-menu-page-section ws-plugin--s2member-mms-registration-section">' . "\n";
             echo '<img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member (a Membership management system for WordPress)" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
             echo '<h3>Multisite Registration (Main Site Configuration)</h3>' . "\n";
             echo '<p>s2Member supports Free Subscribers <em>(at Level #0)</em>, and several Primary Roles created by the s2Member plugin (<em> i.e. s2Member Levels 1-4, or up to the number of configured Levels )</em>. If you want your visitors to be capable of registering absolutely free, you will want to "allow" Open Registration. Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0.</p>' . "\n";
             echo '<p><strong>Running A Multisite Blog Farm?</strong> With Multisite Networking enabled, your Main Site could ALSO offer a Customer access to create a Blog of their own <em>(optional)</em>, where a Customer becomes a "Member" of your Main Site, and also a Blog Owner/Administrator of at least one other Blog on your Network. With s2Member installed <em>(Network wide)</em>, each of your Blog Owners could offer Membership too, using a single copy of the s2Member plugin, which is a great selling point<em>!</em> We refer to this type of installation as a Multisite Blog Farm.</p>' . "\n";
             echo '<p>Multisite Networking makes a new Registration Form available <em>(driven by your theme)</em>; which we refer to as: <code>/wp-signup.php</code>. If, and only if, you\'re planning to offer Blogs, you MUST use <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_signup_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">/wp-signup.php</a>, instead of using the Standard Login/Registration Form. In a Multisite installation, we refer to the Standard Login/Registration Form, as: <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">/wp-login.php?action=register</a>. If you\'re planning to offer Membership Access only, and NOT Blogs, you can simply use the <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">Standard Login/Registration Form</a>, which is easily customized through <code>s2Member -› General Options -› Login/Registration Design</code>.</p>' . "\n";
             echo '<p>In either case, s2Member Pro Forms are possible too. If you\'ve purchased s2Member Pro, you could use Pro Forms instead of these WordPress defaults. That being said, even with s2Member Pro Forms, if you are offering Blogs, you will still need to facilitate the actual creation of each Blog through <code>/wp-signup.php</code>. In other words, Customers can register through s2Member Pro Forms, and even checkout. But when it comes time to setup a new Blog, you will need to redirect your Customer to <code>/wp-signup.php</code>, while they are logged-in. This will allow them to create a new Blog on your Network. That is, if they are allowed to <em>(based on your configuration below)</em>.</p>' . "\n";
             echo c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '<p><em><strong>BuddyPress:</strong> BuddyPress will use its own Registration Form, powered by your theme.<br />(BuddyPress can handle both Membership and Blog creation in its integration)<br />(<a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::bp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your BuddyPress Registration Form.\\n* However, you will probably be redirected away from this BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.\');">' . esc_html(c_ws_plugin__s2member_utils_urls::bp_register_url()) . '</a>)</em></p>' . "\n" : '';
             do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_during_mms_registration", get_defined_vars());
             echo '<div id="ws-plugin--s2member-mms-registration-support-package-details-wrapper">' . "\n";
             echo '<h4 style="margin-bottom:0;">Running a Multisite Blog Farm? (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-registration-support-package-details\').toggle(); return false;" class="ws-dotted-link">click here / please read</a>)</h4>' . "\n";
             echo '<div id="ws-plugin--s2member-mms-registration-support-package-details" style="display:none;">' . "\n";
             echo '<p>The most important thing to do when setting up a Blog Farm with s2Member, is to add this line to your <code>/wp-config.php</code> file: <code><span style="color:#0000BB;">define</span><span style="color:#007700;">(</span><span style="color:#DD0000;">"MULTISITE_FARM"</span>, <span style="color:#0000BB;">true</span><span style="color:#007700;">);</span></code>. This will add a default layer of security, to all Blogs within your Network, with respect to s2Member. <strong>But, before you go live</strong>, please contact <a href="' . esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Pro Module / Prices")) . '" target="_blank" rel="external">s2Member.com</a> for full documentation. There is some additional functionality that can be enabled for security on a Blog Farm installation; and also some menus/documentation/functionality that can be disabled. You will be asked to purchase our <a href="' . esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Pro Module / Prices")) . '" target="_blank" rel="external">Network Support Package</a> when you need assistance in this regard.</p>' . "\n";
             echo '<p>Multisite Blog Farms require a site owner that fully understands the potential security risks associated with Blog Farming. s2Member\'s <a href="' . esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Pro Module / Prices")) . '" target="_blank" rel="external">Network Support Package</a> provides you with the information you need, and priority support for anything about s2Member that you don\'t understand. In addition, our Network Support Package includes a lengthy PDF file that details a list of things affected by <code><span style="color:#0000BB;">define</span><span style="color:#007700;">(</span><span style="color:#DD0000;">"MULTISITE_FARM"</span>, <span style="color:#0000BB;">true</span><span style="color:#007700;">);</span></code>, best practices, and other supplemental documentation focused on Blog Farms.</p>' . "\n";
             echo '<p><em><strong>Definition of a Multisite Blog Farm:</strong> If your Network is making it possible for "Members" of your Main Site, to create and/or manage Blogs (in any way), s2Member will consider your installation to be a Multisite Blog Farm. That being said, some site owners run a Multisite Network for the purpose of maintaining their own sites. The term Multisite Blog Farm does NOT apply to a Network that hosts multiple Child Blogs, all of which are operated by a single site owner and/or a single company. Again, a Multisite Blog Farm (in the eyes of s2Member), is any Network that is making it possible for "Members" of its Main Site, to create and/or manage Blogs; where one or more of these Child Blogs is being administered by a Customer (e.g. if you offer both Membership and Blog creation, as configured below).</em></p>' . "\n";
             echo '<p><em><strong>When NOT to run a Multisite Blog Farm:</strong> If you run a Multisite Network for the purpose of maintaining your own sites. You should NOT run a Multisite Blog Farm. You can still activate s2Member Network-wide, if you like (optional), but the advanced security considerations offered through s2Member\'s Multisite Blog Farm functionality are NOT needed in this case; because all of the Child Blogs in your Network belong to trusted Administrators (i.e. your Customers are NOT going to run Child Blogs on your Network in this case).</em></p>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
             echo '<div class="ws-menu-page-hr"></div>' . "\n";
             echo '<table class="form-table">' . "\n";
             echo '<tbody>' . "\n";
             echo '<tr>' . "\n";
             echo '<th>' . "\n";
             echo '<label for="ws-plugin--s2member-mms-registration-file">' . "\n";
             echo 'What Do You Plan To Offer? (please choose one)' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td>' . "\n";
             if (defined("MULTISITE_FARM") && MULTISITE_FARM) {
                 echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file" disabled="disabled">' . "\n";
                 echo '<option value="wp-signup" selected="selected">Blog Farm (I plan to offer both Membership &amp; Blog creation)</option>' . "\n";
                 echo '</select><br />' . "\n";
                 echo '<em class="ws-menu-page-hilite">This is now locked. Your <code>/wp-config.php</code> file says: <code>MULTISITE_FARM = true</code></em>.' . "\n";
             } else {
                 echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file">' . "\n";
                 echo '<option value="wp-login"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-login" ? ' selected="selected"' : '') . '>Membership Only (I\'m NOT offering Blogs)</option>' . "\n";
                 echo '<option value="wp-signup"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-signup" ? ' selected="selected"' : '') . '>Blog Farm (I plan to offer both Membership &amp; Blog creation)</option>' . "\n";
                 echo '</select><br />' . "\n";
                 echo 'Depending on your selection, the options below may change.' . "\n";
             }
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '<div class="ws-menu-page-hr"></div>' . "\n";
             echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-login" style="margin:0;">' . "\n";
             echo '<tbody>' . "\n";
             echo '<tr>' . "\n";
             echo '<th style="padding-top:0;">' . "\n";
             echo '<label for="ws-plugin--s2member-allow-subscribers-in">' . "\n";
             echo 'Your Main Site / Allow Open Registration? (via <code>wp-login.php?action=register</code>)' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td>' . "\n";
             echo '<select name="ws_plugin__s2member_allow_subscribers_in" id="ws-plugin--s2member-allow-subscribers-in">' . "\n";
             echo '<option value="0"' . (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"] ? ' selected="selected"' : '') . '>No (do NOT allow Open Registration)</option>' . "\n";
             echo '<option value="1"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"] ? ' selected="selected"' : '') . '>Yes (allow Open Registration; Free Subscribers at Level #0)</option>' . "\n";
             echo '</select><br />' . "\n";
             echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">wp-login.php?action=register</a> (on your Main Site). When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup" style="margin:0;">' . "\n";
             echo '<tbody>' . "\n";
             echo '<tr>' . "\n";
             echo '<th style="padding-top:0;">' . "\n";
             echo '<label for="ws-plugin--s2member-mms-registration-grants">' . "\n";
             echo 'Your Main Site / Allow Open Registration? (via <code>wp-signup.php</code>)' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td style="padding-bottom:0;">' . "\n";
             echo '<select name="ws_plugin__s2member_mms_registration_grants" id="ws-plugin--s2member-mms-registration-grants">' . "\n";
             echo '<option value="none"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "none" ? ' selected="selected"' : '') . '>No (do NOT allow Open Registration)</option>' . "\n";
             echo '<option value="user"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "user" ? ' selected="selected"' : '') . '>Yes (allow Open Registration; Free Subscribers at Level #0)</option>' . "\n";
             echo '<option value="all"' . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "all" ? ' selected="selected"' : '') . '>Yes (allow Open Registration; Free Subscribers, with a free Blog too)</option>' . "\n";
             echo '</select><br />' . "\n";
             echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . esc_attr(c_ws_plugin__s2member_utils_urls::wp_signup_url()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times (for testing purposes), regardless of configuration.' . (c_ws_plugin__s2member_utils_conds::bp_is_installed() ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">wp-signup.php</a> (on your Main Site).' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup ws-plugin--s2member-mms-registration-wp-signup-blogs-level0">' . "\n";
             echo '<tbody>' . "\n";
             echo '<tr>' . "\n";
             echo '<th>' . "\n";
             echo '<label for="ws-plugin--s2member-mms-registration-blogs-level0">' . "\n";
             echo 'Level #0 (Free Subscribers):' . "\n";
             echo '</label>' . "\n";
             echo '</th>' . "\n";
             echo '</tr>' . "\n";
             echo '<tr>' . "\n";
             echo '<td style="padding-bottom:0;">' . "\n";
             echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_mms_registration_blogs_level0" id="ws-plugin--s2member-mms-registration-blogs-level0" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_blogs_level0"]) . '" /><br />' . "\n";
             echo 'How many blogs can a Free Subscriber create?' . "\n";
             echo '</td>' . "\n";
             echo '</tr>' . "\n";
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '<div class="ws-menu-page-hr ws-plugin--s2member-mms-registration-wp-signup"></div>' . "\n";
             echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup" style="margin:0;">' . "\n";
             echo '<tbody>' . "\n";
             for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
                 echo '<tr>' . "\n";
                 echo '<th style="padding-top:0;">' . "\n";
                 echo '<label for="ws-plugin--s2member-mms-registration-blogs-level' . $n . '">' . "\n";
                 echo 'Membership Level #' . $n . ' / Maximum Blogs Allowed:' . "\n";
                 echo '</label>' . "\n";
                 echo '</th>' . "\n";
                 echo '</tr>' . "\n";
                 echo '<tr>' . "\n";
                 echo '<td>' . "\n";
                 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_mms_registration_blogs_level' . $n . '" id="ws-plugin--s2member-mms-registration-blogs-level' . $n . '" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_blogs_level" . $n]) . '" /><br />' . "\n";
                 echo 'How many blogs can a Member ( at Level #' . $n . ' ) create?' . "\n";
                 echo '</td>' . "\n";
                 echo '</tr>' . "\n";
             }
             echo '</tbody>' . "\n";
             echo '</table>' . "\n";
             echo '</div>' . "\n";
             echo '</div>' . "\n";
             do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_after_mms_registration", get_defined_vars());
         }
         do_action("ws_plugin__s2member_during_mms_ops_page_after_left_sections", get_defined_vars());
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p class="submit"><input type="submit" value="Save All Changes" /></p>' . "\n";
         echo '</form>' . "\n";
     } else {
         echo '<p style="margin-top:0;"><span class="ws-menu-page-hilite">Your WordPress installation does not have Multisite Networking enabled.<br />Which is perfectly OK :-) Multisite Networking is 100% completely optional.</span></p>' . "\n";
         echo '<img src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member (a Membership management system for WordPress)" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
         if (file_exists($ws_plugin__s2member_temp = dirname(dirname(dirname(__FILE__))) . "/readme-ms.txt")) {
             echo '<div class="ws-menu-page-hr"></div>' . "\n";
             if (!function_exists("NC_Markdown")) {
                 include_once dirname(dirname(__FILE__)) . "/externals/markdown/nc-markdown.inc.php";
             }
             $ws_plugin__s2member_temp = file_get_contents($ws_plugin__s2member_temp);
             $ws_plugin__s2member_temp = preg_replace("/(\\=)( )(.+?)( )(\\=)/", "<h3>\$3</h3>", $ws_plugin__s2member_temp);
             $ws_plugin__s2member_temp = NC_Markdown($ws_plugin__s2member_temp);
             echo preg_replace("/(\\<a)( href)/i", "\$1" . ' target="_blank" rel="nofollow external"' . "\$2", $ws_plugin__s2member_temp);
         }
     }
     echo '</td>' . "\n";
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
 }
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     /**/
     echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
     echo '<h2>s2Member® / ClickBank® Buttons</h2>' . "\n";
     /**/
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     /**/
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<div class="ws-menu-page-group" title="ClickBank® Buttons For Level #' . $n . ' Access">' . "\n";
         /**/
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-level' . $n . '-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Level #' . $n . ' Access</h3>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special ClickBank® Buttons are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their Membership, or fails to make payments on time, s2Member will automatically terminate their Membership privileges. s2Member makes extensive use of the ClickBank® IPN service. s2Member receives updates from ClickBank® behind-the-scene. <em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
         /**/
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-level' . $n . '-shortcode">' . "\n";
         echo 'Button Code<br />For Level #' . $n . ':<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-pro-level' . $n . '-button-prev"></div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         /**/
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         echo '<p>ClickBank® Product Type: <select id="ws-plugin--s2member-pro-level' . $n . '-type">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-product-types.php"))) . '</select>' . "\n";
         echo '<p>ClickBank® Product Item #: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-item-number" value="" size="5" /> <a href="#" onclick="alert(\'This MUST correlate with a Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a> &nbsp;&nbsp;&nbsp; <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_clickbankButtonGenerate(\'level' . $n . '\');" class="button-primary" /></p>' . "\n";
         echo '<p id="ws-plugin--s2member-pro-level' . $n . '-term-line">Fixed-Term Access: <select id="ws-plugin--s2member-pro-level' . $n . '-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-fixed-terms.php"))) . '</select> <a href="#" onclick="alert(\'For Standard Products, a Fixed-Term allows s2Member to configure the Auto-EOT ( End Of Term ) Time after checkout is completed through ClickBank®.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p id="ws-plugin--s2member-pro-level' . $n . '-periods-line">ClickBank® Trial Period: <select id="ws-plugin--s2member-pro-level' . $n . '-p1">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-trial-p1s.php"))) . '</select>, then Re-Bill: <select id="ws-plugin--s2member-pro-level' . $n . '-p3">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-regular-p3s.php"))) . '</select> <a href="#" onclick="alert(\'This MUST correlate with a Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-desc" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) . ' / description and pricing details here." size="70" /> <a href="#" onclick="alert(\'This can be worded however you like. It does NOT need to be an exact match to the Product in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma-delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/clickbank-checkout-button-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%item%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr("0")), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($n)), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '</div>' . "\n";
     }
     /**/
     echo '<div class="ws-menu-page-group" title="ClickBank® Modification/Cancellation Buttons">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-cancellation-buttons-section">' . "\n";
     echo '<h3>One Button Does It All For Modifications/Cancellations ( copy/paste )</h3>' . "\n";
     echo '<p>Every ClickBank® Recurring Subscription can be modified by the Customer, or even cancelled by the Customer through ClickBank®. It\'s very simple. A Member clicks a Modification/Cancellation Button. This brings the Customer to an "Order Lookup" screen at ClickBank.com. Here they\'ll have easy access to make any changes they like. When important changes occur ( such as a cancellation ), information regarding this event will be relayed back to s2Member through ClickBank\'s IPN service. s2Member will react appropriately at that time.</p>' . "\n";
     echo '<p><em><strong>*Understanding Cancellations*</strong> It\'s important to realize that a Cancellation is not an EOT ( End Of Term ). All that happens during a Cancellation event, is that billing is stopped, and it\'s understood that the Customer is going to lose access, at some point in the future. This does NOT mean, that access will be revoked immediately. A separate EOT event will automatically handle a (demotion or deletion) later, at the appropriate time; which could be several days, or even a year after the Cancellation took place.</em></p>' . "\n";
     echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Member\'s Subscription has been cancelled through ClickBank®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when an EOT ( End Of Term ) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member.</em></p>' . "\n";
     echo '<p><em>s2Member will not process an EOT ( End Of Term ) until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<th class="ws-menu-page-th-side">' . "\n";
     echo '<label for="ws-plugin--s2member-pro-cancellation-shortcode">' . "\n";
     echo 'Button Code<br />For Cancellations:<br /><br />' . "\n";
     echo '<div id="ws-plugin--s2member-pro-cancellation-button-prev">' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/buttons/clickbank-cancellation-button.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member_pro"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr(site_url())), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/&amp;/", "&", $ws_plugin__s2member_pro_temp_s);
     /* Match this with the JavaScript generator. */
     echo preg_replace("/\\<a/", '<a target="_blank"', $ws_plugin__s2member_pro_temp_s);
     echo '</div>' . "\n";
     echo '</label>' . "\n";
     echo '</th>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<p>No configuration necessary.</p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td colspan="2">' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/clickbank-cancellation-button-shortcode.php")));
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-cancellation-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
         echo '<div class="ws-menu-page-group" title="ClickBank® Capability (Buy Now) Buttons">' . "\n";
         /**/
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-ccap-buttons-section">' . "\n";
         echo '<h3>Button Code Generator For Independent Custom Capabilities</h3>' . "\n";
         echo '<p>This is VERY advanced. For further details, please check your Dashboard: <code>s2Member -> API Scripting -> Custom Capabiities</code>.</p>' . "\n";
         echo '<p>With s2Member, you can sell one or more Custom Capabilities using Buy Now functionality, to "existing" Users/Members, regardless of which Membership Level they have on your site <em>( i.e. you could even sell Independent Custom Capabilities to Users at Membership Level #0, normally referred to as Free Subscribers, if you like )</em>. So this is quite flexible. Independent Custom Capabilities do NOT rely on any specific Membership Level. That\'s why s2Member refers to these as `Independent` Custom Capabilities, because you can sell Capabilities this way, through Buy Now functionality, and the Customer\'s Membership Level Access, along with any existing paid Subscription they may already have with you, will remain completely unaffected. That being said, if you intend to charge a recurring fee for Custom Capabilities, please use a <code>Membership Level# Button</code> instead; because Independent Custom Capabilities can only be sold through Buy Now functionality.</p>' . "\n";
         echo '<p>Independent Custom Capabilities are added to a Customer\'s account immediately after checkout, and the Customer will have the Custom Capabilities for as long as their Membership lasts, based on their primary Subscription with your site, and/or forever, if they have a Lifetime account with you. In other words, Independent Custom Capabilities will exist on the Customer\'s account forever, or until an EOT <em>( End Of Term )</em> occurs on their primary Subscription with you; in which case s2Member would demote or delete the Customer\'s account <em>( based on your EOT configuration )</em>, and all Custom Capabilities are removed as well.</p>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each set of Custom Capabilities that you plan to sell. Then press (Generate Button Code). These special ClickBank® Buttons are customized to work with s2Member seamlessly. The Customer will be granted additional access to one or more Custom Capabilities that you specify; while the Customer\'s Membership Level Access and any existing paid Subscription they may already have with you, will remain completely unaffected.</p>' . "\n";
         echo '<p><em><strong>*Important Note*</strong> Independent Custom Capability Buttons should ONLY be displayed to existing Users/Members, and they MUST be logged-in, BEFORE clicking this Button. Otherwise, post-processing of their transaction will fail to recognize the Customer\'s existing account within WordPress®. Please display this Button only to Users/Members that are already logged into their account ( perhaps in your Login Welcome Page for s2Member ), or in another location where you can be absolutely sure that a User/Member is logged in. s2Member\'s Simple Conditionals could also be used to ensure a User/Member is logged in, by wrapping your Shortcode within a Conditional test. For further details, please see: <code>s2Member -> API Scripting -> Simple Conditionals</code>.</em></p>' . "\n";
         echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
         /**/
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<th class="ws-menu-page-th-side">' . "\n";
         echo '<label for="ws-plugin--s2member-pro-ccap-shortcode">' . "\n";
         echo 'Button Code<br />For Capabilities:<br /><br />' . "\n";
         echo '<div id="ws-plugin--s2member-pro-ccap-button-prev"></div>' . "\n";
         echo '</label>' . "\n";
         echo '</th>' . "\n";
         /**/
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         echo '<p>ClickBank® Product Type: <select id="ws-plugin--s2member-pro-ccap-type">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-ccap-product-types.php"))) . '</select>' . "\n";
         echo '<p>ClickBank® Product Item #: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-item-number" value="" size="5" /> <a href="#" onclick="alert(\'This MUST correlate with a Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a> &nbsp;&nbsp;&nbsp; <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_clickbankCcapButtonGenerate();" class="button-primary" /></p>' . "\n";
         echo '<p>Fixed-Term Access: <select id="ws-plugin--s2member-pro-ccap-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-ccap-fixed-terms.php"))) . '</select> <a href="#" onclick="alert(\'Independent Custom Capabilities will exist on the Customer\\\'s account forever, or until an EOT ( End Of Term ) occurs on their primary Subscription with you, if one exists.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-desc" value="Description and pricing details here." size="70" /> <a href="#" onclick="alert(\'This can be worded however you like. It does NOT need to be an exact match to the Product in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
         echo '<p>Custom Capabilities ( comma-delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-ccap-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         /**/
         echo '<td colspan="2">' . "\n";
         echo '<form onsubmit="return false;">' . "\n";
         echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/clickbank-ccaps-checkout-button-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%item%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr("0")), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         /**/
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         /**/
         echo '</div>' . "\n";
     }
     /**/
     echo '<div class="ws-menu-page-group" title="ClickBank® Member Registration Access Links">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-reg-links-section">' . "\n";
     echo '<h3>Registration Access Link Generator ( for Customer Service )</h3>' . "\n";
     echo '<p>s2Member automatically generates Registration Access Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Registration Access Link to be created manually, you can use this tool for that. Alternatively, you can create their account yourself/manually by going to <code>s2Member -> Add A Member</code>. Either of these methods will work fine.</p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<p>Paid Membership Level#: <select id="ws-plugin--s2member-pro-reg-link-level">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<option value="' . $n . '">s2Member Level #' . $n . '</option>' . "\n";
     }
     echo '</select></p>' . "\n";
     echo '<p>Paid Subscr. ID: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-subscr-id" value="" size="50" /> <a href="#" onclick="alert(\'The Customer\\\'s Paid Subscr. ID ( aka: ClickBank® Receipt# ) must be unique. This value can be obtained from inside your ClickBank® account. Each paying Customer MUST be associated with a unique Paid Subscr. ID. If the Customer is NOT associated with a Paid Subscr. ID, you will need to generate a unique value for this field on your own. But keep in mind, s2Member will be unable to maintain future communication with the ClickBank® IPN ( i.e. Notification ) service if this value does not reflect a real Paid Subscr. ID that exists in your ClickBank® transaction log.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>Custom String Value: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-custom" value="' . esc_attr($_SERVER["HTTP_HOST"]) . '" size="30" /> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_clickbankRegLinkGenerate();" class="button-primary" /> <img id="ws-plugin--s2member-pro-reg-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma-delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-ccaps" size="40" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></p>' . "\n";
     echo '<p>Fixed Term Length ( for Buy Now transactions ): <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-fixed-term" value="" size="10" /> <a href="#" onclick="alert(\'If the Customer purchased Membership through a Buy Now / Standard transaction ( i.e. there is no Initial/Trial Period and no recurring charges for ongoing access ), you may configure a Fixed Term Length in this field. This way the Customer\\\'s Membership Access is revoked by s2Member at the appropriate time. This will be a numeric value, followed by a space, then a single letter.\\n\\nHere are some examples:\\n\\n1 D ( this means 1 Day )\\n1 W ( this means 1 Week )\\n1 M ( this means 1 Month )\\n1 Y ( this means 1 Year )\\n1 L ( this means 1 Lifetime )\'); return false;">[?]</a></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-reg-link" style="font-family:Consolas, monospace; display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="ClickBank® Specific Post/Page (Buy Now) Buttons">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-buttons-section">' . "\n";
     echo '<h3>Button Code Generator For Specific Post/Page Buttons</h3>' . "\n";
     echo '<p>s2Member now supports an additional layer of functionality ( very powerful ), which allows you to sell access to specific Posts/Pages that you\'ve created in WordPress®. Specific Post/Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Posts/Pages using "Buy Now" Buttons, and your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be.</p>' . "\n";
     echo '<p>In other words, Customers will NOT need to login, just to receive access to the Specific Post/Page they purchased access to. s2Member will immediately redirect the Customer to the Specific Post/Page after checkout is completed successfully. An email is also sent to the Customer with a link ( see: <code>s2Member -> ClickBank® Options -> Specific Post/Page Email</code> ). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>' . "\n";
     echo '<p>Specific Post/Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Post/Page on your site; one that you created in WordPress®. A Specific Post/Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress® Post/Page that you\'ve created. To protect Specific Posts/Pages, please see: <code>s2Member -> Restriction Options -> Specific Post/Page Access</code>. Once you\'ve configured your Specific Post/Page Restrictions, those Posts/Pages will be available in the menus below.</p>' . "\n";
     echo '<p>Very simple. All you do is customize the form fields provided, for each Post/Page that you plan to sell. Then press (Generate Button Code). These special ClickBank® Buttons are customized to work with s2Member seamlessly. You can even Package Additional Posts/Pages together into one transaction. <em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your WordPress® Editor, wherever you feel it would be most appropriate. If you lose your Button Code, you\'ll need to come back &amp; re-generate a new one.</em></p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<th class="ws-menu-page-th-side">' . "\n";
     echo '<label for="ws-plugin--s2member-pro-sp-shortcode">' . "\n";
     echo 'Button Code<br />Specific Posts/Pages:<br /><br />' . "\n";
     echo '<div id="ws-plugin--s2member-pro-sp-button-prev"></div>' . "\n";
     echo '</label>' . "\n";
     echo '</th>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<p>ClickBank® Product Item #: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-item-number" value="" size="5" /> <a href="#" onclick="alert(\'This MUST correlate with a Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-sp-hours.php"))) . '</select></p>' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     /**/
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-additional-ids" multiple="multiple" style="height:100px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page ( they\\\'ll land on your Leading Post/Page after checkout ), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically ( e.g. only one Access Link is needed, and s2Member generates this automatically ). However, you will STILL need to design your Leading Post/Page ( which is what a Customer will actually land on ), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p><input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-desc" value="Description and pricing details here." size="67" /> <a href="#" onclick="alert(\'This can be worded however you like. It does NOT need to be an exact match to the Product in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_pro_clickbankSpButtonGenerate();" class="button-primary" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td colspan="2">' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/clickbank-sp-checkout-button-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%item%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr("0")), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_ds(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="ClickBank® Specific Post/Page Access Links">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-links-section">' . "\n";
     echo '<h3>Specific Post/Page Link Generator ( for Customer Service )</h3>' . "\n";
     echo '<p>s2Member automatically generates Specific Post/Page Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Specific Post/Page Link to be created manually, you can use this tool for that.</p>' . "\n";
     /**/
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     /**/
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;">' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     /**/
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-additional-ids" multiple="multiple" style="height:100px; min-width:450px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     /**/
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     /**/
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page ( they\\\'ll land on your Leading Post/Page after checkout ), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically ( e.g. only one Access Link is needed, and s2Member generates this automatically ). However, you will STILL need to design your Leading Post/Page ( which is what a Customer will actually land on ), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> Restriction Options -> Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     /**/
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/clickbank-sp-hours.php"))) . '</select> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_clickbankSpLinkGenerate();" class="button-primary" /> <img id="ws-plugin--s2member-pro-sp-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-sp-link" style="font-family:Consolas, monospace; display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="Shortcode Attributes ( Explained )">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-shortcode-attrs-section">' . "\n";
     echo '<h3>Shortcode Attributes ( Explained In Full Detail )</h3>' . "\n";
     echo '<p>When you generate a Button Code, s2Member will make a <a href="http://codex.wordpress.org/Shortcode_API#Overview" target="_blank" rel="external">Shortcode</a> available to you. Like most Shortcodes for WordPress®, s2Member reads Attributes in your Shortcode. These Attributes will be pre-configured by one of s2Member\'s Button Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
     /**/
     echo '<table class="form-table" style="margin-top:0;">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr style="padding-top:0;">' . "\n";
     /**/
     echo '<td style="padding-top:0;">' . "\n";
     echo '<ul>' . "\n";
     echo '<li><code>cancel="0"</code> Cancellation Button. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Cancellation Button, <code>1</code> = this IS a Cancellation Button.</li>' . "\n";
     echo '<li><code>cbp="325"</code> ClickBank® Product Item #, which MUST correlate with a Product you\'ve configured at ClickBank.com. <a href="#" onclick="alert(\'This MUST correlate with a Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></li>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>ccaps="music,videos"</code> A comma-delimited list of Custom Capabilities. Only valid w/ Membership Level Access and/or Independent Custom Capabilities.</li>' . "\n" : '';
     echo '<li><code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '"</code> must start with your domain. Additional values can be piped in ( ex: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3|etc"</code> ). Not valid when <code>modify|cancel="1"</code>.</li>' . "\n";
     echo '<li><code>desc="Gold Membership"</code> A brief purchase Description; which may also include pricing details. <a href="#" onclick="alert(\'This could be worded slightly different if you prefer. This does NOT need to exactly match a Product in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></li>' . "\n";
     echo '<li><code>exp="72"</code> Access Expires ( in hours ). Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>ids="14"</code> A Post/Page ID#, or a comma-delimited list of IDs. Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>image="default"</code> Button Image Location. Possible values: <code>default</code> = use the default ClickBank® Button, <code>http://...</code> = location of your custom Image.</li>' . "\n";
     echo '<li><code>level="1"</code> Membership Level [1-4] <em>( or, up to the number of configured Levels )</em>. Only valid for Buttons providing paid Membership Level Access.' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' Or, with Independent Custom Capabilities this MUST be set to <code>level="*"</code>, and <code>ccaps=""</code> must NOT be empty <em>( i.e. <code>level="*" ccaps="music,videos"</code> )</em>.') . '</li>' . "\n";
     echo '<li><code>modify="0"</code> Modification Button. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Modification Button, <code>1</code> = this IS a Modification Button.</li>' . "\n";
     echo '<li><code>output="anchor"</code> Output Type. Possible values: <code>anchor</code> = ClickBank® Button (  &lt;a&gt; anchor tag ) URL w/ ?query string, <code>url</code> = raw URL w/ ?query string.</li>' . "\n";
     echo '<li><code>rp="1"</code> Regular Period. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Must be &gt;= <code>1</code> ( ex: <code>1</code> Week, <code>2</code> Months, <code>1</code> Month, <code>3</code> Days ). <a href="#" onclick="alert(\'With the exception of Fixed-Term Access on Standard Products, this MUST correlate with a Recurring Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></li>' . "\n";
     echo '<li><code>rt="D"</code> Regular Term. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years, <code>L</code> = Lifetime. <a href="#" onclick="alert(\'With the exception of Fixed-Term Access on Standard Products, this MUST correlate with a Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></li>' . "\n";
     echo '<li><code>rr="0"</code> Recurring directive. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>0</code> = "Standard" Product, charge is NOT recurring; <code>1</code> = "Recurring" Product with possible Trial Period, and Rebill charges. <a href="#" onclick="alert(\'This MUST correlate with a Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></li>' . "\n";
     echo '<li><code>sp="0"</code> Specific Post/Page Button. Possible values: <code>0</code> = this is NOT a Specific Post/Page Access Button, <code>1</code> = this IS a Specific Post/Page Access Button.</li>' . "\n";
     echo '<li><code>tp="0"</code> Trial Period. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when you\'re selling a "Standard" ClickBank® Product. <a href="#" onclick="alert(\'This MUST correlate with a Recurring Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></li>' . "\n";
     echo '<li><code>tt="D"</code> Trial Term. Only valid w/ Membership Level Access. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years. <a href="#" onclick="alert(\'This MUST correlate with a Recurring Product that you\\\'ve configured in your ClickBank® account.\'); return false;" tabindex="-1">[?]</a></li>' . "\n";
     echo '</ul>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '<div class="ws-menu-page-group" title="s2_ Vars ( Explained )">' . "\n";
     /**/
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-s2-vars-section">' . "\n";
     echo '<h3>s2_ Variables ( Explained In Full Detail )</h3>' . "\n";
     echo '<p>When you generate a Button Code, s2Member will make a Shortcode available to you. Ultimately, your Shortcode produces a clickable link that will send Customers over to ClickBank® where they\'ll complete the checkout process. You may notice that s2Member will attach several s2_ Variables to the link it generates. These s2_ Variables will be pre-configured by one of s2Member\'s Button Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these s2_ Variables work. Below, is a brief overview of each possible s2_ Variable.</p>' . "\n";
     /**/
     echo '<table class="form-table" style="margin-top:0;">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr style="padding-top:0;">' . "\n";
     /**/
     echo '<td style="padding-top:0;">' . "\n";
     echo '<ul>' . "\n";
     echo '<li><code>&amp;s2_custom=' . esc_html($_SERVER["HTTP_HOST"]) . '</code> The domain of your site, which is passed through the `custom` attribute in your Shortcode. You can pipe in additional values if you like ( ex: <code><em>' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3</em></code> ).</li>' . "\n";
     echo '<li><code>&amp;s2_customer_ip=' . esc_html(S2MEMBER_CURRENT_USER_IP) . '</code> This is the Customer\'s IP Address via <code>$_SERVER["REMOTE_ADDR"]</code>. s2Member will store the Customer\'s IP Address in case you need it for tracking and/or affiliate program integration <em>( optional )</em>.</li>' . "\n";
     echo '<li><code>&amp;s2_desc=Brief Description</code> Description s2Member uses for your ClickBank® Product. This can/could be different from what you have on file at ClickBank® for a particular Product.</li>' . "\n";
     echo '<li><code>&amp;s2_invoice=1:music,videos:2 D</code> s2Member\'s Item Number for Membership Level Access ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) that the Subscription is for.' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' Or, with Independent Custom Capabilities this MUST have <code>level</code> set to <code>*</code> and the <code>custom_capabilities</code> section must NOT be empty <em>( i.e. <code>*:music,videos</code> )</em>.') . '</li>' . "\n";
     echo '<li><code>&amp;s2_invoice=sp:13,24,36:72</code> s2Member\'s Item Number for Specific Post/Page Access ( translates to: <code><em>sp:comma-delimited IDs:expiration hours</em></code> ).</li>' . "\n";
     echo '<li><code>&amp;s2_p1=0 D</code> For Recurring Products, this tells s2Member how many Trial Days are in your ClickBank® Product configuration.</li>' . "\n";
     echo '<li><code>&amp;s2_p3=1 M</code> For Recurring Products, this tells s2Member how your ClickBank® Product is rebilled ( <code><em>2 W = Bi-Weekly, 1 M = Monthly, 3 M = Quarterly, 1 Y = Yearly</em></code> ).</li>' . "\n";
     echo '<li><code>&amp;s2_subscr_id=s2-' . esc_html(uniqid()) . '</code> This is s2Member\'s Unique Subscr. ID for Recurring Products. For ClickBank® Recurring Products, this is stored by s2Member after checkout as the Paid Subscr. ID. Otherwise, for Standard Products, s2Member will record the ClickBank® Receipt # instead. The reason s2Member generates a unique Subscription ID, is because the Receipt # ClickBank® generates is NOT dynamic enough to handle everything s2Member makes possible. ClickBank® Receipts ( by themselves ) do NOT allow site owners to track multiple payments with a common Subscription ID. So s2Member makes up for this minor deficiency. For instance, with Recurring ClickBank® Products, s2Member\'s Subscription ID will remain constant throughout all future payments; making things easier to keep track of ( on the back-end management side of things ).</li>' . "\n";
     echo '<li><code>&amp;s2_referencing=54825</code> If a Member is logged-in when they click a Checkout Button, s2Member will tag this onto the end of the link so it can update a Customer\'s account instead of asking them to re-register after checkout. The value of this parameter will be set to the Member\'s current Paid Subscr. ID, as stored by s2Member in a previous purchase. If the Customer is NOT a paid Member ( i.e. they\'re still a Free Subscriber ), s2Member will grab the User\'s ID# in your WordPress® database instead.</li>' . "\n";
     echo '</ul>' . "\n";
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     /**/
     echo '</div>' . "\n";
     /**/
     echo '</td>' . "\n";
     /**/
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     /**/
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     /**/
     echo '</div>' . "\n";
 }
Пример #25
0
 public function __construct()
 {
     echo '<div class="wrap ws-menu-page">' . "\n";
     echo '<div class="ws-menu-page-toolbox">' . "\n";
     c_ws_plugin__s2member_menu_pages_tb::display();
     echo '</div>' . "\n";
     echo '<h2>PayPal Pro-Forms</h2>' . "\n";
     echo '<table class="ws-menu-page-table">' . "\n";
     echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
     echo '<tr class="ws-menu-page-table-tr">' . "\n";
     echo '<td class="ws-menu-page-table-l">' . "\n";
     echo '<div class="ws-menu-page-group" title="PayPal Pro Requirements">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-requirements-section">' . "\n";
     echo '<h3>Is "PayPal Payments Pro" required for me to use Pro-Forms?</h3>' . "\n";
     echo '<p>Yes, PayPal Payments Pro is required for Pro-Forms. However, there are some exceptions to that rule.</p>' . "\n";
     echo '<div class="ws-menu-page-hr"></div>' . "\n";
     echo '<h4>PayPal Payments Pro is Absolutely Required:</h4>' . "\n";
     echo '<ul>' . "\n";
     echo '	<li>For you to accept on-site credit card payments via Pro-Forms; i.e., not just PayPal Express Checkout.</li>' . "\n";
     echo '	<li>For Cancelation, Billing Update, and Billing Modification Pro-Forms to work as expected in all cases.</li>' . "\n";
     echo '	<li>Generally speaking, for you to take full advantage of everything that Pro-Forms can do; and to have them all work as originally intended.</li>' . "\n";
     echo '</ul>' . "\n";
     echo '<p><em><strong>See also:</strong> <a href="https://s2member.com/kb-article/supported-paypal-account-types/" target="_blank" rel="external">Supported PayPal Account Types</a></em></p>' . "\n";
     echo '<div class="ws-menu-page-hr"></div>' . "\n";
     echo '<h4>PayPal Payments Pro is NOT Required (Exceptions):</h4>' . "\n";
     echo '<ul>' . "\n";
     echo '	<li>For you to introduce Free Registration Pro-Forms. In fact, you can use Free Registration Pro-Forms w/o even configuring PayPal API credentials.</li>' . "\n";
     echo '	<li>For you to accept PayPal Express Checkout only (not ideal). See: <a href="https://s2member.com/kb-article/do-s2member-pro-forms-work-with-paypal-standard-i-e-without-paypal-pro/" target="_blank" rel="external">this KB article</a> for details and important limitations.</li>' . "\n";
     echo '	<li style="font-style:italic;">If you integrate with Stripe™ instead (free, most popular). See: <a href="https://s2member.com/kb-article/does-s2member-integrate-w-stripe-bitcoin/" target="_blank" rel="external">Does s2Member Pro integrate w/ Stripe? Bitcoin?</a></li>' . "\n";
     echo '</ul>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Free Registration Forms">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-registration-forms-section">' . "\n";
     echo '<h3>One Form Does It All For Free Registrations (copy/paste)</h3>' . "\n";
     echo '<p>Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0.</p>' . "\n";
     echo '<p><em><strong>Note:</strong> the use of this particular Form will override your Open Registration configuration. In other words, making this Form available is the same as turning Open Registration <code>(on)</code>. One of the benefits to this functionality, is that it makes it possible for you to integrate this Free Registration Form in creative ways (i.e., making it available ONLY under certain circumstances); while still leaving Open Registration <code>(off)</code> throughout the rest of the site.</em></p>' . "\n";
     echo '<p><em><strong>Tip (optional):</strong> It is also possible to change the <code>level="0"</code> Attribute to something other than the default Level #0 (Free Subscriber). For example, if you need to, you can change it to <code>level="1"</code>, attach Custom Capabilities with the <code>ccaps=""</code> Attribute, and even limit this access to a certain timeframe with <code>tp="30" tt="D"</code> (i.e., 30 Days). So this Form is very flexible. It can be used to allow free access to just about any aspect of your service. For more information on Attributes, please see the section below: Shortcode Attributes (Explained).</em></p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-registration-form-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr("0")), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level0_label"])), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-registration-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<div class="ws-menu-page-group" title="Forms For Level #' . $n . ' Access">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-level' . $n . '-forms-section">' . "\n";
         echo '<h3>Pro-Form Generator For Level #' . $n . ' Access</h3>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Form Code). These special PayPal Forms are customized to work with s2Member seamlessly. Member accounts will be activated instantly, in an automated fashion. When you, or a Member, cancels their Membership, or fails to make payments on time, s2Member will automatically terminate their Membership privileges. s2Member makes extensive use of the PayPal IPN service. s2Member receives updates from PayPal behind-the-scene.</p>' . "\n";
         echo '<p><em><strong>Please note:</strong> forms are NOT saved here. This is only a Form Generator. Once you\'ve generated your Form, copy/paste it into any Post/Page you like. You\'ll want to provide your visitors with a link to the Post/Page where this Form is located. We suggest placing a link to this Form on your Membership Options Page. That way your visitors can get registered &amp; checkout!</em></p>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p id="ws-plugin--s2member-pro-level' . $n . '-trial-line">I\'ll offer the first <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-pro-level' . $n . '-trial-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-trial-terms.php"))) . '</select> @ $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-trial-amount" value="0.00" size="4" /></p>' . "\n";
         echo '<p><span id="ws-plugin--s2member-pro-level' . $n . '-trial-then">Then, </span>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-level' . $n . '-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/" . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_payflow_api_username"] ? "payflow" : "paypal") . "-membership-regular-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-desc" value="' . format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"]) . ' / description and pricing details here." size="68" /></p>' . "\n";
         echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nWith PayPal Pro integration, this is only applied to PayPal Express Checkout pages; when/if a Customer chooses PayPal as the Payment Method.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-pro-level' . $n . '-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_paypalFormGenerate(\'level' . $n . '\');" /></p>' . "\n";
         echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-checkout-form-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($n)), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])), $ws_plugin__s2member_pro_temp_s);
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-level' . $n . '-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
     }
     echo '<div class="ws-menu-page-group" title="Billing Modification Forms">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-modification-forms-section">' . "\n";
     echo '<h3>Pro-Form Generator For Billing Modifications</h3>' . "\n";
     echo '<p>If you\'d like to give your Members (and/or your Free Subscribers) the ability to change (modify) their billing plan; you can generate a new PayPal Modification Form here. Configure the updated Level, pricing, terms, etc. Then, make that new Modification Form available to Members who are logged into their existing account with you. For example, you might want to insert a "Level #2" Upgrade link into your Login Welcome Page, which would up-sell existing Level #1 Members to a more expensive plan that you offer.</p>' . "\n";
     echo '<p><em><strong>Modification Process:</strong> Very simple. A Member clicks a link to a special Post/Page, which contains a Modification Form you\'ve generated. The Member fills in their billing information. After a successful form submission, s2Member will update the status of their account to the Level, pricing, and terms that you configure below. If the Member already has an existing paid Subscription with you, that paid Subscription will be cancelled automatically behind-the-scenes, and a new paid Subscription will be created to replace the old one. Again, the new paid Subscription is based on the Level, pricing, and terms that you specify below. If you need to give Customers some sort of grace period when/if they upgrade to a more expensive plan, please feel free to handle this through the application of free days, or with special pricing configured below.</em></p>' . "\n";
     echo '<p><em><strong>Integrating Conditionals:</strong> Since each Modification Form is configured for a specific Level, you may want to create multiple Modification Forms, one for each combination you intend to make available. s2Member\'s API Conditionals can help you display the proper Form to each Customer, based on the status of their existing account. For further details, see: <strong>s2Member → API Scripting</strong>.</em></p>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<p><em><strong>Independent Custom Capabilities:</strong> If you just want to sell an existing Member new Custom Capabilities, without affecting their paid Subscription in any way, please see the next Form Generator: <code>Capability (Buy Now) Forms</code>. Independent Capability Forms facilitate Buy Now functionality, specifically for Custom Capabilities, without affecting the Customer\'s primary Subscription and Membership Level Access.</em></p>' . "\n" : '';
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p>Modification: <select id="ws-plugin--s2member-pro-modification-level">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<optgroup label="Level #' . $n . '">' . "\n";
         echo '<option value="upgrade:' . $n . '">&uarr; Upgrade To Level #' . $n . '</option>' . "\n";
         echo $n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? '<option value="downgrade:' . $n . '">&darr; Downgrade To Level #' . $n . '</option>' . "\n" : '';
         echo '</optgroup>' . "\n";
         echo $n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] ? '<option disabled="disabled"></option>' . "\n" : '';
     }
     echo '</select></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-modification-trial-line">I\'ll offer the first <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-pro-modification-trial-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-trial-terms.php"))) . '</select> @ $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-trial-amount" value="0.00" size="4" /></p>' . "\n";
     echo '<p><span id="ws-plugin--s2member-pro-modification-trial-then">Then, </span>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-modification-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/" . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_payflow_api_username"] ? "payflow" : "paypal") . "-membership-regular-terms.php"))) . '</select></p>' . "\n";
     echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
     echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nWith PayPal Pro integration, this is only applied to PayPal Express Checkout pages; when/if a Customer chooses PayPal as the Payment Method.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-pro-modification-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_paypalFormGenerate(\'modification\');" /></p>' . "\n";
     echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\\n\\nOr to just (Remove All) and (Add) nothing:\\n-all\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-modification-ccaps" size="40" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-checkout-form-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr("1")), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     $ws_plugin__s2member_pro_temp_s = preg_replace("/\\/]\$/", 'modify="1" /]', $ws_plugin__s2member_pro_temp_s);
     // Adds modify="1" to the end of the Shortcode.
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-modification-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
         echo '<div class="ws-menu-page-group" title="Capability (Buy Now) Forms">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-ccap-forms-section">' . "\n";
         echo '<h3>Pro-Form Generator For Independent Custom Capabilities</h3>' . "\n";
         echo '<p>This is VERY advanced. For further details, please check your Dashboard: <strong>s2Member → API Scripting → Custom Capabiities</strong>.</p>' . "\n";
         echo '<p>With s2Member, you can sell one or more Custom Capabilities using Buy Now functionality, to "existing" Users/Members, regardless of which Membership Level they have on your site <em>(i.e., you could even sell Independent Custom Capabilities to Users at Membership Level #0, normally referred to as Free Subscribers, if you like)</em>. So this is quite flexible. Independent Custom Capabilities do NOT rely on any specific Membership Level. That\'s why s2Member refers to these as `Independent` Custom Capabilities, because you can sell Capabilities this way, through Buy Now functionality, and the Customer\'s Membership Level Access, along with any existing paid Subscription they may already have with you, will remain completely unaffected. That being said, if you intend to charge a recurring fee for Custom Capabilities, please use a <code>Billing Modification Form</code> instead; because Independent Custom Capabilities can only be sold through Buy Now functionality.</p>' . "\n";
         echo '<p>Independent Custom Capabilities are added to a Customer\'s account immediately after checkout, and the Customer will have the Custom Capabilities for as long as their Membership lasts, based on their primary Subscription with your site, and/or forever, if they have a Lifetime account with you. In other words, Independent Custom Capabilities will exist on the Customer\'s account forever, or until an EOT <em>(End Of Term)</em> occurs on their primary Subscription with you; in which case s2Member would demote or delete the Customer\'s account <em>(based on your EOT configuration)</em>, and all Custom Capabilities are removed as well.</p>' . "\n";
         echo '<p>Very simple. All you do is customize the form fields provided, for each set of Custom Capabilities that you plan to sell. Then press (Generate Form Code). These special PayPal Forms are customized to work with s2Member seamlessly. The Customer will be granted additional access to one or more Custom Capabilities that you specify; while the Customer\'s Membership Level Access and any existing paid Subscription they may already have with you, will remain completely unaffected.</p>' . "\n";
         echo '<table class="form-table">' . "\n";
         echo '<tbody>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-ccap-term">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-membership-ccap-terms.php"))) . '</select></p>' . "\n";
         echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
         echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nWith PayPal Pro integration, this is only applied to PayPal Express Checkout pages; when/if a Customer chooses PayPal as the Payment Method.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-pro-ccap-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_paypalCcapFormGenerate();" /></p>' . "\n";
         echo '<p>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.\\n\\n*ADVANCED TIP: You can specifiy a list of Custom Capabilities that will be (Added) with this purchase. Or, you could tell s2Member to (Remove All) Custom Capabilities that may or may not already exist for a particular Member, and (Add) only the new ones that you specify. To do this, just start your list of Custom Capabilities with `-all`.\\n\\nSo instead of just (Adding) Custom Capabilities:\\nmusic,videos,archives,gifts\\n\\nYou could (Remove All) that may already exist, and then (Add) new ones:\\n-all,calendar,forums,tools\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-ccap-ccaps" size="40" /></p>' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '<tr>' . "\n";
         echo '<td>' . "\n";
         echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
         echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
         $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-ccaps-checkout-form-shortcode.php")));
         $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
         echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-ccap-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
         echo '</form>' . "\n";
         echo '</td>' . "\n";
         echo '</tr>' . "\n";
         echo '</tbody>' . "\n";
         echo '</table>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
     }
     echo '<div class="ws-menu-page-group" title="Billing Update Forms">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-update-forms-section">' . "\n";
     echo '<h3>One Form Does It All For Billing Updates (copy/paste)</h3>' . "\n";
     echo '<p>An Update Form can be provided to existing Members, as a way for them to update their billing information; without modifying their existing paid Subscription in any way. For instance, a Customer may need to update their billing information, because their credit card is expiring, or because they moved their bank account.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-update-form-shortcode.php")));
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-update-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Billing Cancellation Forms">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-cancellation-forms-section">' . "\n";
     echo '<h3>One Form Does It All For Cancellations (copy/paste)</h3>' . "\n";
     echo '<p>According to PayPal\'s policy on recurring billing, you MUST provide each and every Customer with an easy to way to cancel future charges. Generating a Cancellation Form here, and making that Form available to all Customers is our recommendation. For further details and legalities, please visit the <a href="http://s2member.com/r/paypal-developer-network/" target="_blank" rel="external">PayPal Developer Network</a>.</p>' . "\n";
     echo '<p><em><strong>Cancellation Process:</strong> Very simple. A Member clicks a link to a Post/Page that contains a Cancellation Form you\'ve generated. The Member clicks the Submit button to confirm the cancellation. s2Member is notified silently behind-the-scenes, and will immediately cancel all future billing. s2Member will later terminate their account access, at the correct point in time. This works in conjunction with the s2Member Auto-EOT System. For further details, see: <strong>s2Member → PayPal Options → EOT Behavior</strong>.</em></p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-cancellation-form-shortcode.php")));
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-cancellation-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Member Registration Access Links">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-reg-links-section">' . "\n";
     echo '<h3>Registration Access Link Generator (for Customer Service)</h3>' . "\n";
     echo '<p>s2Member Pro-Forms consolidate the Registration/Checkout process into a single-step solution, so it is unlikely that you will ever need this tool. That being said, if you DO need to deal with a Customer Service issue that requires a simple paid Registration Access Link to be created manually, you can use this tool for that. Alternatively, you can create their account yourself/manually by going to <strong>Users → Add New</strong>. Either of these methods will work fine.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p>Paid Membership Level#: <select id="ws-plugin--s2member-pro-reg-link-level">' . "\n";
     for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++) {
         echo '<option value="' . $n . '">s2Member Level #' . $n . '</option>' . "\n";
     }
     echo '</select></p>' . "\n";
     echo '<p>Paid Subscr. ID: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-subscr-id" value="" size="50" /> <a href="#" onclick="alert(\'The Customer\\\'s Paid Subscr. ID (aka: Recurring Profile ID, Transaction ID) must be unique. This value can be obtained from inside your PayPal account in the History tab. Each paying Customer MUST be associated with a unique Paid Subscr. ID. If the Customer is NOT associated with a Paid Subscr. ID, you will need to generate a unique value for this field on your own. But keep in mind, s2Member will be unable to maintain future communication with the PayPal IPN (i.e., Notification) service if this value does not reflect a real Paid Subscr. ID that exists in your PayPal History log.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>Custom String Value: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-custom" value="' . esc_attr($_SERVER["HTTP_HOST"]) . '" size="30" /> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_paypalRegLinkGenerate();" /> <img id="ws-plugin--s2member-pro-reg-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? ' style="display:none;"' : '') . '>Custom Capabilities (comma-delimited) <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member → API Scripting → Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" maxlength="125" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-ccaps" size="40" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \\-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" /></p>' . "\n";
     echo '<p>Fixed Term Length (for Buy Now transactions): <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-reg-link-fixed-term" value="" size="10" /> <a href="#" onclick="alert(\'If the Customer purchased Membership through a Buy Now transaction (i.e., there is no Initial/Trial Period and no recurring charges for ongoing access), you may configure a Fixed Term Length in this field. This way the Customer\\\'s Membership Access is revoked by s2Member at the appropriate time. This will be a numeric value, followed by a space, then a single letter.\\n\\nHere are some examples:\\n\\n1 D (this means 1 Day)\\n1 W (this means 1 Week)\\n1 M (this means 1 Month)\\n1 Y (this means 1 Year)\\n1 L (this means 1 Lifetime)\'); return false;">[?]</a></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-reg-link" class="monospace" style="display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Specific Post/Page (Buy Now) Forms">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-forms-section">' . "\n";
     echo '<h3>Pro-Form Generator For Specific Post/Page Forms</h3>' . "\n";
     echo '<p>s2Member now supports an additional layer of functionality (very powerful), which allows you to sell access to specific Posts/Pages that you\'ve created in WordPress. Specific Post/Page Access works independently from Member Level Access. That is, you can sell an unlimited number of Posts/Pages using "Buy Now" functionality. Your Customers will NOT be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be.</p>' . "\n";
     echo '<p>In other words, Customers will NOT need to login, just to receive access to the Specific Post/Page they purchased access to. s2Member will immediately redirect the Customer to the Specific Post/Page after checkout is completed successfully. An email is also sent to the Customer with a link (see: <strong>s2Member → PayPal Options → Specific Post/Page Email</strong>). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>' . "\n";
     echo '<p>Specific Post/Page Access, is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Post/Page on your site; one that you created in WordPress. A Specific Post/Page that is protected by s2Member, might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on and on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress Post/Page that you\'ve created. To protect Specific Posts/Pages, please see: <strong>s2Member → Restriction Options → Specific Post/Page Access</strong>. Once you\'ve configured your Specific Post/Page Restrictions, those Posts/Pages will be available in the menus below.</p>' . "\n";
     echo '<p>Very simple. All you do is customize the form fields provided, for each Post/Page that you plan to sell. Then press (Generate Form Code). These special PayPal Forms are customized to work with s2Member seamlessly. You can even Package Additional Posts/Pages together into one transaction.</p>' . "\n";
     echo '<p><em><strong>Please note:</strong> forms are NOT saved here. This is only a Form Generator. Once you\'ve generated your Form, copy/paste it into any Post/Page you like. You\'ll want to provide your visitors with a link to the Post/Page where this Form is located.</em></p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-additional-ids" multiple="multiple" style="height:100px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p>I want to charge: $<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-pro-sp-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-sp-hours.php"))) . '</select></p>' . "\n";
     echo '<p>Description: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-desc" value="Description and pricing details here." size="68" /></p>' . "\n";
     echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal account. PayPal allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal, you can enter that Page Style here.\\n\\nWith PayPal Pro integration, this is only applied to PayPal Express Checkout pages; when/if a Customer chooses PayPal as the Payment Method.\'); return false;" tabindex="-1">[?]</a>: <input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-pro-sp-currency">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-currencies.php"))) . '</select> <input type="button" value="Generate Form Code" onclick="ws_plugin__s2member_pro_paypalSpFormGenerate();" /></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<strong>WordPress Shortcode:</strong> (recommended for both the WordPress Visual &amp; HTML Editors)<br />' . "\n";
     $ws_plugin__s2member_pro_temp_s = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/shortcodes/paypal-sp-checkout-form-shortcode.php")));
     $ws_plugin__s2member_pro_temp_s = preg_replace("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs(esc_attr($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_pro_temp_s);
     echo '<input type="text" autocomplete="off" id="ws-plugin--s2member-pro-sp-shortcode" value="' . format_to_edit($ws_plugin__s2member_pro_temp_s) . '" onclick="this.select ();" class="monospace" />' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Specific Post/Page Access Links">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-sp-links-section">' . "\n";
     echo '<h3>Specific Post/Page Access Link Generator (for Customer Service)</h3>' . "\n";
     echo '<p>s2Member automatically generates Specific Post/Page Access Links for your Customers after checkout, and also sends them a link in a Confirmation Email. However, if you ever need to deal with a Customer Service issue that requires a new Specific Post/Page Access Link to be created manually, you can use this tool for that.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<form onsubmit="return false;" autocomplete="off">' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-leading-id">' . "\n";
     echo '<option value="">&mdash; Select a Leading Post/Page that you\'ve protected &mdash;</option>' . "\n";
     $ws_plugin__s2member_pro_temp_a_singulars = c_ws_plugin__s2member_utils_gets::get_all_singulars_with_sp("exclude-conflicts");
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</select> <a href="#" onclick="alert(\'Required. The Leading Post/Page, is what your Customers will land on after checkout.\\n\\n*Tip* If there are no Posts/Pages in the menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-additional-ids" multiple="multiple" style="height:100px; min-width:450px;">' . "\n";
     echo '<optgroup label="&mdash; Package Additional Posts/Pages that you\'ve protected &mdash;">' . "\n";
     foreach ($ws_plugin__s2member_pro_temp_a_singulars as $ws_plugin__s2member_pro_temp_o) {
         echo '<option value="' . esc_attr($ws_plugin__s2member_pro_temp_o->ID) . '">' . esc_html($ws_plugin__s2member_pro_temp_o->post_title) . '</option>' . "\n";
     }
     echo '</optgroup></select> <a href="#" onclick="alert(\'Hold down your `Ctrl` key to select multiples.\\n\\nOptional. If you include Additional Posts/Pages, Customers will still land on your Leading Post/Page; BUT, they\\\'ll ALSO have access to some Additional Posts/Pages that you\\\'ve protected. This gives you the ability to create Post/Page Packages.\\n\\nIn other words, a Customer is sold a Specific Post/Page (they\\\'ll land on your Leading Post/Page after checkout), which might contain links to some other Posts/Pages that you\\\'ve packaged together under one transaction.\\n\\nBundling Additional Posts/Pages into one Package, authenticates the Customer for access to the Additional Posts/Pages automatically (i.e., only one Access Link is needed, and s2Member generates this automatically). However, you will STILL need to design your Leading Post/Page (which is what a Customer will actually land on), with links pointing to the other Posts/Pages. This way your Customers will have clickable links to everything they\\\'ve paid for.\\n\\n*Quick Summary* s2Member sends Customers to your Leading Post/Page, and also authenticates them for access to any Additional Posts/Pages automatically. You handle it from there.\\n\\n*Tip* If there are no Posts/Pages in this menu, it\\\'s because you\\\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.\'); return false;" tabindex="-1">[?]</a></p>' . "\n";
     echo '<p><select id="ws-plugin--s2member-pro-sp-link-hours">' . trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__)) . "/templates/options/paypal-sp-hours.php"))) . '</select> <input type="button" value="Generate Access Link" onclick="ws_plugin__s2member_pro_paypalSpLinkGenerate();" /> <img id="ws-plugin--s2member-pro-sp-link-loading" src="' . esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/ajax-loader.gif" alt="" style="display:none;" /></p>' . "\n";
     echo '<p id="ws-plugin--s2member-pro-sp-link" class="monospace" style="display:none;"></p>' . "\n";
     echo '</form>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) {
         echo '<div class="ws-menu-page-group" title="Custom Return URLs Upon Success">' . "\n";
         echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-forms-success-section">' . "\n";
         echo '<h3>Custom Return URLs Upon Success (optional, for developers)</h3>' . "\n";
         echo '<p>s2Member Pro opens the door for Custom Return URLs upon success. You can add a special attribute to any Form Shortcode (<code>success="/my-thank-you-page/"</code>). This makes it possible to integrate PayPal Pro-Forms in very creative ways; and even receive/verify Replacement Code variables, as needed. For example, (<code>success="/my-thank-you-page/?subscr_id=%%subscr_id%%"</code>).</p>' . "\n";
         echo '<p><em>A Custom Return URL is 100% optional. In fact, if you only need to obtain details for the purpose of tracking sales, you should just use the simpler API Tracking methods provided by s2Member, under: <strong>s2Member → API / Tracking</strong>. In other words, if you don\'t use the <code>success=""</code> attribute in your Shortcode, s2Member will handle things gracefully, all on its own. So using a Custom Return URL is only necessary when you need advanced customization for one reason or another.</em></p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Free Registration Forms (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-free-registration\').toggle(); return false;" class="ws-dotted-link">open/close</a>)</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-free-registration" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%role%%</code> = The Role ID <code>(subscriber, s2member_level[0-9]+, administrator, editor, author, contributor)</code>.</li>' . "\n";
         echo '<li><code>%%level%%</code> = The Level number <code>(0, 1, 2, 3, 4)</code>. (<em>deprecated, no longer recommended; use <code>%%role%%</code></em>)</li>' . "\n";
         echo '<li><code>%%ccaps%%</code> = Custom Capabilities. Ex: <code>music,videos,free_gift</code> (<em>in comma-delimited format</em>).</li>' . "\n";
         echo '<li><code>%%auto_eot_time%%</code> = Auto-EOT Time (if applicable). Ex: <code>1299925670</code> (<em>unix timestamp</em>).</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name (First &amp; Last) of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address of the Member who registered their Username.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username the Member selected during registration.</li>' . "\n";
         echo '<li><code>%%user_pass%%</code> = The Password selected or generated during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The User\'s IP Address, via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress User ID generated during registration.</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_decrypt()" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Registration/Profile Fields are also supported here:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member → General Options → Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>(The campaign (i.e., christmas-promo) could be referenced using <code>%%cv1%%</code>)</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Membership Sales / Signups &amp; Modifications (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-sales\').toggle(); return false;" class="ws-dotted-link">open/close</a>)</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-sales" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%subscr_id%%</code> = The PayPal Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term (non-recurring) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase. PayPal does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring (i.e., there is only ONE payment), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%subscr_baid%%</code> = Applicable only with PayPal Pro (Payflow Edition); and only for Express Checkout transactions that require a Billing Agreement. This is the Subscription\'s Billing Agreement ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'Applicable only with PayPal Pro (Payflow Edition); and only for Express Checkout transactions that require a Billing Agreement. In all other cases, the %%subscr_baid%% is simply set to the %%subscr_id%% value; i.e., it is a duplicate of %%subscr_id%% in most cases.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%currency%%</code> = Three-character currency code (uppercase); e.g., <code>USD</code></li>' . "\n";
         echo '<li><code>%%currency_symbol%%</code> = Currency code symbol; e.g., <code>$</code></li>' . "\n";
         echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a 100% Free Trial, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. Even if that amount is 0.\\n\\nIf a Customer signs up, under the terms of a 100% Free Trial Period, this will be 0. So be careful using %%initial%% when you offer a 100% Free Trial Period, because a $0.00 sale amount could cause havoc with affiliate programs.\\n\\nIf you\\\'re offering a 100% Free Trial Period, and you need to track sales through affiliate programs, you can either hard-code an amount; or use `s2Member → API Notifications → Payment Notifications` instead.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. If you offer something 100% free, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an Initial Period expires. If you did NOT offer an Initial Period at a different price, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a recurring basis, or <code>0</code> if non-recurring. [ <a href="#" onclick="alert(\'If Recurring Payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the Regular Recurring Rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%full_name%%</code> = The Full Name (First &amp; Last) of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%item_number%%</code> = The Item Number (colon separated <code><em>level:custom_capabilities:fixed term</em></code>) for the Membership Subscription.</li>' . "\n";
         echo '<li><code>%%item_name%%</code> = The Item Name (as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number).</li>' . "\n";
         echo '<li><code>%%initial_term%%</code> = This is the term length of the Initial Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D (this means 1 Day)\\n%%initial_term%% = 1 W (this means 1 Week)\\n%%initial_term%% = 1 M (this means 1 Month)\\n%%initial_term%% = 1 Y (this means 1 Year)\\n\\nThe Initial Period never recurs, so this only lasts for the term length specified, then it is over.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%regular_term%%</code> = This is the term length of the Regular Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D (this means 1 Day)\\n%%regular_term%% = 1 W (this means 1 Week)\\n%%regular_term%% = 1 M (this means 1 Month)\\n%%regular_term%% = 1 Y (this means 1 Year)\\n%%regular_term%% = 1 L (this means 1 Lifetime)\\n\\nThe Regular Term is usually recurring. So the Regular Term value represents the period (or duration) of each recurring period. If %%recurring%% = 0, then the Regular Term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their Membership privileges are going to last after the %%initial_term%% has expired, if there was an Initial Term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%modification%%</code> = <code>1</code> if/when a Billing Modification has just taken place; otherwise <code>0</code> indicates a new Customer.</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The Customer\'s original IP Address, during checkout/registration via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress User ID that references this account in the WordPress database.</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_decrypt()" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Coupon Replacement Codes:</strong>' . "\n";
         echo '<ul class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%full_coupon_code%%</code> = A full Coupon Code—if one is accepted by your configuration of s2Member. This may indicate an Affiliate Coupon Code, which will include your Affiliate Suffix Chars too (i.e., the full Coupon Code).</li>' . "\n";
         echo '<li><code>%%coupon_code%%</code> = A Coupon Code—if one is accepted by your configuration of s2Member. This will NOT include any Affiliate Suffix Chars. This indicates the actual Coupon Code accepted by your configuration of s2Member (excluding any Affiliate ID).</li>' . "\n";
         echo '<li><code>%%coupon_affiliate_id%%</code> = This is the end of an Affiliate Coupon Code <em>(i.e., the referring affiliate\'s ID)</em>. This is only applicable if an Affiliate Coupon Code is accepted by your configuration of s2Member.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Registration/Profile Fields are also supported here:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member → General Options → Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>(The campaign (i.e., christmas-promo) could be referenced using <code>%%cv1%%</code>)</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Independent Custom Capability Sales (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-ccaps\').toggle(); return false;" class="ws-dotted-link">open/close</a>)</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-ccaps" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%txn_id%%</code> = The Payment Transaction ID, which is always unique for each payment received.</li>' . "\n";
         echo '<li><code>%%currency%%</code> = Three-character currency code (uppercase); e.g., <code>USD</code></li>' . "\n";
         echo '<li><code>%%currency_symbol%%</code> = Currency code symbol; e.g., <code>$</code></li>' . "\n";
         echo '<li><code>%%amount%%</code> = The Amount of the payment. Most affiliate programs calculate commissions from this.</li>' . "\n";
         echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%full_name%%</code> = The Full Name (First &amp; Last) of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Independent Custom Capabilities.</li>' . "\n";
         echo '<li><code>%%item_number%%</code> = The Item Number (colon separated <code><em>*level:custom_capabilities:fixed term</em></code>) that the payment is for. [ <a href="#" onclick="alert(\'With Independent Custom Capabilities, the `level` portion of this string will be an asterisk ( `*` ), since the Membership Level is irrelevant, and remains `as it was`.\'); return false;">?</a> ]</li>' . "\n";
         echo '<li><code>%%item_name%%</code> = The Item Name (as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number).</li>' . "\n";
         echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
         echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The Customer\'s original IP Address, during checkout/registration via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%user_id%%</code> = A unique WordPress User ID that references this account in the WordPress database.</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, it might contain a link to the login page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_decrypt()" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Coupon Replacement Codes:</strong>' . "\n";
         echo '<ul class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%full_coupon_code%%</code> = A full Coupon Code—if one is accepted by your configuration of s2Member. This may indicate an Affiliate Coupon Code, which will include your Affiliate Suffix Chars too (i.e., the full Coupon Code).</li>' . "\n";
         echo '<li><code>%%coupon_code%%</code> = A Coupon Code—if one is accepted by your configuration of s2Member. This will NOT include any Affiliate Suffix Chars. This indicates the actual Coupon Code accepted by your configuration of s2Member (excluding any Affiliate ID).</li>' . "\n";
         echo '<li><code>%%coupon_affiliate_id%%</code> = This is the end of an Affiliate Coupon Code <em>(i.e., the referring affiliate\'s ID)</em>. This is only applicable if an Affiliate Coupon Code is accepted by your configuration of s2Member.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Registration/Profile Fields are also supported here:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>date_of_birth</code>.</li>' . "\n";
         echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>street_address</code>.</li>' . "\n";
         echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration/Profile Field with the ID <code>country</code>.</li>' . "\n";
         echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member → General Options → Registration/Profile Fields</em>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>(The campaign (i.e., christmas-promo) could be referenced using <code>%%cv1%%</code>)</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Specific Post/Page Transactions (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-sp-sales\').toggle(); return false;" class="ws-dotted-link">open/close</a>)</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-sp-sales" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%sp_access_url%%</code> = The full URL (generated by s2Member) where the Customer can gain access.</li>' . "\n";
         echo '<li><code>%%sp_access_exp%%</code> = Human readable expiration for <code>%%sp_access_url%%</code>. Ex: <em>(link expires in <code>%%sp_access_exp%%</code>)</em>.</li>' . "\n";
         echo '<li><code>%%txn_id%%</code> = The PayPal Transaction ID. PayPal assigns a unique identifier for every purchase.</li>' . "\n";
         echo '<li><code>%%currency%%</code> = Three-character currency code (uppercase); e.g., <code>USD</code></li>' . "\n";
         echo '<li><code>%%currency_symbol%%</code> = Currency code symbol; e.g., <code>$</code></li>' . "\n";
         echo '<li><code>%%amount%%</code> = The full Amount of the sale. Most affiliate programs calculate commissions from this.</li>' . "\n";
         echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%full_name%%</code> = The Full Name (First &amp; Last) of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
         echo '<li><code>%%user_ip%%</code> = The Customer\'s IP Address, detected during checkout via <code>$_SERVER["REMOTE_ADDR"]</code>.</li>' . "\n";
         echo '<li><code>%%item_number%%</code> = The Item Number. Ex: <code><em>sp:13,24,36:72</em></code> (translates to: <code><em>sp:comma-delimited IDs:expiration hours</em></code>).</li>' . "\n";
         echo '<li><code>%%item_name%%</code> = The Item Name (as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number).</li>' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link to the Specific Post/Page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link to the Specific Post/Page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_decrypt()" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Coupon Replacement Codes:</strong>' . "\n";
         echo '<ul class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%full_coupon_code%%</code> = A full Coupon Code—if one is accepted by your configuration of s2Member. This may indicate an Affiliate Coupon Code, which will include your Affiliate Suffix Chars too (i.e., the full Coupon Code).</li>' . "\n";
         echo '<li><code>%%coupon_code%%</code> = A Coupon Code—if one is accepted by your configuration of s2Member. This will NOT include any Affiliate Suffix Chars. This indicates the actual Coupon Code accepted by your configuration of s2Member (excluding any Affiliate ID).</li>' . "\n";
         echo '<li><code>%%coupon_affiliate_id%%</code> = This is the end of an Affiliate Coupon Code <em>(i.e., the referring affiliate\'s ID)</em>. This is only applicable if an Affiliate Coupon Code is accepted by your configuration of s2Member.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%cv0%%</code> = The domain of your site, which is passed through the `custom` attribute in your Shortcode.</li>' . "\n";
         echo '<li><code>%%cv1%%</code> = If you need to track additional custom variables, you can pipe delimit them into the `custom` attribute; inside your Shortcode, like this: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3"</code>. You can have an unlimited number of custom variables. Obviously, this is for advanced webmasters; but the functionality has been made available for those who need it.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '<strong>This example uses cv1 to record a special marketing campaign:</strong><br />' . "\n";
         echo '<em>(The campaign (i.e., christmas-promo) could be referenced using <code>%%cv1%%</code>)</em><br />' . "\n";
         echo '<code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|christmas-promo"</code>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Cancellations &amp; Billing Updates (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-cancellations-updates\').toggle(); return false;" class="ws-dotted-link">open/close</a>)</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-cancellations-updates" style="display:none;">' . "\n";
         echo '<ul style="margin: 10px 0 10px 20px; list-style: disc outside;" class="ws-menu-page-li-margins">' . "\n";
         echo '<li><code>%%response%%</code> = Deprecated. Use <code>%%s_response%%</code>. A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link back to their account page. You don\'t have to use this. You can generate your own response if you like.</li>' . "\n";
         echo '<li><code>%%s_response%%</code> = A successful response message that *would* have been displayed to the Customer, had they NOT been redirected to your Custom Return URL upon success. This may contain some basic HTML. For instance, a link back to their account page. You don\'t have to use this. You can generate your own response if you like. Value is encrypted. Use <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_decrypt()" target="_blank" rel="external">s2member_decrypt()</a>.</li>' . "\n";
         echo '</ul>' . "\n";
         echo '</div>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Verify The Integrity Of Replacement Codes (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-pro-forms-success-verification\').toggle(); return false;" class="ws-dotted-link">open/close</a>)</h3>' . "\n";
         echo '<div id="ws-plugin--s2member-pro-forms-success-verification" style="display:none;">' . "\n";
         echo '<p>If you know a little PHP, you can verify the integrity of the Replacement Codes returned by s2Member. This is important, because in this particular situation, Replacement Codes are passed publicly in the query string of your Custom Return URL. In other words, a Customer could manually change one of the values; like the dollar amounts. For this reason, you should always verify the integrity of the details being returned to any processing routines that receive this information. In the PHP code for your Custom Return URL, you can use this s2Member API Function: <code>s2member_pro_paypal_s2p_v_query_ok()</code>.</p>' . "\n";
         echo '<p>Here are some examples:</p>' . "\n";
         echo '<p>1. <strong>Shortcode attribute:</strong> <code>success="/thank-you/?subscr_id=%%subscr_id%%&amp;initial=%%initial%%&amp;regular=%%regular%%"</code></p>' . "\n";
         echo '<p>2. <strong>s2Member returns Customer to:</strong> <code>/thank-you/?subscr_id=123&amp;initial=0.00&amp;regular=24.95&amp;s2p-v=234098234-23409sdfs234sd234209sdf</code></p>' . "\n";
         echo '<p>3. <strong>Now, in your Custom Return Page, you will need to do this before trusting anything:</strong></p>' . "\n";
         echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/paypal-s2p-v-query-ok-1.x-php")) . '</p>' . "\n";
         echo '<p>s2Member will only verify a query string for up to 10 seconds. After 10 seconds, <code>s2member_pro_paypal_s2p_v_query_ok()</code> will always return <code>false</code>, even if the integrity of the query string is valid. This prevents a Customer from bookmarking your Return URL; thereby causing duplicate commissions; in case you\'re using it for tracking purposes.</p>' . "\n";
         echo '<p>Again, if you only need to obtain details for the purpose of tracking sales, you should just use the simpler API Tracking methods provided by s2Member, under: <strong>s2Member → API / Tracking</strong>. The API Tracking methods are specifically designed for tracking sales, exactly ONE time for each Customer.</p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<p><em>If it is your intention to allow Customers to bookmark your Custom Return URL, you can still do that. Just be aware that <code>s2member_pro_paypal_s2p_v_query_ok()</code> will return <code>false</code> after the first 10 seconds. If you want to verify after 10 seconds, you can pass a second argument to the function, like this:</em></p>' . "\n";
         echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__) . "/code-samples/paypal-s2p-v-query-ok-2.x-php")) . '</p>' . "\n";
         echo '<div class="ws-menu-page-hr"></div>' . "\n";
         echo '<h3>Could a Customer change the timestamp in the URL?</h3>' . "\n";
         echo '<p>Based on the structure of the URL, it would appear possible; however, it\'s NOT. s2Member uses an advanced checksum.</p>' . "\n";
         echo '<h3>Can I get rid of the <code>s2p-v</code> variable?</h3>' . "\n";
         echo '<p>No, this variable is always passed to your Custom Return URL, it\'s for important verification purposes.</p>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
         echo '</div>' . "\n";
     }
     echo '<div class="ws-menu-page-group" title="Shortcode Attributes (Explained)">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-shortcode-attrs-section">' . "\n";
     echo '<h3>Shortcode Attributes (Explained In Full Detail)</h3>' . "\n";
     echo '<p>When you generate a Form, s2Member will make a <a href="http://s2member.com/r/shortcode-reference/" target="_blank" rel="external">Shortcode</a> available to you. Like most Shortcodes for WordPress, s2Member reads Attributes in your Shortcode. These Attributes will be pre-configured by one of s2Member\'s Form Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
     echo '<table class="form-table" style="margin-top:0;">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr style="padding-top:0;">' . "\n";
     echo '<td style="padding-top:0;">' . "\n";
     echo '<ul class="ws-menu-page-li-margins">' . "\n";
     echo '<li><code>accept="paypal,visa,mastercard,amex,discover,maestro,solo"</code> Accepted Billing Methods. A comma-delimited list of Billing Methods you want to accept. Due to a PayPal policy, you may NOT exclude PayPal from this list; s2Member won\'t let you. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>accept_via_paypal="paypal"</code> Accepted Billing via PayPal. A comma-delimited list of Billing Methods you want to accept through PayPal, as opposed to processing them on-site. Due to a PayPal policy, you may NOT exclude PayPal from this list; s2Member won\'t let you. <strong>Tip:</strong> If you don\'t have a PayPal Pro account, you can set <code>accept="paypal"</code>, or set <code>accept_via_paypal="paypal,visa,mastercard,amex,discover,maestro,solo"</code>. With one or both of these configurations, all you need is a PayPal Standard account with Express Checkout <em>(which is free)</em>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>accept_coupons="1"</code> Accept Coupons? Possible values: <code>0</code> = do NOT accept Coupons on this particular Form; <code>1</code> = DO accept Coupon Codes on this particular Form.</li>' . "\n";
     echo '<li><code>cancel="0"</code> Cancellation Form. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Cancellation Form, <code>1</code> = this IS a Cancellation Form.</li>' . "\n";
     echo '<li><code>captcha=""</code> When you set this Attribute, visitors must prove they\'re human by typing a <a href="http://s2member.com/r/captcha-reference/" target="_blank" rel="external">captcha/security code</a>. This service is powered by Google\'s reCaptcha system. Possible values: <code>0</code> = do NOT require a captcha code on this Form; <code>clean</code> = DO require a captcha code on this Form; using the <code>clean</code> theme style. Possible theme styles include: <code>red</code>, <code>white</code>, <code>clean</code>, and <code>blackglass</code>. Or, if you supplied reCaptcha v2 keys in your s2Member General Options (i.e., you are using reCaptcha v2), this must be <code>light</code> or <code>dark</code>.</li>' . "\n";
     echo '<li><code>cc="USD"</code> 3 character Currency Code. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>ccaps="music,videos"</code> A comma-delimited list of Custom Capabilities. Only valid w/ Membership Level Access and/or Independent Custom Capabilities.</li>' . "\n" : '';
     echo '<li><code>coupon="SAVE-10"</code> Default/pre-filled Coupon Code. This is optional, and the Coupon Code (if supplied) must exist in your Coupon Code configuration.</li>' . "\n";
     echo '<li><code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '"</code> must start with your domain. Additional values can be piped in (ex: <code>custom="' . esc_html($_SERVER["HTTP_HOST"]) . '|cv1|cv2|cv3|etc"</code>). Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>default_country_code="US"</code> If you set this 2-character value, it will pre-configure the default Country that is selected in the drop-down menu for Checkout and Billing Update Forms. This MUST be an uppercase country code, following the <a href="http://s2member.com/r/iso-3166/" target="_blank" rel="external">ISO-3166-1 specification</a>. If this is empty(i.e., <code>""</code>) s2Member will set the default country code automatically; based on currency. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>desc="Gold Membership @ $29/mo"</code> A brief purchase Description. This can be as long as you like. However, all descriptions passed through PayPal APIs are truncated automatically to 60 characters max (i.e., the maximum allowed length for PayPal descriptions is 60 characters). Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>dg="0"</code> The Digital Goods directive. s2Member will eventually be integrated with <a href="http://s2member.com/r/paypal-express-checkout-digitals/" target="_blank" rel="external">Digital Goods</a> for inline Express Checkout. But for now, this should always be <code>0</code>.</li>' . "\n";
     echo '<li><code>exp="72"</code> Access Expires (in hours). Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>ids="14"</code> A Post/Page ID#, or a comma-delimited list of IDs. Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
     echo '<li><code>lang=""</code> Optional 5 character Button Language Code <em>(ake: Locale Code—ex: <code>en_US</code>)</em>. This controls the interface language of the PayPal Express Checkout Button itself. If unspecified, the language defaults to English (i.e., <code>en_US</code>; or to the value set by an optional MO translation file; which translates s2Member overall). See <a href="http://s2member.com/r/paypal-locale-codes/" target="_blank" rel="external">this list of possible Locale Codes</a>.</li>' . "\n";
     echo '<li><code>lc=""</code> Optional 2 character Country/Locale Code <em>(i.e., Country Code—ex: <code>US</code>)</em>. This controls the interface language used when/if a Customer chooses PayPal Express Checkout as their payment method. If unspecified, the language is determined by PayPal Express Checkout when possible, defaulting to <code>US</code> <em>english</em> when not possible. See <a href="http://s2member.com/r/paypal-locale-codes/" target="_blank" rel="external">this list of possible Country Codes</a>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>level="1"</code> Membership Level [1-4] <em>(or, up to the number of configured Levels)</em>. Only valid for Forms providing Membership Level Access, which includes Free Registration Forms too. Free Registration Forms allow a value of <code>level="0"</code> whenever <code>register="1"</code> for Free Registration. In addition, Free Registration Forms will also allow visitors to register for free, even at higher Levels if you wish. Free Registration Forms will accept any value [0-4] <em>(or, up to the number of configured Levels)</em>.' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' With Independent Custom Capabilities this MUST be set to <code>level="*"</code>, and <code>ccaps=""</code> must NOT be empty <em>(i.e., <code>level="*" ccaps="music,videos"</code>)</em>.') . '</li>' . "\n";
     echo '<li><code>modify="0"</code> Modification directive. Only valid w/ Membership Level Access. Possible values: <code>0</code> = allows Customers to modify their current Subscription or sign up for a new one, <code>1</code> = allows Customers to only modify their current Subscription. When <code>modify="1"</code>, s2Member will force a Customer to be logged-in before they can fill out the Form (very handy). This is slightly different than PayPal "Button" Codes; there is no "2" option for "Forms"; only <code>0</code> &amp; <code>1</code> are valid values.</li>' . "\n";
     echo '<li><code>ns="0"</code> The <em>no_shipping</em> directive. Possible values: <code>0</code> = prompt for an address, but do not require one, <code>1</code> = do not prompt for a shipping address, <code>2</code> = prompt for an address, and require one. Applies only to PayPal Express Checkout; because Pro-Forms do not ask for a Shipping Address. However, you may request a Shipping Address by creating Custom Fields under: <em>s2Member → General Options → Registration/Profile Fields</em>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>ps="paypal"</code> PayPal checkout Page Style. Applies only to PayPal Express Checkout. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>register="0"</code> Free Registration Form. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Free Registration Form, <code>1</code> = this IS a Free Registration Form.</li>' . "\n";
     echo '<li><code>ra="0.01"</code> Regular, Buy Now, and/or Recurring Amount. Can also be <code>0.00</code> to provide free access. Not valid when <code>cancel="1"</code>.</li>' . "\n";
     echo '<li><code>rp="1"</code> Regular Period. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Must be &gt;= <code>1</code> (ex: <code>1</code> Week, <code>2</code> Months, <code>1</code> Month, <code>3</code> Days).—<strong>NOTICE (regarding Payflow):</strong> If you are operating a PayPal Pro (Payflow Edition) account, please take note. Payflow supports ONLY a specific set of recurring intervals. Pro-Forms integrated with the Payflow API can be configured to charge: weekly, bi-weekly, monthly, quarterly, semi-yearly or yearly.</li>' . "\n";
     echo '<li><code>rt="M"</code> Regular Term. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years, <code>L</code> = Lifetime.—<strong>NOTICE (regarding Payflow):</strong> If you are operating a PayPal Pro (Payflow Edition) account, please take note. Payflow supports ONLY a specific set of recurring intervals. Pro-Forms integrated with the Payflow API can be configured to charge: weekly, bi-weekly, monthly, quarterly, semi-yearly or yearly.</li>' . "\n";
     echo '<li><code>rr="1"</code> Recurring directive. Only valid w/ Membership Level Access' . (is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site() ? '' : ' and/or Independent Custom Capabilities') . '. Possible values: <code>0</code> = non-recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>1</code> = recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>BN</code> = non-recurring "Buy Now" functionality, no Trial Period possible.</li>' . "\n";
     echo '<li><code>rrt=""</code> Recurring Times <em>(i.e., a fixed number of installments)</em>. Only valid w/ Membership Level Access. When unspecified, any recurring charges will remain ongoing until cancelled, or until payments start failing. If this is set to <code>1 or higher</code> the regular recurring charges will only continue for X billing cycles, depending on what you specify. This is only valid when <code>rr="1"</code> for recurring "Subscriptions". Please note that a fixed number of installments, also means a fixed period of access. If a Customer\'s billing is monthly, and you set <code>rrt="3"</code>, billing will continue for only 3 monthly installments. After that, billing would stop, and their access to the site would be revoked as well <em>(based on your EOT Behavior setting under: s2Member → PayPal Options)</em>. <strong>IMPORTANT NOTE:</strong> If you don\'t offer a trial period; i.e., the first charge occurs when a customer completes checkout, you should set this to the number of <em>additional</em> payments, and NOT to the total number. For instance, if I want to charge the customer a total of 3 times, and one of those charges occurs when they complete checkout, I set should this to <code>rrt="2"</code> for a grand total of three all together.</li>' . "\n";
     echo '<li><code>rra="2"</code> Reattempt billing when/if a recurring payment fails; exactly X number of times; and then automatically suspend the customer\'s account (i.e., the customer loses access). By default, PayPal will retry a maximum of 2 times whenever <code>rra="2"</code>; after that, a Subscription would be terminated due to Max Failed Payments having been reached. The value of this attribute configures Max Failed Payments. A setting of <code>rra="2"</code> means that you allow a maximum of 2 failed payments. Setting <code>rra="0"</code> means that you allow an infinite number of failed payments.</li>' . "\n";
     echo '<li><code>sp="0"</code> Specific Post/Page Form. Possible values: <code>0</code> = this is NOT a Specific Post/Page Access Form, <code>1</code> = this IS a Specific Post/Page Access Form.</li>' . "\n";
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>success=""</code> 100% optional. This can be used to create a Custom Return URL on success. Please see the sub-section above titled: <em>Custom Return URLs on Success</em>.</li>' . "\n" : '';
     echo !is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site() ? '<li><code>template=""</code> 100% optional. This can be a custom template file that exists inside your WordPress theme directory. For example: <code>template="checkout.php"</code>. Please see <a href="http://s2member.com/kb-article/can-i-customize-pro-forms/" target="_blank" rel="external">this KB article</a> for further details.</li>' . "\n" : '';
     echo '<li><code>ta="0.00"</code> Trial Amount. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
     echo '<li><code>tp="0"</code> Trial Period. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
     echo '<li><code>tt="D"</code> Trial Term. Only valid w/ Membership Level Access. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years.</li>' . "\n";
     echo '<li><code>unsub="0"</code> Unsubscribe user? Only valid when <code>cancel="1"</code>. Possible values: <code>0</code> = do NOT unsubscribe (wait until an EOT occurs), <code>1</code> = yes, unusbscribe user immediately; i.e., when they submit the cancellation form. <em>NOTE: Just to clarify, this pertains to List Servers that you\'ve configured with s2Member. Setting <code>unsub="1"</code> will cause the user to be unsubscribed from a mailing list (if they are currently subscribed).</em></li>' . "\n";
     echo '<li><code>update="0"</code> Billing Update Form. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Billing Update Form, <code>1</code> = this IS a Billing Update Form.</li>' . "\n";
     echo '</ul>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-group" title="Wrapping Multiple Shortcodes as Checkout Options">' . "\n";
     echo '<div class="ws-menu-page-section ws-plugin--s2member-pro-form-options-section">' . "\n";
     echo '<h3>Wrapping Multiple Shortcodes as "Checkout Options"</h3>' . "\n";
     echo '<p>If you would like to offer a single Pro-Form w/ multiple "Checkout Options", it\'s quite easy. Generate each of your Pro-Form Shortcodes the same as you normally would (using some of the Pro-Form Generators on this page). Then, you can simply wrap them all inside another Pro-Form Shortcode (as seen below). For instance, if you generate two Pro-Form Shortcodes (or you have multiple Pro-Form Shortcodes on-site already); you can simply take those and wrap them inside another Pro-Form Shortcode and it consolidates all the Pro-Form Shortcodes into a single Pro-Form with multiple "Checkout Options" (i.e., it creates a drop-down menu for your customers to choose from). The following is a VERY simple example.</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<pre class="code">';
     echo '<code>';
     echo '[s2Member-Pro-PayPal-Form]' . "\n";
     echo "\t" . '[s2Member-Pro-PayPal-Form /]' . "\n";
     echo "\t" . '[s2Member-Pro-PayPal-Form /]' . "\n";
     echo '[/s2Member-Pro-PayPal-Form]';
     echo '</code>';
     echo '</pre>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '<div class="ws-menu-page-hr"></div>' . "\n";
     echo '<h3>How do "Checkout Options" work behind-the-scenes?</h3>' . "\n";
     echo '<p>Given this simple example (as seen below); s2Member will first take the primary default Shortcode Attributes (from the top-level parent Shortcode); and then it merges those together with Shortcode Attributes from a particular Checkout Option (i.e., a child). The one s2Member merges with is based on the currently selected Checkout Option (i.e., the Checkout Option selected by your customer).</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo '<pre class="code">';
     echo '<code>';
     echo '[s2Member-Pro-PayPal-Form rp="1" rt="M" rr="1" accept_coupons="1"]' . "\n";
     echo "\t" . '[s2Member-Pro-PayPal-Form level="1" desc="Option 1 ($10.00)" ra="10.00" /]' . "\n";
     echo "\t" . '[s2Member-Pro-PayPal-Form level="2" desc="Option 2 ($20.00)" ra="20.00" /]' . "\n";
     echo "\t" . '[s2Member-Pro-PayPal-Form level="3" desc="Option 3 ($30.00)" ra="30.00" /]' . "\n";
     echo '[/s2Member-Pro-PayPal-Form]';
     echo '</code>';
     echo '</pre>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '<p style="font-style:italic;">In this example, the default checkout Level is 1 (because the default Checkout Option is always the first Checkout Option); but that can change depending on which Checkout Option is selected by the customer. All of these Checkout Options will be associated with different prices; and each Checkout Option will provide access to a different Membership Level. The customer may choose which one they would like to pay for and gain access to.</p>' . "\n";
     echo '<p style="font-style:italic;">All of these Checkout Options will allow a Coupon Code; because that\'s an absolute default Shortcode Attribute (in this particular example); which is not overwritten by any of the children. All of these Checkout Options will charge the customer on a recurring basis (once each month); because those are absolute default Shortcode Attributes (in this particular example) i.e., <code>rp="1" rt="M" rr="1"</code>; which are not overwritten by any of the children.</p>' . "\n";
     echo '<p style="font-style:italic;">~ You\'ll be happy to know that ANY Shortcode Attribute can be declared (and/or overridden); in any of these tags. There is no special subset of restricted Shortcode Attributes in any of these; you can do whatever you like once you understand how this works. In addition, this works for Specific Post/Page Access, Buy Now Access, Recurring Access; etc. You can even mix these together if you like. Just wrap all of your Pro-Form Shortcodes with another Pro-Form Shortcode :-)</p>' . "\n";
     echo '</div>' . "\n";
     echo '<div class="ws-menu-page-hr"></div>' . "\n";
     echo '<h3>Linking To A Pro-Form w/ Multiple "Checkout Options"</h3>' . "\n";
     echo '<p>It is also possible to link to a Pro-Form and pre-select a specific Checkout Option that appears in the list. Starting from the first Checkout Option in the list (we call this Checkout Option 1) you can choose which Checkout Option number you want to have selected by default. This is accomplished by linking to any Post/Page on your site which contains a Pro-Form Shortcode; and then adding the <code>?s2p-option=</code> variable onto the end of that URL (as seen below).</p>' . "\n";
     echo '<table class="form-table">' . "\n";
     echo '<tbody>' . "\n";
     echo '<tr>' . "\n";
     echo '<td>' . "\n";
     echo 'This example would pre-select option 2.' . "\n";
     echo '<pre class="code">';
     echo '<code>';
     echo 'http://www.example.com/my-checkout-form/?s2p-option=2';
     echo '</code>';
     echo '</pre>' . "\n";
     echo 'The absolute default Checkout Option is always the first one (Checkout Option 1).<br />' . "\n";
     echo 'This would pre-select option 1 (but this is NOT necessary, because it\'s the default already).' . "\n";
     echo '<pre class="code">';
     echo '<code>';
     echo 'http://www.example.com/my-checkout-form/?s2p-option=1';
     echo '</code>';
     echo '</pre>' . "\n";
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
     echo '</div>' . "\n";
     echo '</td>' . "\n";
     echo '<td class="ws-menu-page-table-r">' . "\n";
     c_ws_plugin__s2member_menu_pages_rs::display();
     echo '</td>' . "\n";
     echo '</tr>' . "\n";
     echo '</tbody>' . "\n";
     echo '</table>' . "\n";
     echo '</div>' . "\n";
 }
 /**
  * Handles ClickBank Return URL processing.
  *
  * @package s2Member\ClickBank
  * @since 1.5
  *
  * @attaches-to ``add_action('init');``
  */
 public static function clickbank_return()
 {
     global $current_site, $current_blog;
     // For Multisite support.
     if (!empty($_GET['s2member_pro_clickbank_return']) && $GLOBALS['WS_PLUGIN__']['s2member']['o']['pro_clickbank_username']) {
         if (is_array($clickbank = c_ws_plugin__s2member_pro_clickbank_utilities::clickbank_postvars_v2_1()) && ($_clickbank = $clickbank)) {
             $clickbank['s2member_log'][] = 'Return-Data received on: ' . date('D M j, Y g:i:s a T');
             $clickbank['s2member_log'][] = 's2Member POST vars verified with ClickBank.';
             $clickbank['s2member_log'][] = 'Sleeping for 5 seconds. Giving ClickBank a chance to finalize processing.';
             sleep(5);
             // Sleep here to give ClickBank a chance to finalize processing. Allows the API call to succeed.
             $clickbank['s2member_log'][] = 'Awake. It\'s ' . date('D M j, Y g:i:s a T') . '. Processing will continue.';
             if (is_array($order = json_decode(c_ws_plugin__s2member_utils_urls::remote('https://api.clickbank.com/rest/1.3/orders/' . $clickbank['cbreceipt'], FALSE, array_merge(c_ws_plugin__s2member_pro_clickbank_utilities::clickbank_api_headers(), array('timeout' => 20))), TRUE)) && ($order = $order['orderData'])) {
                 if (is_array($order) && isset($order[0]) && is_array($order[0])) {
                     $order = $order[0];
                 }
                 // If there is more than one, we only want the first one.
                 foreach ($order as $_k => &$_v) {
                     if (is_array($_v) && isset($_v['@nil'])) {
                         $_v = NULL;
                     }
                 }
                 // Nullify properly.
                 unset($_k, $_v);
                 // Housekeeping.
                 $clickbank['s2member_log'][] = 'Order API variables have been obtained from ClickBank.';
                 $s2vars = c_ws_plugin__s2member_pro_clickbank_utilities::clickbank_parse_s2vars_v2_1(http_build_query($clickbank, NULL, '&'), $order['txnType']);
                 if (!empty($s2vars['s2_p1']) && !empty($s2vars['s2_p3']) && $s2vars['s2_p1'] === '0 D') {
                     // Initial Period. No Trial defaults to Regular Period.
                     $s2vars['s2_p1'] = $s2vars['s2_p3'];
                 }
                 $clickbank['s2vars'] = $s2vars;
                 // So they appear in the log entry for this Notification.
                 if (strcasecmp($order['firstName'] . ' ' . $order['lastName'], $order['customerDisplayName']) !== 0 && preg_match('/([^ ]+)( +)([^ ]+)/', $order['customerDisplayName'])) {
                     list($order['firstName'], $order['lastName']) = preg_split('/ +/', $order['customerDisplayName'], 2);
                 }
                 if (preg_match('/^(TEST_)?SALE$/i', $order['txnType']) && empty($s2vars['s2_p1']) && empty($s2vars['s2_p3'])) {
                     $clickbank['s2member_log'][] = 'ClickBank transaction identified as (`SALE/STANDARD`).';
                     $clickbank['s2member_log'][] = 'Return-Data reformulated. Piping through s2Member\'s core/standard PayPal processor as `txn_type` (`web_accept`).';
                     $clickbank['s2member_log'][] = 'Please check PayPal RTN logs for further processing details.';
                     $rtn = array();
                     // Reset.
                     $rtn['txn_type'] = 'web_accept';
                     $rtn['txn_id'] = $order['receipt'];
                     $rtn['custom'] = $s2vars['s2_custom'];
                     $rtn['mc_gross'] = number_format($order['amount'], 2, '.', '');
                     $rtn['mc_currency'] = strtoupper($order['currency']);
                     $rtn['tax'] = '0.00';
                     // No tax.
                     $rtn['payer_email'] = $order['email'];
                     $rtn['first_name'] = ucwords(strtolower($order['firstName']));
                     $rtn['last_name'] = ucwords(strtolower($order['lastName']));
                     $rtn['option_name1'] = !empty($s2vars['s2_referencing']) ? 'Referencing Customer ID' : 'Originating Domain';
                     $rtn['option_selection1'] = !empty($s2vars['s2_referencing']) ? $s2vars['s2_referencing'] : $_SERVER['HTTP_HOST'];
                     $rtn['option_name2'] = 'Customer IP Address';
                     $rtn['option_selection2'] = $s2vars['s2_customer_ip'];
                     $rtn['item_number'] = $s2vars['s2_invoice'];
                     $rtn['item_name'] = $s2vars['s2_desc'];
                     $rtn_q = '&s2member_paypal_proxy=clickbank&s2member_paypal_proxy_use=standard-emails';
                     if (!empty($_GET['s2member_pro_clickbank_return_success'])) {
                         // Using a custom Return URL on success?
                         $rtn_q .= '&s2member_paypal_return_success=' . rawurlencode(trim(stripslashes($_GET['s2member_pro_clickbank_return_success'])));
                     }
                     $rtn_r = add_query_arg(urlencode_deep($rtn), home_url('/?s2member_pro_clickbank_return&s2member_paypal_return=1' . $rtn_q));
                     $rtn_r = c_ws_plugin__s2member_utils_urls::add_s2member_sig($rtn_r, 's2member_paypal_proxy_verification');
                     $clickbank['s2member_log'][] = $rtn_r;
                     // Log the full Return redirection URL here.
                     wp_redirect($rtn_r);
                     // Proxy this through s2Member's core PayPal processor.
                 } else {
                     if (preg_match('/^(TEST_)?SALE$/i', $order['txnType']) && !empty($s2vars['s2_p1']) && !empty($s2vars['s2_p3'])) {
                         $clickbank['s2member_log'][] = 'ClickBank transaction identified as (`SALE/RECURRING`).';
                         $clickbank['s2member_log'][] = 'Return-Data reformulated. Piping through s2Member\'s core/standard PayPal processor as `txn_type` (`subscr_signup`).';
                         $clickbank['s2member_log'][] = 'Please check PayPal RTN logs for further processing details.';
                         $rtn = array();
                         // Reset.
                         $rtn['txn_type'] = 'subscr_signup';
                         $rtn['subscr_id'] = $s2vars['s2_subscr_id'];
                         $rtn['recurring'] = $order['futurePayments'] > 1 ? '1' : '0';
                         $rtn['txn_id'] = $order['receipt'];
                         $rtn['custom'] = $s2vars['s2_custom'];
                         $rtn['period1'] = $s2vars['s2_p1'];
                         $rtn['period3'] = $s2vars['s2_p3'];
                         $rtn['mc_amount1'] = number_format($order['amount'], 2, '.', '');
                         $rtn['mc_amount3'] = @number_format($order['rebillAmount'], 2, '.', '');
                         $rtn['mc_currency'] = strtoupper($order['currency']);
                         $rtn['tax'] = '0.00';
                         // No tax.
                         $rtn['payer_email'] = $order['email'];
                         $rtn['first_name'] = ucwords(strtolower($order['firstName']));
                         $rtn['last_name'] = ucwords(strtolower($order['lastName']));
                         $rtn['option_name1'] = !empty($s2vars['s2_referencing']) ? 'Referencing Customer ID' : 'Originating Domain';
                         $rtn['option_selection1'] = !empty($s2vars['s2_referencing']) ? $s2vars['s2_referencing'] : $_SERVER['HTTP_HOST'];
                         $rtn['option_name2'] = 'Customer IP Address';
                         $rtn['option_selection2'] = $s2vars['s2_customer_ip'];
                         $rtn['item_number'] = $s2vars['s2_invoice'];
                         $rtn['item_name'] = $s2vars['s2_desc'];
                         $rtn_q = '&s2member_paypal_proxy=clickbank&s2member_paypal_proxy_use=standard-emails';
                         if (!empty($_GET['s2member_pro_clickbank_return_success'])) {
                             // Using a custom Return URL on success?
                             $rtn_q .= '&s2member_paypal_return_success=' . rawurlencode(trim(stripslashes($_GET['s2member_pro_clickbank_return_success'])));
                         }
                         $rtn_r = add_query_arg(urlencode_deep($rtn), home_url('/?s2member_pro_clickbank_return&s2member_paypal_return=1' . $rtn_q));
                         $rtn_r = c_ws_plugin__s2member_utils_urls::add_s2member_sig($rtn_r, 's2member_paypal_proxy_verification');
                         $clickbank['s2member_log'][] = $rtn_r;
                         // Log the full Return redirection URL here.
                         wp_redirect($rtn_r);
                         // Proxy this through s2Member's core PayPal processor.
                     } else {
                         $clickbank['s2member_log'][] = 'Unexpected txnType. The ClickBank txnType did not match a required action.';
                         $clickbank['s2member_log'][] = 'Redirecting Customer to the Home Page, due to an error that occurred.';
                         echo '<script type="text/javascript">' . "\n";
                         echo "alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x('ERROR: Unexpected txnType. Please contact Support for assistance.\\n\\nThe ClickBank txnType did not match a required action.', 's2member-front', 's2member')) . "');" . "\n";
                         echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(home_url('/')) . "';";
                         echo '</script>' . "\n";
                     }
                 }
             } else {
                 $clickbank['s2member_log'][] = 'Unable to obtain API vars. The ClickBank API may NOT have data for this order yet. Or, your ClickBank API Keys are NOT configured properly under `s2Member ⥱ ClickBank Options`.';
                 $clickbank['s2member_log'][] = var_export($_REQUEST, TRUE);
                 // Recording ``$_POST`` + ``$_GET`` vars for analysis and debugging.
                 $clickbank['s2member_log'][] = 'Return-Data reformulated. Piping through s2Member\'s core/standard PayPal processor with `proxy_use` (`ty-email`).';
                 $clickbank['s2member_log'][] = 'Please check PayPal RTN logs for further processing details.';
                 $rtn_q = '&s2member_paypal_proxy=clickbank&s2member_paypal_proxy_use=standard-emails,ty-email';
                 if (!empty($_GET['s2member_pro_clickbank_return_success'])) {
                     $rtn_q .= '&s2member_paypal_return_success=' . rawurlencode(trim(stripslashes($_GET['s2member_pro_clickbank_return_success'])));
                 }
                 $rtn_r = home_url('/?s2member_pro_clickbank_return&s2member_paypal_return=1' . $rtn_q);
                 $rtn_r = c_ws_plugin__s2member_utils_urls::add_s2member_sig($rtn_r, 's2member_paypal_proxy_verification');
                 $clickbank['s2member_log'][] = $rtn_r;
                 // Log the full Return redirection URL here.
                 wp_redirect($rtn_r);
                 // Proxy this through s2Member's core PayPal processor.
             }
         } else {
             $clickbank['s2member_log'][] = 'Unable to verify POST vars. This is most likely related to an invalid ClickBank configuration. Please check: s2Member ⥱ ClickBank Options.';
             $clickbank['s2member_log'][] = 'If you\'re absolutely SURE that your ClickBank configuration is valid, you may want to run some tests on your server, just to be sure \\$_POST variables are populated, and that your server is able to connect to ClickBank over an HTTPS connection.';
             $clickbank['s2member_log'][] = 's2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows server.';
             $clickbank['s2member_log'][] = var_export($_REQUEST, TRUE);
             // Recording _POST + _GET vars for analysis and debugging.
             $clickbank['s2member_log'][] = 'Redirecting Customer to the Home Page, due to an error that occurred.';
             echo '<script type="text/javascript">' . "\n";
             echo "alert('" . c_ws_plugin__s2member_utils_strings::esc_js_sq(_x('ERROR: Unable to verify POST vars. Please contact Support for assistance.\\n\\nThis is most likely related to an invalid ClickBank configuration. If you are the site owner, please check: s2Member ⥱ ClickBank Options.', 's2member-front', 's2member')) . "');" . "\n";
             echo "window.location = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq(home_url("/")) . "';";
             echo '</script>' . "\n";
         }
         $logt = c_ws_plugin__s2member_utilities::time_details();
         $logv = c_ws_plugin__s2member_utilities::ver_details();
         $logm = c_ws_plugin__s2member_utilities::mem_details();
         $log4 = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . "\n" . 'User-Agent: ' . @$_SERVER['HTTP_USER_AGENT'];
         $log4 = is_multisite() && !is_main_site() ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
         $log2 = is_multisite() && !is_main_site() ? 'clickbank-rtn-4-' . trim(preg_replace('/[^a-z0-9]/i', '-', !empty($_log4) ? $_log4 : ''), '-') . '.log' : 'clickbank-rtn.log';
         if ($GLOBALS['WS_PLUGIN__']['s2member']['o']['gateway_debug_logs']) {
             if (is_dir($logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'])) {
                 if (is_writable($logs_dir) && c_ws_plugin__s2member_utils_logs::archive_oversize_log_files()) {
                     file_put_contents($logs_dir . '/' . $log2, 'LOG ENTRY: ' . $logt . "\n" . $logv . "\n" . $logm . "\n" . $log4 . "\n" . c_ws_plugin__s2member_utils_logs::conceal_private_info(var_export($clickbank, TRUE)) . "\n\n", FILE_APPEND);
                 }
             }
         }
         exit;
         // Clean exit; all done here.
     }
 }