PluginProbe
MailPoet – Newsletters, Email Marketing, and Automation / 5.38.0
MailPoet – Newsletters, Email Marketing, and Automation v5.38.0
5.38.0 5.37.0 5.36.1 5.36.0 5.35.1 5.35.0 5.34.3 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 All 542 releases
← All changes | lib/API/JSON/API.php +29 -1 5.34.25.38.0 View file →
@@ -207,9 +207,12 @@
207 207 $endpoint = $this->container->get($this->requestEndpointClass);
208 208 if (!$endpoint instanceof Endpoint) {
209 209 throw new \Exception(__('Invalid API endpoint.', 'mailpoet'));
210 210 }
211 - if (!method_exists($endpoint, $this->requestMethod)) {
211 + if (
212 + !method_exists($endpoint, $this->requestMethod)
213 + || !$this->isDispatchableEndpointMethod($endpoint, $this->requestMethod)
214 + ) {
212 215 throw new \Exception(__('Invalid API endpoint method.', 'mailpoet'));
213 216 }
214 217
215 218 if (!$endpoint->isMethodAllowed($this->requestMethod, $this->requestType)) {
@@ -232,8 +235,11 @@
232 235 $errorResponse = $this->createErrorResponse(Error::FORBIDDEN, $errorMessage, Response::STATUS_FORBIDDEN);
233 236 return $errorResponse;
234 237 }
235 238 $response = $endpoint->{$this->requestMethod}($this->requestData);
239 + if (!$response instanceof Response) {
240 + throw new \Exception(__('Invalid API endpoint method.', 'mailpoet'));
241 + }
236 242 return $response;
237 243 } catch (Exception $e) {
238 244 $this->logError($e);
239 245 return $this->errorHandler->convertToResponse($e);
@@ -245,8 +251,30 @@
245 251 $errorMessage = $e->getMessage();
246 252 $errorResponse = $this->createErrorResponse(Error::BAD_REQUEST, $errorMessage, Response::STATUS_BAD_REQUEST);
247 253 return $errorResponse;
248 254 }
255 + }
256 +
257 + /**
258 + * The response-builder helpers on the Endpoint base class are framework plumbing,
259 + * blocked by name so that a subclass override cannot re-expose them. Non-public
260 + * methods are never dispatchable.
261 + */
262 + private function isDispatchableEndpointMethod(Endpoint $endpoint, string $requestMethod): bool {
263 + // Magic methods (__construct, __call, __get, __invoke, ...) are never actions.
264 + if (strpos($requestMethod, '__') === 0) {
265 + return false;
266 + }
267 + if (method_exists(Endpoint::class, $requestMethod)) {
268 + return false;
269 + }
270 + $method = new \ReflectionMethod($endpoint, $requestMethod);
271 + // PHP resolves method names case-insensitively; require the exact declared casing
272 + // so that every name-keyed lookup downstream matches the method that runs.
273 + if ($method->getName() !== $requestMethod) {
274 + return false;
275 + }
276 + return $method->isPublic();
249 277 }
250 278
251 279 public function validatePermissions($requestMethod, $permissions) {
252 280 // validate method permission if defined, otherwise validate global permission