PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / lib / Newsletter / Sharing / PublicEmailRoute.php
mailpoet / lib / Newsletter / Sharing Last commit date
PublicEmailController.php 1 month ago PublicEmailRoute.php 1 month ago ShareMetadataBuilder.php 2 months ago ShareVisibility.php 2 months ago index.php 2 months ago
PublicEmailRoute.php
137 lines
1 <?php declare(strict_types = 1);
2
3 namespace MailPoet\Newsletter\Sharing;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use InvalidArgumentException;
9 use MailPoet\Newsletter\Url as NewsletterUrl;
10 use MailPoet\Util\ThirdPartyOutput;
11 use MailPoet\WP\Functions as WPFunctions;
12
13 class PublicEmailRoute {
14 public const QUERY_VAR = 'mailpoet_public_email';
15 private const IDENTIFIER_CAPTURE = '([0-9a-f]{12}(?:-[^/]+)?)';
16
17 /** @var PublicEmailController */
18 private $controller;
19
20 /** @var NewsletterUrl */
21 private $newsletterUrl;
22
23 /** @var WPFunctions */
24 private $wp;
25
26 public function __construct(
27 PublicEmailController $controller,
28 NewsletterUrl $newsletterUrl,
29 WPFunctions $wp
30 ) {
31 $this->controller = $controller;
32 $this->newsletterUrl = $newsletterUrl;
33 $this->wp = $wp;
34 }
35
36 public function init(): void {
37 $this->wp->addAction('init', [$this, 'registerRewriteRule']);
38 $this->wp->addFilter('query_vars', [$this, 'addQueryVars']);
39 $this->wp->addAction('template_redirect', [$this, 'render']);
40 }
41
42 public function registerRewriteRule(): void {
43 $prefix = ltrim($this->newsletterUrl->getPublicSharePathPrefix(), '/');
44 $this->wp->addRewriteRule(
45 '^' . $prefix . self::IDENTIFIER_CAPTURE . '/?$',
46 'index.php?' . self::QUERY_VAR . '=$matches[1]',
47 'top'
48 );
49 }
50
51 public function addQueryVars(array $queryVars): array {
52 $queryVars[] = self::QUERY_VAR;
53 return $queryVars;
54 }
55
56 public function render(): void {
57 $identifier = $this->getIdentifier();
58 if ($identifier === '') {
59 return;
60 }
61
62 try {
63 $newsletter = $this->controller->getNewsletter($identifier);
64 } catch (InvalidArgumentException $e) {
65 // The path matched our prefix but the identifier didn't resolve to a
66 // shareable newsletter. Let WP continue: it will serve a real page at
67 // that URL if one exists, or fall through to its own 404.
68 return;
69 }
70 if (!$this->controller->isCanonicalIdentifier($identifier, $newsletter)) {
71 $this->wp->wpSafeRedirect($this->controller->getCanonicalUrl($newsletter), 301);
72 exit;
73 }
74 $this->display($this->controller->render($newsletter));
75 }
76
77 private function getIdentifier(): string {
78 $identifier = $this->wp->getQueryVar(self::QUERY_VAR, '');
79 if (is_string($identifier) && trim($identifier) !== '') {
80 return trim($identifier);
81 }
82
83 return $this->getIdentifierFromRequestPath();
84 }
85
86 private function getIdentifierFromRequestPath(): string {
87 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized through WPFunctions below.
88 $rawUri = $_SERVER['REQUEST_URI'] ?? '';
89 if (!is_string($rawUri) || $rawUri === '') {
90 return '';
91 }
92 $unslashed = $this->wp->wpUnslash($rawUri);
93 if (!is_string($unslashed)) {
94 return '';
95 }
96 $requestUri = $this->wp->sanitizeTextField($unslashed);
97 if (!is_string($requestUri) || $requestUri === '') {
98 return '';
99 }
100
101 $requestPath = $this->wp->wpParseUrl($requestUri, PHP_URL_PATH);
102 if (!is_string($requestPath)) {
103 return '';
104 }
105
106 $homePath = $this->wp->wpParseUrl($this->wp->homeUrl('/'), PHP_URL_PATH);
107 if (is_string($homePath) && $homePath !== '/') {
108 $homePath = rtrim($homePath, '/');
109 if (strpos($requestPath, $homePath . '/') === 0) {
110 $requestPath = substr($requestPath, strlen($homePath));
111 }
112 }
113
114 $pathPrefix = $this->newsletterUrl->getPublicSharePathPrefix();
115 if (strpos($requestPath, $pathPrefix) !== 0) {
116 return '';
117 }
118
119 $identifier = trim(substr($requestPath, strlen($pathPrefix)), '/');
120 if ($identifier === '' || strpos($identifier, '/') !== false) {
121 return '';
122 }
123
124 return $this->newsletterUrl->parsePublicShareIdentifier($identifier) ? $identifier : '';
125 }
126
127 private function display(string $html): void {
128 ThirdPartyOutput::preventHtmlRewriting();
129 header('Content-Type: text/html; charset=utf-8');
130 header('Cache-Control: private, no-store, max-age=0');
131 header('X-Robots-Tag: noindex, nofollow');
132 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
133 echo $html;
134 exit;
135 }
136 }
137