Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/sendmachine/api/SendmachineApiClient.php
+++ b/sendmachine/api/SendmachineApiClient.php
@@ -1,35 +1,38 @@
<?php
+defined('ABSPATH') || exit;
defined('CURL_SSLVERSION_DEFAULT') || define('CURL_SSLVERSION_DEFAULT', 0);
-class Sendmachine_Error extends Exception {
-
+class Sendmachine_Error extends Exception
+{
private $err_status;
- public function __construct($error_reason = "", $error_status = "") {
-
+ public function __construct($error_reason = "", $error_status = "")
+ {
parent::__construct($error_reason);
$this->err_status = $error_status;
}
- public function getSendmachineStatus() {
+ public function getSendmachineStatus()
+ {
return $this->err_status;
}
-
}
class Http_Error extends Sendmachine_Error {}
-require_once __dir__ . '/library/Account.php';
-require_once __dir__ . '/library/Sender.php';
-require_once __dir__ . '/library/Campaigns.php';
-require_once __dir__ . '/library/Lists.php';
-require_once __dir__ . '/library/Templates.php';
-require_once __dir__ . '/library/Mail.php';
-
-class SendmachineApiClient {
+require_once __DIR__ . '/library/Account.php';
+require_once __DIR__ . '/library/Sender.php';
+require_once __DIR__ . '/library/Campaigns.php';
+require_once __DIR__ . '/library/Lists.php';
+require_once __DIR__ . '/library/Templates.php';
+require_once __DIR__ . '/library/Mail.php';
+require_once __DIR__ . '/library/Sms.php';
+require_once __DIR__ . '/library/Recipients.php';
+class SendmachineApiClient
+{
/**
* api host
* @var string
@@ -54,18 +57,29 @@
*/
private $curl;
+ private $headers = array();
+
/*
* for debugging
*/
private $debug = false;
+ public $campaigns;
+ public $sender;
+ public $lists;
+ public $account;
+ public $templates;
+ public $mail;
+ public $sms;
+ public $recipients;
+
/**
* connect to api
* @param string $username
* @param string $password
*/
- public function __construct($username = null, $password = null) {
-
+ public function __construct($username = null, $password = null)
+ {
if (!$username || !$password) {
list($username, $password) = $this->check_config();
@@ -87,12 +101,15 @@
$this->account = new Account($this);
$this->templates = new Templates($this);
$this->mail = new Mail($this);
+ $this->sms = new Sms($this);
+ $this->recipients = new Recipients($this);
}
- public function request($url, $method, $params = array()) {
-
+ public function request($url, $method, $params = array())
+ {
$ch = $this->curl;
-
+ $headers = $this->headers ? $this->headers : [];
+
switch (strtoupper($method)) {
case 'GET':
if (count($params)) {
@@ -106,22 +123,29 @@
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen($params)));
+
+ $headers[] = 'Content-Type: application/json';
+ $headers[] = 'Content-Length: ' . strlen($params);
break;
case 'DELETE':
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
+
+ $headers[] = 'Content-Type: application/json';
break;
}
-
+
$final_url = $this->api_host . $url;
-
+
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_DEFAULT);
curl_setopt($ch, CURLOPT_USERPWD, $this->username . ":" . $this->password);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $final_url);
curl_setopt($ch, CURLOPT_VERBOSE, $this->debug);
+ if (!empty($this->headers)) {
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ }
+
if ($this->debug) {
$start = microtime(true);
$this->log('URL: ' . $this->api_host . $url . (is_string($params) ? ", params: " . $params : ""));
@@ -153,20 +177,20 @@
return $result;
}
- public function __destruct() {
-
- if (is_resource($this->curl)) {
-
+ public function __destruct()
+ {
+ if ((class_exists('CurlHandle') && $this->curl instanceof CurlHandle) || is_resource($this->curl)) {
curl_close($this->curl);
}
}
- public function log($msg) {
+ public function log($msg)
+ {
error_log($msg);
}
- public function check_config() {
-
+ public function check_config()
+ {
$config_paths = array(".sendmachine.conf", "/etc/.sendmachine.conf");
$username = null;
$password = null;
@@ -191,8 +215,8 @@
return array($username, $password);
}
- public function set_error($result) {
-
+ public function set_error($result)
+ {
if (is_array($result)) {
if (empty($result['error_reason'])) {
@@ -207,4 +231,14 @@
}
}
-}
No newline at end of file
+ public function set_headers($headers)
+ {
+ $formatted = array();
+
+ foreach ($headers as $name => $value) {
+ $formatted[] = $name . ': ' . $value;
+ }
+
+ $this->headers = $formatted;
+ }
+}
--- a/sendmachine/api/library/Account.php
+++ b/sendmachine/api/library/Account.php
@@ -1,8 +1,12 @@
<?php
+defined( 'ABSPATH' ) || exit;
-class Account {
-
- public function __construct(SendmachineApiClient $master) {
+class Account
+{
+ private $master;
+
+ public function __construct(SendmachineApiClient $master)
+ {
$this->master = $master;
}
@@ -28,11 +32,16 @@
* }
* }
*/
- public function package() {
-
+ public function package()
+ {
return $this->master->request('/account/package', 'GET');
}
+ public function sms_package()
+ {
+ return $this->master->request('/sms/account/package', 'GET');
+ }
+
/**
* Get details about the current rating
* @return array
@@ -40,8 +49,8 @@
* "score"
* }
*/
- public function rating() {
-
+ public function rating()
+ {
return $this->master->request('/account/rating', 'GET');
}
@@ -60,8 +69,8 @@
* }
* }
*/
- public function smtp() {
-
+ public function smtp()
+ {
return $this->master->request('/account/smtp', 'GET');
}
@@ -82,9 +91,8 @@
* }
* }
*/
- public function details() {
-
+ public function details()
+ {
return $this->master->request('/account/user', 'GET');
}
-
}
--- a/sendmachine/api/library/Campaigns.php
+++ b/sendmachine/api/library/Campaigns.php
@@ -1,4 +1,5 @@
<?php
+defined( 'ABSPATH' ) || exit;
class Campaigns {
@@ -105,7 +106,7 @@
*/
public function schedule($campaign_id, $date = "") {
- $params = array('date' => $date);
+ $params = array('datetime' => $date);
return $this->master->request('/campaigns/schedule/' . $campaign_id, 'POST', $params);
}
--- a/sendmachine/api/library/Lists.php
+++ b/sendmachine/api/library/Lists.php
@@ -1,4 +1,5 @@
<?php
+defined( 'ABSPATH' ) || exit;
class Lists {
--- a/sendmachine/api/library/Mail.php
+++ b/sendmachine/api/library/Mail.php
@@ -1,4 +1,5 @@
<?php
+defined( 'ABSPATH' ) || exit;
class Mail {
--- a/sendmachine/api/library/Recipients.php
+++ b/sendmachine/api/library/Recipients.php
@@ -0,0 +1,22 @@
+<?php
+defined( 'ABSPATH' ) || exit;
+
+class Recipients
+{
+ private $master;
+
+ public function __construct(SendmachineApiClient $master)
+ {
+ $this->master = $master;
+ }
+
+ /**
+ *
+ * @param string $email
+ * @return array
+ */
+ public function get($email)
+ {
+ return $this->master->request('/recipient/' . $email, 'GET');
+ }
+}
--- a/sendmachine/api/library/Sender.php
+++ b/sendmachine/api/library/Sender.php
@@ -1,4 +1,5 @@
<?php
+defined( 'ABSPATH' ) || exit;
class Sender {
--- a/sendmachine/api/library/Sms.php
+++ b/sendmachine/api/library/Sms.php
@@ -0,0 +1,26 @@
+<?php
+defined( 'ABSPATH' ) || exit;
+
+class Sms
+{
+ private $master;
+
+ public function __construct(SendmachineApiClient $master)
+ {
+ $this->master = $master;
+ }
+
+ /**
+ * send sms
+ * @param array $details
+ * @return array
+ * {
+ * "sent"
+ * "status"
+ * }
+ */
+ public function send($details)
+ {
+ return $this->master->request('/sms/send', 'POST', $details);
+ }
+}
--- a/sendmachine/api/library/Templates.php
+++ b/sendmachine/api/library/Templates.php
@@ -1,4 +1,5 @@
<?php
+defined( 'ABSPATH' ) || exit;
class Templates {
--- a/sendmachine/includes/sendmachine_api.php
+++ b/sendmachine/includes/sendmachine_api.php
@@ -1,204 +1,321 @@
<?php
+defined( 'ABSPATH' ) || exit;
-class Sm_api {
-
+class Sm_api
+{
private $api;
private $credentials;
-
+
private $debug;
- public function __construct($credentials = NULL, $debug = false) {
-
+ public function __construct($credentials = NULL, $debug = false, $plugin_info = '')
+ {
$this->credentials = $credentials;
-
+
$this->debug = $debug;
- require_once SM_PLUGIN_DIR.'api/SendmachineApiClient.php';
+ require_once SM_PLUGIN_DIR . 'api/SendmachineApiClient.php';
if (!empty($credentials['api_username']) && !empty($credentials['api_password'])) {
-
try {
$this->api = new SendmachineApiClient($credentials['api_username'], $credentials['api_password']);
- }
- catch (Sendmachine_Error $e) {$this->print_exceptions($e);}
- catch (Http_Error $e) {$this->print_exceptions($e);}
- }
-
- }
-
- public function test_credentials(){
-
- if (empty($this->credentials['api_username']) || empty($this->credentials['api_password'])) return "You must provide a username and password";
-
- try{
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ }
+
+ $this->api->set_headers(array(
+ 'X-Plugin' => $plugin_info,
+ 'User-Agent' => $plugin_info,
+ ));
+ }
+ }
+
+ public function test_credentials()
+ {
+ if (empty($this->credentials['api_username']) || empty($this->credentials['api_password'])) return "Provided credentials are not valid";
+
+ try {
$res = $this->api->account->details();
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return $e->getMessage();
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return false;
}
- catch (Sendmachine_Error $e) {$this->print_exceptions($e); return $e->getMessage();}
- catch (Http_Error $e) {$this->print_exceptions($e); return false;}
- if(isset($res['user'])) return true;
-
+ if (isset($res['user'])) return true;
+
$this->print_exceptions($res);
return false;
}
- public function get_lists() {
-
+ public function get_lists()
+ {
try {
$res = $this->api->lists->get();
-
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
}
- catch (Sendmachine_Error $e) {$this->print_exceptions($e); return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e); return NULL;}
-
- if(isset($res['contactlists']) && count($res['contactlists'])) return $res['contactlists'];
-
+
+ if (isset($res['contactlists']) && is_array($res['contactlists']) && count($res['contactlists'])) return $res['contactlists'];
+
$this->print_exceptions($res);
return false;
}
-
- public function subscribe($list_id = NULL, $email_address = NULL, $data = NULL) {
- if(!$list_id || !$email_address) return NULL;
-
- try{
+ public function subscribe($list_id = NULL, $email_address = NULL, $data = NULL)
+ {
+ if (!$list_id || !$email_address) return NULL;
+
+ try {
$res = $this->api->lists->manage_contact($list_id, $email_address, $data);
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
}
- catch (Sendmachine_Error $e) {$this->print_exceptions($e); return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e); return NULL;}
-
- if(isset($res['status']) && $res['status'] == "saved") return true;
-
+
+ if (isset($res['status']) && $res['status'] == "saved") return true;
+
$this->print_exceptions($res);
return false;
}
-
- public function mass_subscribe($list_id = NULL, $recipients = ""){
-
- if(!$list_id || !$recipients || !count($recipients)) return NULL;
-
- try{
+
+ public function mass_subscribe($list_id = NULL, $recipients = array())
+ {
+ if (!$list_id || !$recipients || !count($recipients)) return NULL;
+
+ try {
$res = $this->api->lists->manage_contacts($list_id, $recipients);
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
}
- catch (Sendmachine_Error $e) {$this->print_exceptions($e); return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e); return NULL;}
-
- if(isset($res['status']) && $res['status'] == "saved") return true;
-
+
+ if (isset($res['status']) && $res['status'] == "saved") return true;
+
$this->print_exceptions($res);
return false;
}
-
- public function get_recipient($list_id = NULL, $recipient = ""){
-
- if(!$list_id) return NULL;
-
+
+ public function get_recipient($list_id = NULL, $recipient = "")
+ {
+ if (!$list_id) return NULL;
+
try {
$res = $this->api->lists->contact_details($list_id, $recipient);
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
}
- catch (Sendmachine_Error $e) {$this->print_exceptions($e); return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e); return NULL;}
-
- if(isset($res['contacts'])) return $res['contacts'];
-
+
+ if (isset($res['contacts'])) return $res['contacts'];
+
$this->print_exceptions($res);
return false;
}
-
- public function list_fields($list_id = ""){
-
+
+ public function list_fields($list_id = "")
+ {
try {
$res = $this->api->lists->custom_fields($list_id);
-
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
}
- catch (Sendmachine_Error $e) {$this->print_exceptions($e); return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e); return NULL;}
-
- if(isset($res['custom_fields']) && count($res['custom_fields'])) return $res['custom_fields'];
-
+
+ if (isset($res['custom_fields']) && is_array($res['custom_fields']) && count($res['custom_fields'])) return $res['custom_fields'];
+
$this->print_exceptions($res);
return false;
}
-
- public function get_from_emails() {
-
+
+ public function get_from_emails()
+ {
try {
$res = $this->api->sender->get();
- }
- catch (Sendmachine_Error $e) {$this->print_exceptions($e);return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e);return NULL;}
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ }
+
+ if (isset($res['senderlist']) && is_array($res['senderlist']) && count($res['senderlist'])) return array_column($res['senderlist'], 'email');
- if(isset($res['senderlist']) && count($res['senderlist'])) return array_column($res['senderlist'], 'email');
-
$this->print_exceptions($res);
return false;
}
-
- public function get_email_settings(){
-
+
+ public function get_email_settings()
+ {
try {
$res = $this->api->account->smtp();
- }
- catch (Sendmachine_Error $e) {$this->print_exceptions($e);return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e);return NULL;}
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ }
+
+ if (isset($res['smtp']) && is_array($res['smtp']) && count($res['smtp'])) return $res['smtp'];
- if(isset($res['smtp']) && count($res['smtp'])) return $res['smtp'];
-
$this->print_exceptions($res);
return false;
}
-
- public function create_campaign($params = array()){
-
- if(!$params) return NULL;
-
+
+ public function get_email_package()
+ {
+ try {
+ $res = $this->api->account->package();
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return null;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return null;
+ }
+
+ if (isset($res['package']) && is_array($res['package'])) return $res['package'];
+
+ return null;
+ }
+
+ public function get_sms_package()
+ {
+ try {
+ $res = $this->api->account->sms_package();
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return null;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return null;
+ }
+
+ if (isset($res['package']) && is_array($res['package'])) return $res['package'];
+
+ return null;
+ }
+
+ public function create_campaign($params = array())
+ {
+ if (!$params) return NULL;
+
try {
$res = $this->api->campaigns->create($params);
- }
- catch (Sendmachine_Error $e) {$this->print_exceptions($e);return $e->getMessage();}
- catch (Http_Error $e) {$this->print_exceptions($e);return NULL;}
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return $e->getMessage();
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ }
return $res;
}
-
- public function test_campaign($campaign_id = NULL){
-
- if(!$campaign_id) return NULL;
-
+
+ public function test_campaign($campaign_id = NULL)
+ {
+ if (!$campaign_id) return NULL;
+
try {
$res = $this->api->campaigns->ready($campaign_id);
- }
- catch (Sendmachine_Error $e) {$this->print_exceptions($e);return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e);return NULL;}
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ }
+
+ if (isset($res['status'])) return $res["status"];
- if(isset($res['status'])) return $res["status"];
-
$this->print_exceptions($res);
return false;
}
-
- public function start_campaign($campaign_id = NULL){
-
- if(!$campaign_id) return NULL;
-
+
+ public function start_campaign($campaign_id = NULL)
+ {
+ if (!$campaign_id) return NULL;
+
try {
$res = $this->api->campaigns->send($campaign_id);
- }
- catch (Sendmachine_Error $e) {$this->print_exceptions($e);return NULL;}
- catch (Http_Error $e) {$this->print_exceptions($e);return NULL;}
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return NULL;
+ }
+
+ if (isset($res['status']) && $res['status'] == "launched") return true;
- if(isset($res['status']) && $res['status'] == "launched") return true;
-
$this->print_exceptions($res);
return false;
}
- public function print_exceptions($ex){
+ public function send_sms($to, $message, $sender = '', $admin_phone = '', $click_tracking = 0)
+ {
+ if (empty($this->api)) {
+ return array('success' => false, 'status' => 'failed', 'raw' => array('error' => 'API client not initialised'));
+ }
+
+ $recipients = array($to);
+ if (!empty($admin_phone) && $admin_phone !== $to) {
+ $recipients[] = $admin_phone;
+ }
+
+ $payload = array(
+ 'personalization' => array(array('to' => $recipients)),
+ 'message' => $message,
+ 'message_type' => 'transactional',
+ 'click_tracking' => $click_tracking,
+ );
+ if (!empty($sender)) {
+ $payload['sender'] = $sender;
+ }
+
+ try {
+ $raw = $this->api->sms->send($payload);
+ $raw = is_array($raw) ? $raw : array('raw_response' => $raw);
+
+ return array('success' => true, 'status' => 'sent', 'raw' => $raw);
+ } catch (Sendmachine_Error $e) {
+ $this->print_exceptions($e);
+ return array('success' => false, 'status' => 'failed', 'raw' => array('error' => $e->getMessage()));
+ } catch (Http_Error $e) {
+ $this->print_exceptions($e);
+ return array('success' => false, 'status' => 'failed', 'raw' => array('error' => $e->getMessage()));
+ }
+ }
+
+ public function print_exceptions($ex)
+ {
if ($this->debug) {
$msg = is_object($ex) && method_exists($ex, "getMessage") ? $ex->getMessage() : $ex;
- echo "<div class='sm_wp_display_exceptions' >New exception occurred: " . $msg . "</div>";
+ echo "<div class='sm_wp_display_exceptions'>New exception occurred: " . esc_html( $msg ) . "</div>";
}
}
-
}
--- a/sendmachine/includes/sendmachine_defaults.php
+++ b/sendmachine/includes/sendmachine_defaults.php
@@ -1,9 +1,10 @@
<?php
+defined( 'ABSPATH' ) || exit;
-class Sm_defaults {
-
- public static function config() {
-
+class Sm_defaults
+{
+ public static function config()
+ {
return array(
"keys_to_encode" => array("header_template", "body_template", "footer_template"),
"to_reset" => array('list|id', 'list|data', 'list|fields', 'email|senderlist', 'email|provider_settings', 'email|host', 'email|port', 'email|from_email', 'feed|sender_email', 'feed|list_id'),
@@ -11,23 +12,23 @@
);
}
- public static function defaults() {
-
+ public static function defaults()
+ {
return array(
"list" => array(
"hide_subscribed" => 0,
"use_captcha" => 0,
"redirect_subscribed" => "",
- "message_success_subscribe" => __('You have been successfully subscribed! Thank you!', SM_LANGUAGE_DOMAIN),
- "message_subscriber_exists" => __('You are already subscribed.Thanks anyway.', SM_LANGUAGE_DOMAIN),
- "message_not_subscribed" => __('Something went wrong, you were not subscribed.', SM_LANGUAGE_DOMAIN),
- "message_invalid_email" => __('Please provide a valid email address.', SM_LANGUAGE_DOMAIN),
- "message_invalid_captcha" => __('Invalid captcha code. Please try again.', SM_LANGUAGE_DOMAIN),
- "label_submit_button" => __('Subscribe', SM_LANGUAGE_DOMAIN),
- "message_required_field" => __('Please provide all the required field data.', SM_LANGUAGE_DOMAIN),
+ "message_success_subscribe" => 'You have been successfully subscribed! Thank you!',
+ "message_subscriber_exists" => 'You are already subscribed.Thanks anyway.',
+ "message_not_subscribed" => 'Something went wrong, you were not subscribed.',
+ "message_invalid_email" => 'Please provide a valid email address.',
+ "message_invalid_captcha" => 'Invalid captcha code. Please try again.',
+ "label_submit_button" => 'Subscribe',
+ "message_required_field" => 'Please provide all the required field data.',
"checkbox_register" => 1,
"checkbox_comment" => 0,
- "checkbox_label" => __('Sign me up for the newsletter!', SM_LANGUAGE_DOMAIN),
+ "checkbox_label" => 'Sign me up for the newsletter!',
"checkbox_checked" => 0,
"simple_subscribe" => 1
),
@@ -42,12 +43,11 @@
"feed" => array(
"post_nr" => 10,
"header_template" => "<h1>||SITENAME||</h1>",
- "body_template" => "<h3><a href="||POSTURL||">||POSTTITLE||</a></h3><p>||POSTCONTENTSUMMARY||</p><p><em>Author: ||POSTAUTHOR|| Posted on ||POSTDATE||</em></p>",
- "footer_template" => "<p><em>If you don't want to receive this messages anymore, unsubscribe by clicking <a href="[[UNSUB_LINK]]">here</a>!</em></p>",
+ "body_template" => "<h3><a href="||POSTURL||">||POSTTITLE||</a></h3><p>||POSTCONTENTSUMMARY||</p><p><em>Author: ||POSTAUTHOR|| Posted on ||POSTDATE||</em></p>",
+ "footer_template" => "<p><em>If you don't want to receive this messages anymore, unsubscribe by clicking <a href="[[UNSUB_LINK]]">here</a>!</em></p>",
"template_width" => "600px",
"template_bgcolor" => "#fff"
)
);
}
-
-}
No newline at end of file
+}
--- a/sendmachine/includes/sendmachine_email_manager.php
+++ b/sendmachine/includes/sendmachine_email_manager.php
@@ -1,39 +1,40 @@
<?php
+defined( 'ABSPATH' ) || exit;
-class Sm_email_manager {
-
- private $phpmailer_headers;
+class Sm_email_manager
+{
- public function __construct() {
+ private $phpmailer_headers;
+ public function __construct()
+ {
add_action('init', array($this, 'manage_email_requests'));
add_action('comment_post', array($this, 'add_sm_headers'));
- add_action('register_post', array($this, 'add_sm_headers'));
+ add_action('user_register', array($this, 'add_sm_headers'));
add_action('phpmailer_init', array($this, 'configure_smtp'));
}
- public function add_sm_headers() {
-
+ public function add_sm_headers()
+ {
$app = Sm_wp::instance()->app;
$key = current_filter();
-
+
if (!empty($app['email'][$key]) && !empty($app['email'][$key . "_label"]))
$this->phpmailer_headers = current_filter();
}
- public function configure_smtp($phpmailer) {
-
+ public function configure_smtp($phpmailer)
+ {
$sm = Sm_wp::instance();
-
+
if (empty($sm->app['email']['enable_service']) || (empty($sm->app['email']['emailconfirmed']) && empty($sm->bypass_emailconfirmation))) return false;
-
- $required_items = array('encryption','host','port','from_email');
-
- foreach($required_items as $k => $v) {
-
- if(!isset($sm->app['email'][$v]) || !trim($sm->app['email'][$v])) return false;
+
+ $required_items = array('encryption', 'host', 'port', 'from_email');
+
+ foreach ($required_items as $k => $v) {
+ if (!isset($sm->app['email'][$v]) || !trim($sm->app['email'][$v])) return false;
}
$phpmailer->isSMTP();
@@ -42,18 +43,17 @@
$phpmailer->Host = $sm->app['email']['host'];
$phpmailer->Port = $sm->app['email']['port'];
-
+
$phpmailer->From = $sm->app['email']['from_email'];
$phpmailer->FromName = isset($sm->app['email']['from_name']) ? $sm->app['email']['from_name'] : NULL;
-
+
$phpmailer->SMTPAuth = true;
$phpmailer->Username = $sm->app['credentials']['api_username'];
$phpmailer->Password = $sm->app['credentials']['api_password'];
$phpmailer = apply_filters('sm_mail_custom_options', $phpmailer);
-
- if ($this->phpmailer_headers) {
+ if ($this->phpmailer_headers) {
$e = new Exception();
$trace = method_exists($e, 'getTrace') ? $e->getTrace() : NULL;
$caller_func = NULL;
@@ -70,36 +70,42 @@
$recipient = isset($caller_func['args'][0]) ? $caller_func['args'][0] : NULL;
- if ($this->phpmailer_headers == "register_post" && $recipient == get_option('admin_email'))
+ if ($this->phpmailer_headers == "user_register" && $recipient == get_option('admin_email'))
return false;
-
- if(SM_SITE_APP_URL) $phpmailer->SMTPDebug = 1;
+
+ if (SM_WP_DEV_MODE) $phpmailer->SMTPDebug = 1;
else $phpmailer->SMTPDebug = 0;
-
- $phpmailer->AddCustomHeader(SM_CAMPAIGN_HEADER . ": " . $sm->app['email'][$this->phpmailer_headers . "_label"]);
+
+ $phpmailer->addCustomHeader(SM_CAMPAIGN_HEADER . ": " . $sm->app['email'][$this->phpmailer_headers . "_label"]);
}
}
- public function manage_email_requests() {
-
+ public function manage_email_requests()
+ {
if (empty($_REQUEST['sm_email_wp_request'])) return false;
- $action = isset($_REQUEST['sm_action']) ? $_REQUEST['sm_action'] : NULL;
+ $action = isset($_REQUEST['sm_action']) ? sanitize_key( $_REQUEST['sm_action'] ) : NULL;
+
+ check_admin_referer( 'sm_admin_wp_nonce' );
+
$data = $_POST;
if ($action == "send_test_email") {
-
$blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
$ret = NULL;
- if(isset($data['email']) && trim($data['email']))
- $ret = wp_mail($data['email'], 'Test email -'.$blogname, 'This is a test email from your wordpress site');
+ $email = isset( $data['email'] ) ? sanitize_email( wp_unslash( $data['email'] ) ) : '';
+
+ if ( $email && is_email( $email ) ) {
+ /* translators: %s: site name */
+ $ret = wp_mail( $email, sprintf( __( 'Test email - %s', 'sendmachine' ), $blogname ), __( 'This is a test email from your WordPress site.', 'sendmachine' ) );
+ }
+
+ /* translators: %s: email address */
+ if ($ret) $message = array("smEmailSentSuccess", "email_sent_success", sprintf(__("Email to %s sent successfully!", 'sendmachine'), esc_html( $email )), "updated");
+ else $message = array("smEmailSentError", "email_sent_error", __("Something went wrong. Email not sent.", 'sendmachine'), "error");
- if($ret) $message = array("smEmailSentSuccess","email_sent_success", sprintf(__("Email to %s sent successfully!", SM_LANGUAGE_DOMAIN), $data['email']), "updated");
- else $message = array("smEmailSentError","email_sent_error", __("Something went wrong. Email not sent.", SM_LANGUAGE_DOMAIN), "error");
-
Sm_wp::instance()->enqueue_admin_message($message);
}
}
-
}
--- a/sendmachine/includes/sendmachine_feed_manager.php
+++ b/sendmachine/includes/sendmachine_feed_manager.php
@@ -1,29 +1,29 @@
<?php
+defined( 'ABSPATH' ) || exit;
-class Sm_feed_manager {
-
- public function preview_newsletter($feed){
-
+class Sm_feed_manager
+{
+ public function preview_newsletter($feed)
+ {
return $this->build_newsletter($feed);
}
- public function manage_feed($feed, $sm, $action) {
-
+ public function manage_feed($feed, $sm, $action)
+ {
if (
- !empty($feed['sm_feed_campaign_name']) &&
- !empty($feed['sm_feed_campaign_subject']) &&
- !empty($feed['post_nr']) &&
- !empty($feed['list_id']) &&
- !empty($feed['sender_email'])
+ !empty($feed['sm_feed_campaign_name']) &&
+ !empty($feed['sm_feed_campaign_subject']) &&
+ !empty($feed['post_nr']) &&
+ !empty($feed['list_id']) &&
+ !empty($feed['sender_email'])
) {
-
$args = array('numberposts' => $feed['post_nr']);
$body = $this->build_newsletter($feed);
if (!$body)
- return array('smSendCampaignErrorNoPost', 'campaignsend_err_nopost', __("No post found.Campaign not created!", SM_LANGUAGE_DOMAIN), "error");
-
+ return array('smSendCampaignErrorNoPost', 'campaignsend_err_nopost', __("No post found.Campaign not created!", 'sendmachine'), "error");
+
$res = $sm->create_campaign(array(
"name" => $feed['sm_feed_campaign_name'],
"subject" => $feed['sm_feed_campaign_subject'],
@@ -33,16 +33,16 @@
));
if (isset($res['status']) && ($res['status'] == "created")) {
-
+
if ($action == 'sm_feed_save_draft') {
- $link = "<a target='_blank' href='" . SM_SITE_APP_URL . "/#/campaigns/" . $res['id'] . "/source_editor' >" . __("here", SM_LANGUAGE_DOMAIN) . "</a>";
- return array('smSendCampaignSaveDraft', 'campaignsend_saved_draft', sprintf(__("Campaign saved as draft in your Sendmachine account. Click %s to access it.", SM_LANGUAGE_DOMAIN), $link), "updated");
- }
- elseif ($action == 'sm_feed_send_campaign') {
+ $link = "<a target='_blank' href='" . esc_url( SM_SITE_APP_URL . '/#/campaigns/' . $res['id'] . '/source_editor' ) . "'>" . esc_html__( "here", 'sendmachine' ) . "</a>";
+ /* translators: %s: link to campaign */
+ return array('smSendCampaignSaveDraft', 'campaignsend_saved_draft', sprintf(__("Campaign saved as draft in your Sendmachine account. Click %s to access it.", 'sendmachine'), $link), "updated");
+ } elseif ($action == 'sm_feed_send_campaign') {
if (!$tested_cmp = $sm->test_campaign($res['id']))
- return array('smSendCampaignErrorGeneral', 'campaignsend_err_general', __("Something went wrong.Campaign could not be tested.", SM_LANGUAGE_DOMAIN), "error");
+ return array('smSendCampaignErrorGeneral', 'campaignsend_err_general', __("Something went wrong.Campaign could not be tested.", 'sendmachine'), "error");
if ($tested_cmp != "ok") {
@@ -54,47 +54,49 @@
foreach ($tested_cmp as $err_rsn) {
- $reasons .= "<li>" . $err_rsn . "</li>";
+ $reasons .= "<li>" . esc_html( $err_rsn ) . "</li>";
}
}
$reasons .= "</ul>";
- return array('smSendCampaignErrorTestFail', 'campaignsend_err_testfail', sprintf(__("Campaign created, but not started. Reported reasons: %s", SM_LANGUAGE_DOMAIN), $reasons), "error");
+ /* translators: %s: list of reasons why campaign test failed */
+ return array('smSendCampaignErrorTestFail', 'campaignsend_err_testfail', sprintf(__("Campaign created, but not started. Reported reasons: %s", 'sendmachine'), $reasons), "error");
}
if ($sm->start_campaign($res['id'])) {
- $track_url = "<a target='_blank' href='" . SM_SITE_APP_URL . "//#/stats/" . $res['id'] . "' >" . __("here", SM_LANGUAGE_DOMAIN) . "</a>";
- return array('smSendCampaignStartedSuccess', 'campaignsend_started_success', sprintf(__("Campaign started successfully. You can track it by clicking %s.", SM_LANGUAGE_DOMAIN), $track_url), "updated");
- }
-
- return array('smSendCampaignLaunchErrpr', 'campaignsend_launch_error', __("For some reason campaign was not started.", SM_LANGUAGE_DOMAIN), "error");
+ $track_url = "<a target='_blank' href='" . esc_url( SM_SITE_APP_URL . '/#/stats/' . $res['id'] ) . "'>" . esc_html__( "here", 'sendmachine' ) . "</a>";
+ /* translators: %s: link to campaign */
+ return array('smSendCampaignStartedSuccess', 'campaignsend_started_success', sprintf(__("Campaign started successfully. You can track it by clicking %s.", 'sendmachine'), $track_url), "updated");
+ }
+
+ return array('smSendCampaignLaunchErrpr', 'campaignsend_launch_error', __("For some reason campaign was not started.", 'sendmachine'), "error");
}
}
-
+
return array('smSendCampaignErrorNotCreated', 'campaignsend_err_notcreated', isset($res['status']) ? $res['status'] : $res, "error");
- }
+ }
- return array('smSendCampaignError', 'campaignsend_error', __("All fields are required.", SM_LANGUAGE_DOMAIN), "error");
+ return array('smSendCampaignError', 'campaignsend_error', __("All fields are required.", 'sendmachine'), "error");
}
-
- private function build_newsletter($feed_data = NULL) {
- $args = array('numberposts' => $feed_data['post_nr']);
+ private function build_newsletter($feed_data = NULL)
+ {
+ $args = array('numberposts' => $feed_data['post_nr'], 'post_status' => 'publish');
- $rp = wp_get_recent_posts($args);
+ $rp = get_posts($args);
if (!$rp) return false;
$body = "<html><head></head><body>";
- $body .= "<table style='padding:10px;width:100%;max-width:".$feed_data['template_width']."' width='600' bgcolor='".$feed_data['template_bgcolor']."' cellpadding='0' cellspacing='0' ><tr><td>";
+ $body .= "<table style='padding:10px;width:100%;max-width:" . esc_attr( $feed_data['template_width'] ) . "' width='600' bgcolor='" . esc_attr( $feed_data['template_bgcolor'] ) . "' cellpadding='0' cellspacing='0'><tr><td>";
$body .= "<div id='sm_nl_header' >" . $this->parse_nl_parts($feed_data['header_template']) . "</div>";
$body .= "<div id='sm_nl_body'>";
foreach ($rp as $post) {
- $body .= "<div class='sm_nl_postcontent' >" . $this->parse_nl_parts($feed_data['body_template'], $post) . "</div>";
+ $body .= "<div class='sm_nl_postcontent' >" . $this->parse_nl_parts($feed_data['body_template'], (array) $post) . "</div>";
}
$body .= "</div>";
@@ -105,73 +107,71 @@
return $body;
}
- private function parse_nl_parts($tpl, $args = NULL) {
-
+ private function parse_nl_parts($tpl, $args = NULL)
+ {
$keywords = $this->keywords('values', $args);
$delimiter = Sm_wp::instance()->config["feed_delimiter"];
$content = stripslashes(html_entity_decode($tpl));
foreach ($keywords as $k => $v) {
- $content = preg_replace("/(". preg_quote(sprintf($delimiter, $k)).")/", $v, $content);
+ $content = preg_replace("/(" . preg_quote(sprintf($delimiter, $k)) . ")/", $v, $content);
}
return $content;
}
-
- public function keywords($action, $args = array()) {
+ public function keywords($action, $args = array())
+ {
$keywords = array(
"SITENAME" => array(
"value" => get_bloginfo('name'),
- "description" => __("Your blog's title", SM_LANGUAGE_DOMAIN)
+ "description" => __("Your blog's title", 'sendmachine')
),
"SITEDESCRIPTION" => array(
"value" => get_option('blogdescription'),
- "description" => __("Blog's description", SM_LANGUAGE_DOMAIN)
+ "description" => __("Blog's description", 'sendmachine')
),
"ADMINEMAIL" => array(
"value" => get_option('admin_email'),
- "description" => __("Administrator's email address", SM_LANGUAGE_DOMAIN)
+ "description" => __("Administrator's email address", 'sendmachine')
),
"SITEURL" => array(
"value" => get_option('siteurl'),
- "description" => __("Blog URL.", SM_LANGUAGE_DOMAIN)
+ "description" => __("Blog URL.", 'sendmachine')
),
"POSTTITLE" => array(
"value" => isset($args['post_title']) ? $args['post_title'] : "",
- "description" => __("Display post title.Works only in template body", SM_LANGUAGE_DOMAIN)
+ "description" => __("Display post title.Works only in template body", 'sendmachine')
),
"POSTURL" => array(
"value" => isset($args['guid']) ? $args['guid'] : "",
- "description" => __("Post url. Works only in template body", SM_LANGUAGE_DOMAIN)
+ "description" => __("Post url. Works only in template body", 'sendmachine')
),
"POSTCONTENTSUMMARY" => array(
"value" => isset($args['post_content']) ? substr($args['post_content'], 0, 300) . " [...]" : "",
- "description" => __("Post's content summary.Display first 300 characters of content. Works only in template body", SM_LANGUAGE_DOMAIN)
+ "description" => __("Post's content summary.Display first 300 characters of content. Works only in template body", 'sendmachine')
),
"POSTCONTENTFULL" => array(
"value" => isset($args['post_content']) ? $args['post_content'] : "",
- "description" => __("Post's content (full content). Works only in template body", SM_LANGUAGE_DOMAIN)
+ "description" => __("Post's content (full content). Works only in template body", 'sendmachine')
),
"POSTAUTHOR" => array(
- "value" => isset($args['post_author']) ? get_user_by('id', $args['post_author'])->data->user_nicename : "",
- "description" => __("Who wrote post. Works only in template body", SM_LANGUAGE_DOMAIN)
+ "value" => isset($args['post_author']) ? (($u = get_user_by('ID', $args['post_author'])) ? $u->data->user_nicename : '') : "",
+ "description" => __("Who wrote post. Works only in template body", 'sendmachine')
),
"POSTDATE" => array(
"value" => isset($args['post_date']) ? $args['post_date'] : "",
- "description" => __("Post publish date. Works only in template body", SM_LANGUAGE_DOMAIN)
+ "description" => __("Post publish date. Works only in template body", 'sendmachine')
)
);
$ret_arr = array();
-
- foreach ($keywords as $keyword => $data) {
+ foreach ($keywords as $keyword => $data) {
if ($action == "values") $ret_arr[$keyword] = $data['value'];
elseif ($action == "description") $ret_arr[$keyword] = $data['description'];
}
-
+
return $ret_arr;
}
-
}
--- a/sendmachine/includes/sendmachine_subscribe_manager.php
+++ b/sendmachine/includes/sendmachine_subscribe_manager.php
@@ -1,16 +1,19 @@
<?php
+defined( 'ABSPATH' ) || exit;
-class Sm_subscribe_manager {
-
+class Sm_subscribe_manager
+{
+
+ public $app;
private $subscribe_notification;
-
+
private $form_count = 0;
private $captcha_prefix = '83921';
- public function __construct($app_config) {
-
+ public function __construct($app_config)
+ {
$this->app = $app_config;
-
+
if (!empty($this->app['list']['checkbox_comment'])) add_action('comment_form', array($this, 'build_checkbox'));
if (!empty($this->app['list']['checkbox_register'])) add_action('register_form', array($this, 'build_checkbox'));
@@ -19,17 +22,17 @@
add_shortcode('sm_subscribe_form', array($this, 'build_shortcode_form'));
}
- public function build_widget_form($args, $instance) {
-
- if(!$this->can_build()) return false;
+ public function build_widget_form($args, $instance)
+ {
+ if (!$this->can_build()) return false;
$title = $instance['title'];
$out = $args['before_widget'];
- $out .=$args['before_title'] . $title . $args['after_title'];
-
- $out .= $instance['description'] ? "<p>".$instance['description']."</p>" : "";
+ $out .= $args['before_title'] . $title . $args['after_title'];
+
+ $out .= $instance['description'] ? "<p>" . esc_html( $instance['description'] ) . "</p>" : "";
$out .= $this->build_form($args['id']);
@@ -38,49 +41,50 @@
return $out;
}
- public function build_shortcode_form() {
+ public function build_shortcode_form()
+ {
+ if (!$this->can_build()) return false;
- if(!$this->can_build()) return false;
-
return $this->build_form();
}
- public function build_checkbox() {
-
- if(!$this->can_build()) return false;
+ public function build_checkbox()
+ {
+ if (!$this->can_build()) return false;
$checked = !empty($this->app['list']['checkbox_checked']) ? "checked" : "";
echo ''
- . '<input type="hidden" name="sm_subscribe_wp_request" value="1"/>'
- . '<input type="hidden" name="sm_action" value="subscribe_checkbox"/> '
- . '<label>'
- . '<br><input type="checkbox" name="sm_do_subscribe" value="1" ' . $checked . ' /> ' . $this->app['list']['checkbox_label'] . '</label><br><br>';
+ . '<input type="hidden" name="sm_subscribe_wp_request" value="1"/>'
+ . '<input type="hidden" name="sm_action" value="subscribe_checkbox"/> '
+ . wp_nonce_field( 'sm_subscribe_nonce', '_wpnonce', true, false ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_nonce_field returns safe HTML
+ . '<label>'
+ . '<br><input type="checkbox" name="sm_do_subscribe" value="1" ' . esc_attr( $checked ) . ' /> ' . esc_html($this->app['list']['checkbox_label']) . '</label><br><br>';
}
-
- private function can_build() {
-
- if(empty($this->app['list']['id']))
+
+ private function can_build()
+ {
+ if (empty($this->app['list']['id']))
return false;
-
+
if (!empty($this->app['list']['hide_subscribed']) && is_user_logged_in()) {
$is_subbed = (bool)get_user_meta(get_current_user_id(), SM_USER_META_NAME, true);
-
+
return $is_subbed ? false : true;
}
-
+
return true;
}
- private function build_form($instance_id = "") {
-
+ private function build_form($instance_id = "")
+ {
$this->form_count++;
$defaults = Sm_defaults::defaults();
-
+
if ($this->form_count <= 1) {
-
- wp_enqueue_style('sm-wp-widget-styles', plugins_url('static/css/sm-widget.css', SM_PLUGIN_FILE));
- wp_enqueue_script('sm-wp-widget-script', plugins_url('static/js/sm-widget.js', SM_PLUGIN_FILE));
+
+ wp_enqueue_style('sm-wp-widget-styles', plugins_url('static/css/sm-widget.css', SM_PLUGIN_FILE), array(), SM_VERSION);
+ wp_enqueue_script('sm-wp-widget-script', plugins_url('static/js/sm-widget.js', SM_PLUGIN_FILE), array(), SM_VERSION, true);
wp_localize_script('sm-wp-widget-script', 'SM_JS_DATA', array(
'loading_img' => plugin_dir_url(SM_PLUGIN_FILE) . 'static/images/loading.gif',
'redirect' => $this->app['list']['redirect_subscribed'],
@@ -91,10 +95,10 @@
$fields = isset($this->app['list']['fields']) ? $this->app['list']['fields'] : NULL;
if (!$fields) return "";
-
+
$list_fields = '';
$captcha_field = '';
-
+
foreach ($fields as $list_field) {
if ($list_field['visible']) {
@@ -105,31 +109,29 @@
$required = ($list_field['required']) ? "*" : "";
$element_id = strtolower("form_input_{$list_field['form_name']}_$instance_id");
- $list_fields .= "<div class='sm_wp_input_group'><label for='$element_id' class='sm_wp_form_label'>" . $list_field['form_name'] . " $required</label>";
+ $list_fields .= "<div class='sm_wp_input_group'><label for='" . esc_attr( $element_id ) . "' class='sm_wp_form_label'>" . esc_html( $list_field['form_name'] ) . " $required</label>";
- if (in_array($list_field['cf_type'], array("text", "number", "email","date","birthday"))) {
+ if (in_array($list_field['cf_type'], array("text", "number", "email", "date", "birthday"))) {
$placeholder = "";
-
- if($list_field['cf_type'] == "date") $placeholder = "yyyy/mm/dd";
- elseif($list_field['cf_type'] == "birthday") $placeholder = "mm/dd";
-
- $list_fields .= "<input id='$element_id' class='sm_wp_form_input_text' placeholder='$placeholder' type='text' name='" . $list_field['name'] . "'/>";
- }
- elseif ($list_field['cf_type'] == "radiobutton") {
+
+ if ($list_field['cf_type'] == "date") $placeholder = "yyyy/mm/dd";
+ elseif ($list_field['cf_type'] == "birthday") $placeholder = "mm/dd";
+
+ $list_fields .= "<input id='" . esc_attr( $element_id ) . "' class='sm_wp_form_input_text' placeholder='" . esc_attr( $placeholder ) . "' type='text' name='" . esc_attr( $list_field['name'] ) . "'/>";
+ } elseif ($list_field['cf_type'] == "radiobutton") {
foreach ($list_field['options'] as $option) {
- $list_fields .= "<label class='sm_wp_form_radio_label'><input class='sm_wp_form_input_radio' type='radio' value='" . $option . "' name='" . $list_field['name'] . "' /> " . $option . "</label><br>";
+ $list_fields .= "<label class='sm_wp_form_radio_label'><input class='sm_wp_form_input_radio' type='radio' value='" . esc_attr( $option ) . "' name='" . esc_attr( $list_field['name'] ) . "' /> " . esc_html( $option ) . "</label><br>";
}
- }
- elseif ($list_field['cf_type'] == "dropdown") {
+ } elseif ($list_field['cf_type'] == "dropdown") {
- $list_fields .= "<select class='sm_list_dropdown sm_wp_form_select' name='" . $list_field['name'] . "'>";
+ $list_fields .= "<select class='sm_list_dropdown sm_wp_form_select' name='" . esc_attr( $list_field['name'] ) . "'>";
$list_fields .= "<option></option>";
foreach ($list_field['options'] as $option) {
- $list_fields .= "<option value='" . $option . "'>" . $option . "</option>";
+ $list_fields .= "<option value='" . esc_attr( $option ) . "'>" . esc_html( $option ) . "</option>";
}
$list_fields .= "</select>";
@@ -137,125 +139,136 @@
$list_fields .= "</div>";
}
}
-
- if(isset($this->app['list']['use_captcha']) && $this->app['list']['use_captcha']) {
-
- if(class_exists('ReallySimpleCaptcha')) {
-
- list($captcha_file, $prefix) = $this->genCaptcha();
-
- $captcha_field .= '<table><tbody><tr>';
- $captcha_field .= "<td><img id='form_captcha_img_{$instance_id}' class='sm_wp_form_captcha_img' src='{$captcha_file}' alt='Captcha'></td>";
- $captcha_field .= '<td>';
- $captcha_field .= "<input id='form_input_captcha_{$instance_id}' class='sm_wp_form_input_text' type='text' name='captcha'/>";
- $captcha_field .= "<input id='form_captcha_prefix_{$instance_id}' type='hidden' name='captcha_prefix' value='{$prefix}'/>";
- $captcha_field .= '</td>';
- $captcha_field .= '</tr></tbody></table>';
+
+ if (isset($this->app['list']['use_captcha']) && $this->app['list']['use_captcha']) {
+ if (class_exists('ReallySimpleCaptcha')) {
+ $captcha_result = $this->genCaptcha();
+ if ($captcha_result) {
+ list($captcha_file, $prefix) = $captcha_result;
+ $captcha_field .= '<table><tbody><tr>';
+ $captcha_field .= "<td><img id='form_captcha_img_{$instance_id}' class='sm_wp_form_captcha_img' src='" . esc_url( $captcha_file ) . "' alt='Captcha'></td>";
+ $captcha_field .= '<td>';
+ $captcha_field .= "<input id='form_input_captcha_{$instance_id}' class='sm_wp_form_input_text' type='text' name='captcha'/>";
+ $captcha_field .= "<input id='form_captcha_prefix_{$instance_id}' type='hidden' name='captcha_prefix' value='" . esc_attr( $prefix ) . "'/>";
+ $captcha_field .= '</td>';
+ $captcha_field .= '</tr></tbody></table>';
+ }
}
}
-
- $msg = isset($this->subscribe_notification['default']) && $this->subscribe_notification['default'] ? __($this->subscribe_notification['message'], SM_LANGUAGE_DOMAIN) : $this->subscribe_notification['message'];
- $notices = $this->subscribe_notification && $this->subscribe_notification['form_nr'] == $this->form_count ? "<div class='".$this->subscribe_notification['status']."' >".$msg."</div>" : "";
- $submit_action = isset($this->app['list']['reload_subscribe']) && $this->app['list']['reload_subscribe'] ? "" : "subscribe_user(this);return false;" ;
-
- $subscribe_label = isset($this->app['list']['label_submit_button']) ? $this->app['list']['label_submit_button'] : $defaults['list']['label_submit_button'];
-
+
+ if ( $this->subscribe_notification && $this->subscribe_notification['form_nr'] == $this->form_count ) {
+ $msg = esc_html( $this->subscribe_notification['message'] );
+ $notices = "<div class='" . esc_attr( $this->subscribe_notification['status'] ) . "' >" . $msg . "</div>";
+ } else {
+ $notices = "";
+ }
+ $submit_action = isset($this->app['list']['reload_subscribe']) && $this->app['list']['reload_subscribe'] ? "" : "subscribe_user(this);return false;";
+
+ $subscribe_label = isset($this->app['list']['label_submit_button']) ? $this->app['list']['label_submit_button'] : $defaults['list']['label_submit_button'];
+
return ''
- . '<div class="sendmachine_wp_subscribe" >'
- . '<form id="sm_subscribe_form_'.$instance_id.'" class="subscribe_form" method="post" onsubmit="'.$submit_action.'" >'
- . '<input type="hidden" name="sm_subscribe_wp_request" value="1"/>'
- . '<input type="hidden" name="sm_action" value="subscribe_form"/> '
- . '<input type="hidden" name="sm_form_nr" value="'.$this->form_count.'"/> '
- . $list_fields
- . $captcha_field
- . '<div class="sm_wp_form_submit_button_wrapper"><input class="sm_wp_form_submit_button" type="submit" value="'. $subscribe_label .'" /></div>'
- . '<div class="sm_wp_sub_req_resp" >' . $notices . '</div>'
- . '</form>'
- . '</div>';
+ . '<div class="sendmachine_wp_subscribe" >'
+ . '<form id="sm_subscribe_form_' . esc_attr( $instance_id ) . '" class="subscribe_form" method="post" onsubmit="' . esc_attr( $submit_action ) . '" >'
+ . '<input type="hidden" name="sm_subscribe_wp_request" value="1"/>'
+ . wp_nonce_field( 'sm_subscribe_nonce', '_wpnonce', true, false ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_nonce_field returns safe HTML
+ . '<input type="hidden" name="sm_action" value="subscribe_form"/> '
+ . '<input type="hidden" name="sm_form_nr" value="' . esc_attr( $this->form_count ) . '"/> '
+ . $list_fields
+ . $captcha_field
+ . '<div class="sm_wp_form_submit_button_wrapper"><input class="sm_wp_form_submit_button" type="submit" value="' . esc_attr( $subscribe_label ) . '" /></div>'
+ . '<div class="sm_wp_sub_req_resp" >' . $notices . '</div>'
+ . '</form>'
+ . '</div>';
}
- public function manage_subscribe_requests() {
-
+ public function manage_subscribe_requests()
+ {
if (empty($_REQUEST['sm_subscribe_wp_request'])) return false;
-
- $action = isset($_REQUEST['sm_action']) ? $_REQUEST['sm_action'] : NULL;
- $data = $_POST;
-
+
+ $action = isset($_REQUEST['sm_action']) ? sanitize_key( $_REQUEST['sm_action'] ) : NULL;
+ $data = $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce is verified below
+
+ if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $data['_wpnonce'] ), 'sm_subscribe_nonce' ) ) {
+ return false;
+ }
+
$is_ajax = isset($data['is_sm_ajax_request']) ? $data['is_sm_ajax_request'] : NULL;
$sm_api = Sm_wp::instance()->sm;
$defaults = Sm_defaults::defaults();
if ($action == "subscribe_form") {
- $email = isset($data['EMAIL']) ? $data['EMAIL'] : NULL;
+ $email = isset($data['EMAIL']) ? sanitize_email( wp_unslash( $data['EMAIL'] ) ) : NULL;
unset($data['EMAIL']);
$captcha = isset($data['captcha']) ? $data['captcha'] : NULL;
unset($data['captcha']);
$captcha_prefix = isset($data['captcha_prefix']) ? $data['captcha_prefix'] : NULL;
unset($data['captcha_prefix']);
-
+
$needs_captcha = false;
if (isset($this->app['list']['use_captcha']) && $this->app['list']['use_captcha'] && class_exists('ReallySimpleCaptcha')) {
$needs_captcha = true;
}
-
+
$respawn_captcha = false;
- if($needs_captcha && $is_ajax) $respawn_captcha = true;
-
+ if ($needs_captcha && $is_ajax) $respawn_captcha = true;
+
$form_nr = isset($data['sm_form_nr']) ? $data['sm_form_nr'] : 0;
-
+
$fields = $this->app['list']['fields'];
- if(!$fields) {
+ if (!$fields) {
$msg = array("message" => $this->app['list']['message_not_subscribed'], "status" => "error");
$this->respond($msg, $is_ajax, $form_nr);
return false;
}
-
- if(!$email) {
+
+ if (!$email || ! is_email( $email )) {
$_msg = isset($this->app['list']['message_invalid_email']) ? $this->app['list']['message_invalid_email'] : $defaults['list']['message_invalid_email'];
$this->respond(array("message" => $_msg, "status" => "error"), $is_ajax, $form_nr);
return false;
}
-
+
$fn = array();
$has_error = false;
- foreach($fields as $f) $fn[] = $f['name'];
+ foreach ($fields as $f) $fn[] = $f['name'];
+
+ foreach ($data as $k => $v) {
- foreach($data as $k => $v) {
-
- if(!in_array($k,$fn)) {
+ if (!in_array($k, $fn)) {
unset($data[$k]);
continue;
}
-
- foreach($fields as $field) {
- if($field['name'] === $k) {
- if($field['required'] && !$v) {
+
+ $data[$k] = sanitize_text_field( wp_unslash( $v ) );
+
+ foreach ($fields as $field) {
+ if ($field['name'] === $k) {
+ if ($field['required'] && !$v) {
$has_error = true;
}
break;
}
}
}
-
+
if ($has_error) {
$_msg = isset($this->app['list']['message_required_field']) ? $this->app['list']['message_required_field'] : $defaults['list']['message_required_field'];
$this->respond(array("message" => $_msg, "status" => "error"), $is_ajax, $form_nr);
return false;
}
-
- if($needs_captcha) {
-
+
+ if ($needs_captcha) {
+
$correct = false;
-
- if(substr($captcha_prefix, 0, strlen($this->captcha_prefix)) === $this->captcha_prefix) {
-
+
+ if (substr($captcha_prefix, 0, strlen($this->captcha_prefix)) === $this->captcha_prefix) {
+
$captcha_instance = new ReallySimpleCaptcha();
$correct = $captcha_instance->check($captcha_prefix, $captcha);
$captcha_instance->remove($captcha_prefix);
}
-
- if(!$correct) {
+
+ if (!$correct) {
$_msg = isset($this->app['list']['message_invalid_captcha']) ? $this->app['list']['message_invalid_captcha'] : $defaults['list']['message_invalid_captcha'];
$this->respond(array("message" => $_msg, "status" => "error"), $is_ajax, $form_nr, $respawn_captcha);
return false;
@@ -267,113 +280,109 @@
$this->respond($msg, $is_ajax, $form_nr, $respawn_captcha);
return false;
}
-
+
if ($resp = $sm_api->subscribe($this->app['list']['id'], $email, $data)) {
+ if (is_user_logged_in()) add_user_meta(get_current_user_id(), SM_USER_META_NAME, 1);
- if (is_user_logged_in()) add_user_meta( get_current_user_id(), SM_USER_META_NAME, 1);
-
- if (trim($this->app['list']['redirect_subscribed']) && !$is_ajax) wp_redirect($this->app['list']['redirect_subscribed']);
+ if (trim($this->app['list']['redirect_subscribed']) && !$is_ajax) wp_safe_redirect($this->app['list']['redirect_subscribed']);
$msg = array("message" => $this->app['list']['message_success_subscribe'], "status" => "success");
$this->respond($msg, $is_ajax, $form_nr, $respawn_captcha);
return true;
}
-
+
$msg = array("message" => $this->app['list']['message_not_subscribed'], "status" => "error");
$this->respond($msg, $is_ajax, $form_nr, $respawn_captcha);
return false;
- }
- elseif ($action == "subscribe_checkbox") {
-
+ } elseif ($action == "subscribe_checkbox") {
if (empty($data['sm_do_subscribe'])) return false;
if (is_user_logged_in()) {
-
$user = wp_get_current_user();
$email = $user->user_email;
- }
- else {
-
+ } else {
if (!empty($data['email']))
- $email = $data['email'];
+ $email = sanitize_email( wp_unslash( $data['email'] ) );
elseif (!empty($data['user_email']))
- $email = $data['user_email'];
+ $email = sanitize_email( wp_unslash( $data['user_email'] ) );
else
return false;
}
$resp = $sm_api->subscribe($this->app['list']['id'], $email);
-
- if (is_user_logged_in() && $resp) add_user_meta( get_current_user_id(), SM_USER_META_NAME, 1);
- }
- elseif ($action == "sync_users") {
-
+
+ if (is_user_logged_in() && $resp) add_user_meta(get_current_user_id(), SM_USER_META_NAME, 1);
+ } elseif ($action == "sync_users") {
+ if ( ! current_user_can( 'manage_options' ) ) {
+ return false;
+ }
+
if (empty($this->app['list']['id'])) {
- $message = array("smUsersSyncErrorApiLost", "users_sync_api_lost", __("API must be connected and you have to select a list in order to sync your users.", SM_LANGUAGE_DOMAIN), "error");
+ $message = array("smUsersSyncErrorApiLost", "users_sync_api_lost", __("API must be connected and you have to select a list in order to sync your users.", 'sendmachine'), "error");
Sm_wp::instance()->enqueue_admin_message($message);
return NULL;
}
$ret = NULL;
-
- $users = get_users(array( 'fields' => array( 'user_email' ) ));
-
+
+ $users = get_users(array('fields' => array('user_email')));
+
$recipients = array();
- foreach($users as $k => $u){
- array_push($recipients, $u->user_email);
+ foreach ($users as $k => $u) {
+ $recipients[] = $u->user_email;
}
-
+
$cnt = count($recipients);
-
+
$ret = $sm_api->mass_subscribe($this->app['list']['id'], $recipients);
-
- if($ret) $message = array("smUsersSyncSuccess","users_sync success", sprintf(__("Sync complete! %u users were added to your contact list.", SM_LANGUAGE_DOMAIN), $cnt), "updated");
- else $message = array("smUsersSyncError","users_sync_error", __("Something went wrong. Users not synced.", SM_LANGUAGE_DOMAIN), "error");
+
+ /* translators: %u: number of users synced */
+ if ($ret) $message = array("smUsersSyncSuccess", "users_sync success", sprintf(__("Sync complete! %u users were added to your contact list.", 'sendmachine'), $cnt), "updated");
+ else $message = array("smUsersSyncError", "users_sync_error", __("Something went wrong. Users not synced.", 'sendmachine'), "error");
Sm_wp::instance()->enqueue_admin_message($message);
}
}
-
- private function genCaptcha() {
-
- if(!class_exists('ReallySimpleCaptcha')) {
+
+ private function genCaptcha()
+ {
+ if (!class_exists('ReallySimpleCaptcha')) {
return false;
}
-
+
$captcha_instance = new ReallySimpleCaptcha();
-
+
// cleanup files older than 30 minutes
$captcha_instance->cleanup(30);
-
+
$word = $captcha_instance->generate_random_word();
-
- $prefix = $this->captcha_prefix . mt_rand();
+
+ $prefix = $this->captcha_prefix . wp_rand();
$captcha_image = $captcha_instance->generate_image($prefix, $word);
- $captcha_file = rtrim(get_bloginfo('wpurl'), '/') . '/wp-content/plugins/really-simple-captcha/tmp/' . $captcha_image;
-
+ $captcha_file = plugins_url( 'really-simple-captcha/tmp/' . $captcha_image );
+
return array($captcha_file, $prefix);
}
-
- private function respond($msg = "", $is_ajax = false, $form_nr = 0, $respawn_captcha = false) {
-
- if($respawn_captcha) {
- list($captcha_file, $prefix) = $this->genCaptcha();
- $msg['respawn_captcha'] = array(
- "img" => $captcha_file,
- "prefix" => $prefix
- );
+
+ private function respond($msg = "", $is_ajax = false, $form_nr = 0, $respawn_captcha = false)
+ {
+ if ($respawn_captcha) {
+ $captcha_result = $this->genCaptcha();
+ if ($captcha_result) {
+ list($captcha_file, $prefix) = $captcha_result;
+ $msg['respawn_captcha'] = array(
+ "img" => $captcha_file,
+ "prefix" => $prefix
+ );
+ }
}
-
+
if ($is_ajax) {
-
- echo json_encode($msg);
- exit();
+ wp_send_json($msg);
} else {
-
- $msg['form_nr']= $form_nr;
+ $msg['form_nr'] = $form_nr;
$this->subscribe_notification = $msg;
return true;
}
}
-
}
--- a/sendmachine/includes/utils.php
+++ b/sendmachine/includes/utils.php
@@ -1,27 +1,5 @@
<?php
-
-class Sm4WpUtils {
-
- private static $notifications;
-
- public static function add_notification($message = '', $section = 'general', $type = 'success') {
-
- self::$notifications[$section] =