Plugin Directory

Changeset 3444723


Ignore:
Timestamp:
01/22/2026 11:01:31 AM (4 weeks ago)
Author:
modulards
Message:

v2.6.1

Location:
modular-connector/trunk
Files:
9 added
20 deleted
36 edited

Legend:

Unmodified
Added
Removed
  • modular-connector/trunk/init.php

    r3441222 r3444723  
    44 * Plugin URI: https://modulards.com/herramienta-gestion-webs/
    55 * Description: Connect and manage all your WordPress websites in an easier and more efficient way. Backups, bulk updates, Uptime Monitor, statistics, security, performance, client reports and much more.
    6  * Version: 2.6.0
     6 * Version: 2.6.1
    77 * License: GPL v3.0
    88 * License URI: https://www.gnu.org/licenses/gpl.html
     
    2121define('MODULAR_CONNECTOR_BASENAME', sprintf('%s/%s', basename(dirname(__FILE__)), basename(__FILE__)));
    2222define('MODULAR_CONNECTOR_MU_BASENAME', sprintf('0-%s.php', dirname(MODULAR_CONNECTOR_BASENAME)));
    23 define('MODULAR_CONNECTOR_VERSION', '2.6.0');
     23define('MODULAR_CONNECTOR_VERSION', '2.6.1');
    2424define('MODULAR_ARES_SCHEDULE_HOOK', 'modular_connector_run_schedule');
    2525define('MODULAR_CONNECTOR_STORAGE_PATH', untrailingslashit(WP_CONTENT_DIR) . DIRECTORY_SEPARATOR . 'modular_storage');
  • modular-connector/trunk/modular-php/src/ModularClient.php

    r3441222 r3444723  
    6868        $this->oauthToken = $config['oauth_token'];
    6969
     70        // Only disable for local/staging development
     71        $isDevEnvironment = in_array($config['env'] ?? 'production', ['local', 'stg', 'dev', 'testing'], true);
     72
    7073        $this->client = new Client([
    71             'verify' => false,
     74            'verify' => !$isDevEnvironment,
    7275            'base_uri' => rtrim($config['base_uri'], '/'),
    7376            'headers' => [
  • modular-connector/trunk/readme.txt

    r3441222 r3444723  
    44Requires at least: 6.0
    55Tested up to: 6.9
    6 Stable tag: 2.6.0
     6Stable tag: 2.6.1
    77Requires PHP: 7.4
    88License: GPLv3
     
    184184
    185185== Changelog ==
     186= v2.6.1 =
     187Release date: 2026-01-22
     188
     189* Extra security measures added to validate JWT tokens
     190* FIXED: Error executing WordPress pseudo cron
     191
    186192= v2.6.0 =
    187193Release date: 2026-01-16
  • modular-connector/trunk/src/app/Http/Controllers/AuthController.php

    r3427955 r3444723  
    1717{
    1818    /**
     19     * Get code from request (header XOR query, never both).
     20     *
     21     * @param \Illuminate\Http\Request $request
     22     * @return string|null
     23     */
     24    private function getCodeFromRequest($request): ?string
     25    {
     26        $hasQuery = $request->has('code');
     27        $hasHeader = $request->hasHeader('x-mo-code');
     28
     29        if ($hasQuery) {
     30            return $request->get('code');
     31        }
     32
     33        if ($hasHeader) {
     34            return $request->header('x-mo-code');
     35        }
     36
     37        return null;
     38    }
     39
     40    /**
    1941     * Confirm OAuth from Modular
    2042     *
     
    2648    {
    2749        $client = OauthClient::getClient();
    28         $code = $request->header('x-mo-code') ?: $request->get('xcode') ?: $request->get('code');
     50
     51        // code: XOR - query or header, never both (already validated in isDirectRequest)
     52        $code = $this->getCodeFromRequest($request);
    2953
    3054        try {
  • modular-connector/trunk/src/app/Http/Middleware/AuthenticateLoopback.php

    r3441222 r3444723  
    88use Modular\ConnectorDependencies\Illuminate\Support\Facades\Log;
    99use function Modular\ConnectorDependencies\abort;
    10 use function Modular\ConnectorDependencies\app;
    1110
    1211class AuthenticateLoopback
    1312{
    14 
    1513    /**
    1614     * Handle an incoming request.
     15     *
     16     * Authentication methods (mutually exclusive - one or the other):
     17     * - x-mo-authentication header with JWT (for loopback/oauth)
     18     * - sig query parameter with JWT (for type=request from API)
    1719     *
    1820     * @param Request $request
     
    2325    public function handle($request, \Closure $next)
    2426    {
    25         $action = app()->getScheduleHook();
    26 
    27         // Check for x-mo-Authentication header or sig parameter (API authentication with client_secret)
    28         if ($request->hasHeader('x-mo-authentication') || $request->has('sig')) {
    29             $token = $request->hasHeader('x-mo-authentication')
    30                 ? $request->header('x-mo-authentication', '')
    31                 : $request->get('sig');
    32 
    33             $source = $request->hasHeader('x-mo-authentication') ? 'header' : 'parameter';
    34 
    35             // Verify JWT with client_secret
    36             if (!$this->verifyApiAuthentication($request, $token, $source)) {
    37                 abort(404);
    38             }
    39 
    40             Log::debug("API authentication verified successfully via {$source}");
    41         } elseif ($request->hasHeader('Authentication')) {
    42             // Legacy Authentication header (uses default hashing key)
    43             $authHeader = $request->header('Authentication', '');
    44 
    45             if (!JWT::verify($authHeader, $action)) {
    46                 Log::debug('Invalid JWT for schedule hook', [
    47                     'hook' => $action,
    48                     'header' => $authHeader,
    49                 ]);
    50 
    51                 abort(404);
    52             }
    53         } else {
    54             // Fallback to nonce validation
    55             $isValid = check_ajax_referer($action, 'nonce', false);
    56 
    57             if (!$isValid) {
    58                 Log::debug('Invalid nonce for schedule hook', [
    59                     'hook' => $action,
    60                     'nonce' => $request->input('nonce'),
    61                 ]);
    62 
    63                 abort(404);
    64             }
    65         }
    66 
    67         Log::debug('Valid authentication for loopback request');
     27        $hasAuthHeader = $request->hasHeader('x-mo-authentication');
     28        $hasSigParam = $request->has('sig');
     29
     30        // Must have one authentication method
     31        if (!$hasAuthHeader && !$hasSigParam) {
     32            Log::debug('Authentication: No auth method provided', [
     33                'ip' => $request->ip(),
     34                'uri' => $request->fullUrl(),
     35            ]);
     36
     37            abort(404);
     38        }
     39
     40        // Cannot have both (mutual exclusivity - already validated in isDirectRequest)
     41        if ($hasAuthHeader && $hasSigParam) {
     42            Log::debug('Authentication: Both auth methods provided', [
     43                'ip' => $request->ip(),
     44            ]);
     45
     46            abort(404);
     47        }
     48
     49        // Get token from header or query
     50        $token = $hasAuthHeader
     51            ? $request->header('x-mo-authentication')
     52            : $request->get('sig');
     53
     54        if (!$this->verifyAuthentication($request, $token)) {
     55            abort(404);
     56        }
     57
     58        Log::debug('Authentication verified successfully', [
     59            'method' => $hasAuthHeader ? 'x-mo-authentication' : 'sig',
     60        ]);
    6861
    6962        return $next($request);
     
    7164
    7265    /**
    73      * Verify API authentication with client_secret.
     66     * Verify JWT authentication with client_secret.
    7467     *
    7568     * @param Request $request
    76      * @param string $token JWT token from header or parameter
    77      * @param string $source 'header' or 'parameter'
     69     * @param string $token JWT token from header
    7870     * @return bool
    7971     */
    80     private function verifyApiAuthentication($request, $token, $source)
     72    private function verifyAuthentication(Request $request, string $token): bool
    8173    {
    82         // Verify token is not empty
    8374        if (empty($token)) {
    84             Log::debug("API auth ({$source}): Token is empty");
     75            Log::debug('x-mo-authentication: Token is empty');
    8576            return false;
    8677        }
     
    8980        $clientSecret = OauthClient::getClient()->getClientSecret();
    9081
    91         // If client_secret is empty, authentication is invalid
    9282        if (empty($clientSecret)) {
    93             Log::debug("API auth ({$source}): client_secret is empty");
    94             return false;
    95         }
    96 
    97         // Get request data based on route
     83            Log::debug('x-mo-authentication: client_secret is empty - site not connected');
     84
     85            return false;
     86        }
     87
     88        // Get request data based on route for validation
    9889        $requestData = $this->getRequestData($request);
    9990
    10091        if ($requestData === null) {
    101             Log::debug("API auth ({$source}): Unable to get request data");
    102             return false;
    103         }
    104 
    105         // Verify JWT using client_secret with request data
    106         if (!$this->verifyJwtWithData($token, $clientSecret, $requestData)) {
    107             Log::debug("API auth ({$source}): Invalid JWT");
    108             return false;
     92            Log::debug('x-mo-authentication: Unable to get request data');
     93
     94            return false;
     95        }
     96
     97        // Verify JWT signature and claims
     98        $jwtPayload = $this->verifyJwt($token, $clientSecret);
     99
     100        if ($jwtPayload === null) {
     101            Log::debug('x-mo-authentication: JWT verification failed');
     102
     103            return false;
     104        }
     105
     106        // Verify client_id matches (site-specific token binding)
     107        $siteClientId = OauthClient::getClient()->getClientId();
     108        $jwtClientId = $jwtPayload->client_id ?? null;
     109
     110        if (empty($siteClientId) || empty($jwtClientId)) {
     111            Log::debug('x-mo-authentication: client_id missing', [
     112                'site_client_id' => $siteClientId ? 'present' : 'missing',
     113                'jwt_client_id' => $jwtClientId ? 'present' : 'missing',
     114            ]);
     115
     116            return false;
     117        }
     118
     119        if (!hash_equals($siteClientId, $jwtClientId)) {
     120            Log::debug('x-mo-authentication: client_id mismatch');
     121
     122            return false;
     123        }
     124
     125        Log::debug('x-mo-authentication: client_id verified');
     126
     127        // For loopback requests, verify lbn (loopback nonce) matches
     128        if (isset($requestData->type) && $requestData->type === 'loopback') {
     129            $queryLbn = $requestData->lbn ?? null;
     130            $jwtLbn = $jwtPayload->lbn ?? null;
     131
     132            if (empty($queryLbn) || empty($jwtLbn)) {
     133                Log::debug('x-mo-authentication: Loopback nonce missing', [
     134                    'query_lbn' => $queryLbn ? 'present' : 'missing',
     135                    'jwt_lbn' => $jwtLbn ? 'present' : 'missing',
     136                ]);
     137                return false;
     138            }
     139
     140            if (!hash_equals($jwtLbn, $queryLbn)) {
     141                Log::debug('x-mo-authentication: Loopback nonce mismatch');
     142
     143                return false;
     144            }
     145
     146            Log::debug('x-mo-authentication: Loopback nonce verified');
    109147        }
    110148
     
    118156     * @return object|array|null
    119157     */
    120     private function getRequestData($request)
     158    private function getRequestData(Request $request)
    121159    {
    122160        $routeName = $request->route()->getName();
     
    124162        // Special handling for OAuth route
    125163        if ($routeName === 'modular-connector.oauth') {
     164            // code: XOR - query or header, never both (already validated in isDirectRequest)
     165            $code = $request->has('code')
     166                ? $request->get('code')
     167                : $request->header('x-mo-code');
     168
    126169            return (object)[
    127                 'code' => $request->get('code'),
     170                'code' => $code,
    128171                'state' => $request->get('state'),
    129172            ];
    130173        }
    131         // For other routes, get modularRequest from cache
     174
     175        // Special handling for schedule.run route (loopback)
     176        if ($routeName === 'schedule.run') {
     177            return (object)[
     178                'type' => 'loopback',
     179                'lbn' => $request->get('lbn'), // Loopback nonce from query string
     180            ];
     181        }
     182
     183        // For other routes, get modularRequest from route parameter
    132184        $modularRequest = $request->route()->parameter('modular_request');
    133185
    134186        if (!$modularRequest) {
    135             Log::debug('x-mo-Authentication: modularRequest not found in cache', [
     187            Log::debug('x-mo-authentication: modularRequest not found', [
    136188                'route' => $routeName,
    137189            ]);
     190
    138191            return null;
    139192        }
     
    158211        foreach ($requiredKeys as $key) {
    159212            if (!array_key_exists($key, $modularRequest->attributesToArray())) {
    160                 Log::debug('x-mo-Authentication: modularRequest missing required key', [
     213                Log::debug('x-mo-authentication: modularRequest missing required key', [
    161214                    'missing_key' => $key,
    162215                    'route' => $routeName,
     
    167220        }
    168221
    169         // Return the entire modularRequest object for hashing
    170222        return $modularRequest;
    171223    }
    172224
    173225    /**
    174      * Verify JWT signature and integrity.
    175      *
    176      * Decodes the JWT, regenerates the signature with the same payload and client_secret,
    177      * and compares. If signatures match, the JWT is authentic and unmodified.
     226     * Verify JWT signature, structure, and temporal claims.
    178227     *
    179228     * @param string $token
    180229     * @param string $clientSecret
    181      * @param object|array $requestData
    182      * @return bool
     230     * @return object|null Returns payload on success, null on failure
    183231     */
    184     private function verifyJwtWithData($token, $clientSecret, $requestData)
     232    private function verifyJwt(string $token, string $clientSecret): ?object
    185233    {
    186         // Remove Bearer prefix
     234        // Remove Bearer prefix if present
    187235        $token = str_replace('Bearer ', '', $token);
    188236        $jwtParts = explode('.', $token);
    189237
    190238        if (count($jwtParts) !== 3) {
    191             Log::debug('x-mo-Authentication: Invalid JWT structure');
    192             return false;
     239            Log::debug('x-mo-authentication: Invalid JWT structure - expected 3 parts');
     240            return null;
    193241        }
    194242
    195243        [$base64UrlHeader, $base64UrlPayload, $base64UrlSignature] = $jwtParts;
    196244
    197         // Decode header and payload to inspect them
    198         $header = json_decode(JWT::base64UrlDecode($base64UrlHeader));
    199         $payload = json_decode(JWT::base64UrlDecode($base64UrlPayload));
    200 
    201         if (!$header || !$payload) {
    202             Log::debug('x-mo-Authentication: Failed to decode JWT', [
    203                 'header_valid' => is_object($header),
    204                 'payload_valid' => is_object($payload),
    205             ]);
    206             return false;
    207         }
    208 
    209         Log::debug('x-mo-Authentication: JWT payload decoded', [
    210             'client_id' => $payload->client_id ?? null,
    211             'exp' => $payload->exp ?? null,
    212             'iat' => $payload->iat ?? null,
    213         ]);
    214 
    215         // Regenerate signature with the exact same payload
    216         // If this matches the received signature, the payload is authentic and unmodified
    217         $signatureInput = "$base64UrlHeader.$base64UrlPayload";
     245        // Decode header and payload with strict JSON parsing
     246        try {
     247            $headerJson = JWT::base64UrlDecode($base64UrlHeader);
     248            $payloadJson = JWT::base64UrlDecode($base64UrlPayload);
     249
     250            $header = json_decode($headerJson, false, 512, JSON_THROW_ON_ERROR);
     251            $payload = json_decode($payloadJson, false, 512, JSON_THROW_ON_ERROR);
     252        } catch (\JsonException $e) {
     253            Log::debug('x-mo-authentication: JSON decode failed', ['error' => $e->getMessage()]);
     254
     255            return null;
     256        }
     257
     258        if ($header->alg !== 'HS256') {
     259            Log::debug('x-mo-authentication: Invalid algorithm', ['alg' => $header->alg]);
     260
     261            return null;
     262        }
     263
     264        // Verify signature using timing-safe comparison
     265        $signatureInput = "{$base64UrlHeader}.{$base64UrlPayload}";
    218266        $expectedSignature = hash_hmac('sha256', $signatureInput, $clientSecret, true);
    219267        $receivedSignature = JWT::base64UrlDecode($base64UrlSignature);
    220268
    221269        if (!hash_equals($expectedSignature, $receivedSignature)) {
    222             Log::debug('x-mo-Authentication: JWT signature mismatch - token tampered or wrong secret');
    223             return false;
    224         }
    225 
    226         Log::debug('x-mo-Authentication: JWT signature valid');
    227 
    228         // Verify expiration
     270            Log::debug('x-mo-authentication: JWT signature mismatch');
     271            return null;
     272        }
     273
     274        // Verify temporal claims
    229275        $currentTime = time();
    230         if ($currentTime > ($payload->exp ?? 0)) {
    231             Log::debug('x-mo-Authentication: JWT expired', [
     276
     277        // Check expiration (exp)
     278        if (isset($payload->exp) && $currentTime > $payload->exp) {
     279            Log::debug('x-mo-authentication: JWT expired', [
    232280                'exp' => $payload->exp,
    233281                'now' => $currentTime,
    234             ]);
    235             return false;
    236         }
    237 
    238         // Verify issued at
    239         if ($currentTime < ($payload->iat ?? 0)) {
    240             Log::debug('x-mo-Authentication: JWT not yet valid', [
     282                'expired_ago' => $currentTime - $payload->exp,
     283            ]);
     284            return null;
     285        }
     286
     287        // Check not before (iat - issued at)
     288        if (isset($payload->iat) && $currentTime < $payload->iat) {
     289            Log::debug('x-mo-authentication: JWT not yet valid', [
    241290                'iat' => $payload->iat,
    242291                'now' => $currentTime,
    243292            ]);
    244             return false;
    245         }
    246 
    247         return true;
     293            return null;
     294        }
     295
     296        Log::debug('x-mo-authentication: JWT verified successfully', [
     297            'client_id' => $payload->client_id ?? 'not set',
     298            'type' => $payload->type ?? 'not set',
     299        ]);
     300
     301        return $payload;
    248302    }
    249303}
  • modular-connector/trunk/src/app/Jobs/ManagerInstallJob.php

    r3386550 r3444723  
    77use Modular\Connector\Services\Manager\ManagerPlugin;
    88use Modular\Connector\Services\Manager\ManagerTheme;
     9use Modular\ConnectorDependencies\Ares\Framework\Foundation\ScreenSimulation;
    910use Modular\ConnectorDependencies\Illuminate\Bus\Queueable;
    1011use Modular\ConnectorDependencies\Illuminate\Contracts\Queue\ShouldQueue;
     
    4748    public function handle(): void
    4849    {
     50        ScreenSimulation::simulateAdmin();
     51
    4952        $payload = $this->payload;
    5053
  • modular-connector/trunk/src/app/Jobs/ManagerManageItemJob.php

    r3386550 r3444723  
    1313use Modular\Connector\Services\Manager\ManagerTheme;
    1414use Modular\ConnectorDependencies\Ares\Framework\Foundation\Http\HttpUtils;
     15use Modular\ConnectorDependencies\Ares\Framework\Foundation\ScreenSimulation;
    1516use Modular\ConnectorDependencies\Illuminate\Bus\Queueable;
    1617use Modular\ConnectorDependencies\Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
     
    7576    public function handle(): void
    7677    {
     78        ScreenSimulation::simulateAdmin();
     79
    7780        $payload = $this->payload;
    7881        $action = $this->action;
  • modular-connector/trunk/src/app/Jobs/ManagerUpdateJob.php

    r3316585 r3444723  
    55use Modular\Connector\Events\ManagerItemsUpdated;
    66use Modular\Connector\Facades\Manager;
     7use Modular\ConnectorDependencies\Ares\Framework\Foundation\ScreenSimulation;
    78use Modular\ConnectorDependencies\Illuminate\Bus\Queueable;
    89use Modular\ConnectorDependencies\Illuminate\Contracts\Queue\ShouldQueue;
     
    3738    public function handle(): void
    3839    {
     40        ScreenSimulation::simulateAdmin();
     41
    3942        $items = Manager::update();
    4043
  • modular-connector/trunk/src/app/Providers/ModularConnectorServiceProvider.php

    r3421301 r3444723  
    77use Modular\Connector\Facades\Manager as ManagerFacade;
    88use Modular\Connector\Facades\WhiteLabel;
     9use Modular\Connector\Helper\OauthClient;
    910use Modular\Connector\Services\Manager;
    1011use Modular\Connector\Services\Manager\ManagerSafeUpgrade;
     
    129130            $url = apply_filters(sprintf('%s_query_url', $hook), site_url('wp-load.php'));
    130131
     132            // Generate random control parameter for this specific request
     133            $lbNonce = bin2hex(random_bytes(16));
     134
    131135            $query = apply_filters(
    132136                sprintf('%s_query_args', $hook),
     
    134138                    'origin' => 'mo',
    135139                    'type' => 'lb',
    136                     'nonce' => wp_create_nonce($hook),
     140                    'lbn' => $lbNonce, // Loopback nonce - must match JWT payload
    137141                ]
    138142            );
     
    144148                'sslverify' => false,
    145149                'blocking' => $debugSchedule,
    146                 'headers' => [],
     150                'headers' => [
     151                    'User-Agent' => 'ModularConnector/' . MODULAR_CONNECTOR_VERSION . ' (Linux)',
     152                ],
    147153            ];
    148154
     155            // Generate JWT with client_secret for x-mo-authentication
    149156            try {
    150                 $token = JWT::generate($hook);
    151                 $args['headers']['Authentication'] = 'Bearer ' . $token;
     157                $client = OauthClient::getClient();
     158                $clientSecret = $client->getClientSecret();
     159                $clientId = $client->getClientId();
     160
     161                if (!empty($clientSecret) && !empty($clientId)) {
     162                    $token = $this->generateLoopbackJwt($clientSecret, $clientId, $lbNonce);
     163
     164                    $args['headers']['x-mo-authentication'] = 'Bearer ' . $token;
     165                } else {
     166                    Log::warning('Loopback: client_secret or client_id not available, skipping dispatch');
     167
     168                    return;
     169                }
    152170            } catch (\Throwable $e) {
    153                 // Silence is golden
    154                 Log::debug($e);
     171                Log::debug('Loopback: Failed to generate JWT', ['error' => $e->getMessage()]);
     172                return;
    155173            }
    156174
     
    192210
    193211    /**
     212     * Generate a JWT for loopback requests using client_secret.
     213     *
     214     * @param string $clientSecret
     215     * @param string $clientId
     216     * @param string $lbNonce Random nonce that must match the query string parameter
     217     * @return string
     218     */
     219    private function generateLoopbackJwt(string $clientSecret, string $clientId, string $lbNonce): string
     220    {
     221        $header = [
     222            'typ' => 'JWT',
     223            'alg' => 'HS256',
     224        ];
     225
     226        $payload = [
     227            'iat' => time(),
     228            'exp' => time() + 300, // 5 minutes expiration
     229            'type' => 'loopback',
     230            'client_id' => $clientId, // Site-specific verification
     231            'lbn' => $lbNonce, // Must match query string lbn parameter
     232        ];
     233
     234        $base64UrlHeader = JWT::base64UrlEncode(
     235            json_encode($header, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR)
     236        );
     237        $base64UrlPayload = JWT::base64UrlEncode(
     238            json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR)
     239        );
     240
     241        $signature = hash_hmac('sha256', "{$base64UrlHeader}.{$base64UrlPayload}", $clientSecret, true);
     242        $base64UrlSignature = JWT::base64UrlEncode($signature);
     243
     244        return "{$base64UrlHeader}.{$base64UrlPayload}.{$base64UrlSignature}";
     245    }
     246
     247    /**
    194248     * @return void
    195249     */
  • modular-connector/trunk/src/app/Providers/RouteServiceProvider.php

    r3441222 r3444723  
    99use Modular\ConnectorDependencies\Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
    1010use Modular\ConnectorDependencies\Illuminate\Support\Facades\Cache;
     11use Modular\ConnectorDependencies\Illuminate\Support\Facades\Log;
    1112use Modular\ConnectorDependencies\Illuminate\Support\Facades\Route;
     13use Modular\ConnectorDependencies\Illuminate\Support\Str;
    1214use Modular\ConnectorDependencies\Symfony\Component\HttpKernel\Exception\HttpException;
    1315use function Modular\ConnectorDependencies\app;
     
    3840
    3941    /**
     42     * Get type from request (header XOR query, never both).
     43     *
     44     * @param \Illuminate\Http\Request $request
     45     * @return string|null
     46     */
     47    private function getTypeFromRequest($request): ?string
     48    {
     49        $hasQuery = $request->has('type');
     50        $hasHeader = $request->hasHeader('x-mo-type');
     51
     52        // XOR: one or the other, never both (already validated in isDirectRequest)
     53        if ($hasQuery) {
     54            return $request->get('type');
     55        }
     56
     57        if ($hasHeader) {
     58            return $request->header('x-mo-type');
     59        }
     60
     61        return null;
     62    }
     63
     64    /**
     65     * Get mrid from request (header XOR query, never both).
     66     *
     67     * @param \Illuminate\Http\Request $request
     68     * @return string|null
     69     */
     70    private function getMridFromRequest($request): ?string
     71    {
     72        $hasQuery = $request->has('mrid');
     73        $hasHeader = $request->hasHeader('x-mo-mrid');
     74
     75        if ($hasQuery) {
     76            return $request->get('mrid');
     77        }
     78
     79        if ($hasHeader) {
     80            return $request->header('x-mo-mrid');
     81        }
     82
     83        return null;
     84    }
     85
     86    /**
    4087     * @param $route
    4188     * @param $removeQuery
     
    56103
    57104        $request = request();
    58         $type = $request->header('x-mo-type', $request->get('type'));
     105        $type = $this->getTypeFromRequest($request);
    59106
    60107        if ($type === 'request') {
    61             $mrid = $request->header('x-mo-mrid', $request->get('mrid'));
     108            $mrid = $this->getMridFromRequest($request);
     109
     110            // Defense in depth: validate mrid is UUID (already validated in isDirectRequest)
     111            if (!$mrid || !Str::isUuid($mrid)) {
     112                Log::warning('bindOldRoutes: Invalid mrid format', ['mrid' => $mrid]);
     113
     114                return $route;
     115            }
     116
    62117            $modularRequest = Cache::driver('array')->get('modularRequest') ?: $this->getModularRequest($mrid);
    63118
     
    72127            }
    73128
    74             $type = $modularRequest->type;
    75 
    76             /**
    77              * @var \Illuminate\Routing\Route $route
    78              */
    79             $routeByName = $routes->getByName($type);
     129            $routeType = $modularRequest->type;
     130
     131            /** @var \Illuminate\Routing\Route $routeByName */
     132            $routeByName = $routes->getByName($routeType);
    80133
    81134            if (!$routeByName) {
     135                Log::warning('bindOldRoutes: Route not found', ['route_type' => $routeType]);
     136
    82137                return $route;
    83138            }
     
    96151                $route->setParameter('modular_request', $modularRequest);
    97152            }
    98         } else if ($type === 'oauth') {
     153        } elseif ($type === 'oauth') {
    99154            /**
    100155             * @var \Illuminate\Routing\Route $route
     
    105160                $request->query->remove('origin');
    106161                $request->query->remove('type');
     162                $request->query->remove('state');
    107163            }
    108164
    109165            $route = $route->bind($request);
    110         } else if ($type === 'lb') {
     166        } elseif ($type === 'lb') {
    111167            /**
    112168             * @var \Illuminate\Routing\Route $route
     
    120176
    121177            $route = $route->bind($request);
    122         }
    123 
    124         if ($request->hasHeader('authorization')) {
    125             $authorization = $request->header('Authorization');
    126 
    127             Cache::driver('wordpress')->forever('header.authorization', $authorization);
    128         } elseif (Cache::driver('wordpress')->has('header.authorization')) {
    129             Cache::driver('wordpress')->forget('header.authorization');
     178        } else {
     179            // Unknown type - should never reach here if isDirectRequest() works correctly
     180            Log::warning('bindOldRoutes: Unknown type after isDirectRequest passed', ['type' => $type]);
     181
     182            return $route;
    130183        }
    131184
  • modular-connector/trunk/src/app/WordPress/Settings.php

    r3421301 r3444723  
    230230
    231231    /**
     232     * Allowed queue connection names for clear operations.
     233     */
     234    private const ALLOWED_QUEUE_CONNECTIONS = ['sync', 'wordpress', 'database'];
     235
     236    /**
     237     * Allowed cache store names for clear operations.
     238     */
     239    private const ALLOWED_CACHE_STORES = ['file', 'database'];
     240
     241    /**
    232242     * The function used to clear the cache
    233243     *
     
    248258            $connection = $request->get('driver');
    249259
     260            // Validate connection is in allowed list
     261            if (!in_array($connection, self::ALLOWED_QUEUE_CONNECTIONS, true)) {
     262                wp_die(esc_html__('Invalid queue connection.', 'modular-connector'));
     263            }
     264
    250265            $queue = app('queue')->connection($connection);
    251266
     
    255270        } elseif ($request->get('action') === 'cache') {
    256271            $driver = $request->get('driver');
     272
     273            // Validate driver is in allowed list
     274            if (!in_array($driver, self::ALLOWED_CACHE_STORES, true)) {
     275                wp_die(esc_html__('Invalid cache driver.', 'modular-connector'));
     276            }
    257277
    258278            app('cache')->driver($driver)->flush();
  • modular-connector/trunk/src/config/app.php

    r3318767 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37return [
  • modular-connector/trunk/src/config/auth.php

    r3214910 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37return [
  • modular-connector/trunk/src/config/backup.php

    r3421301 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37return [
  • modular-connector/trunk/src/config/cache.php

    r3266504 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37return [
  • modular-connector/trunk/src/config/database.php

    r3421301 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37global $wpdb;
  • modular-connector/trunk/src/config/filesystems.php

    r3371802 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37return [
  • modular-connector/trunk/src/config/hashing.php

    r3249268 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
     6
     7/**
     8 * Get or generate a unique JWT signing key for this installation.
     9 *
     10 * SECURITY: This replaces the use of SECURE_AUTH_KEY which can be leaked
     11 * through various vectors (LFI, backups, phpinfo, etc.).
     12 *
     13 * The key is stored in the database and is unique per installation.
     14 *
     15 * @return string
     16 */
     17function modular_get_jwt_secret_key(): string
     18{
     19    $optionName = '_modular_jwt_secret_key';
     20    $key = get_option($optionName);
     21
     22    if (empty($key)) {
     23        // Generate a cryptographically secure random key
     24        if (function_exists('wp_generate_password')) {
     25            $key = wp_generate_password(64, true, true);
     26        } else {
     27            $key = bin2hex(random_bytes(32));
     28        }
     29
     30        // Store it in the database
     31        update_option($optionName, $key, false); // false = don't autoload
     32    }
     33
     34    return $key;
     35}
    236
    337return [
     
    2256    |--------------------------------------------------------------------------
    2357    |
    24     | This is the default key used to sign the generated JWT tokens.
    25     | If not set or specified on the generate function,
    26     | an insecure one will be generated.
     58    | SECURITY: This key is now unique per installation and stored in the
     59    | database. It is NOT derived from SECURE_AUTH_KEY to prevent attacks
     60    | if wp-config.php is leaked.
     61    |
     62    | The key is automatically generated on first use.
    2763    |
    2864    */
    2965
    30     'default_key' => defined('SECURE_AUTH_KEY') ? SECURE_AUTH_KEY : null,
     66    'default_key' => function_exists('get_option') ? modular_get_jwt_secret_key() : null,
    3167
    3268    /*
  • modular-connector/trunk/src/config/logging.php

    r3214910 r3444723  
    11<?php
    22
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    36
    47return [
  • modular-connector/trunk/src/config/queue.php

    r3266504 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37return [
  • modular-connector/trunk/src/config/view.php

    r3218772 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37return [
  • modular-connector/trunk/src/routes/api.php

    r3441222 r3444723  
    11<?php
     2
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26
    37use Modular\Connector\Http\Controllers\AuthController;
     
    1014use Modular\Connector\Http\Controllers\WooCommerceController;
    1115use Modular\Connector\Http\Middleware\AuthenticateLoopback;
     16use Modular\ConnectorDependencies\Ares\Framework\Foundation\Http\HttpUtils;
    1217use Modular\ConnectorDependencies\Illuminate\Support\Facades\Route;
    1318use function Modular\ConnectorDependencies\abort;
     
    110115    });
    111116
    112 Route::get('default/{modular_request}', function () {
    113     abort(404);
     117Route::get('default', function () {
     118    if (!HttpUtils::isCron()) {
     119        abort(404);
     120    }
     121
     122    while (ob_get_level()) {
     123        ob_end_clean();
     124    }
    114125})->name('default');
  • modular-connector/trunk/vendor/ares/framework/src/Foundation/Auth/JWT.php

    r3441222 r3444723  
    4848     * @return string       The Base64Url encoded string.
    4949     */
    50     private static function base64UrlEncode($input)
     50    public static function base64UrlEncode($input)
    5151    {
    5252        return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($input));
  • modular-connector/trunk/vendor/ares/framework/src/Foundation/Bootloader.php

    r3441222 r3444723  
    33namespace Modular\ConnectorDependencies\Ares\Framework\Foundation;
    44
     5use Modular\ConnectorDependencies\Ares\Framework\Foundation\Compatibilities\LoginCompatibilities;
    56use Modular\ConnectorDependencies\Ares\Framework\Foundation\Http\HttpUtils;
    67use Modular\ConnectorDependencies\Ares\Framework\Foundation\Routing\Router;
     
    910use Modular\ConnectorDependencies\Illuminate\Http\Request;
    1011use Modular\ConnectorDependencies\Illuminate\Http\Response;
    11 use Modular\ConnectorDependencies\Illuminate\Support\Collection;
    1212use Modular\ConnectorDependencies\Illuminate\Support\Facades\Facade;
    1313use Modular\ConnectorDependencies\Illuminate\Support\Facades\Log;
    14 use Modular\ConnectorDependencies\Illuminate\Support\Str;
    1514/**
    1615 * Class Bootloader inspired by Roots (Acorn).
     
    4746    }
    4847    /**
    49      * @param Request $request
    50      * @return bool
    51      */
    52     protected function getPath(Request $request)
    53     {
    54         return rtrim($request->getBaseUrl() . $request->getPathInfo(), '/');
    55     }
    56     /**
    57      * @param string $path
    58      * @return bool
    59      */
    60     protected function isWpLoad(string $path)
    61     {
    62         return Str::endsWith($path, 'wp-load.php');
    63     }
    64     /**
    65      * @param Request $request
    66      * @return bool
    67      */
    68     protected function isExcluded(Request $request)
    69     {
    70         $except = Collection::make([admin_url(), wp_login_url(), wp_registration_url()])->map(fn($url) => parse_url($url, \PHP_URL_PATH))->unique()->filter();
    71         $path = $this->getPath($request);
    72         return !$this->isWpLoad($path) && (Str::startsWith($path, $except->all()) || Str::endsWith($path, '.php'));
    73     }
    74     /**
    7548     * Initialize and retrieve the Application instance.
    7649     */
     
    9871            @ini_set('display_errors', \false);
    9972        }
    100         // We're just before the WordPress bootstrap, so we can load the admin files.
    101         ScreenSimulation::getInstance()->boot();
    102     }
    103     /**
    104      * Register the default WordPress route to avoid Not Found errors.
    105      *
    106      * @return void
    107      * @throws \Illuminate\Contracts\Container\BindingResolutionException
    108      */
    109     protected function registerDefaultRoute(): void
    110     {
    111         $this->app->make('router')->any('{any?}', fn() => \Modular\ConnectorDependencies\tap(\Modular\ConnectorDependencies\response(''), function (Response $response) {
    112             foreach (headers_list() as $header) {
    113                 [$header, $value] = explode(': ', $header, 2);
    114                 if (!headers_sent()) {
    115                     header_remove($header);
    116                 }
    117                 $response->header($header, $value, $header !== 'Set-Cookie');
    118             }
    119             if ($this->app->hasDebugModeEnabled()) {
    120                 $response->header('X-Powered-By', $this->app->version());
    121             }
    122             $content = '';
    123             $levels = ob_get_level();
    124             for ($i = 0; $i < $levels; $i++) {
    125                 $content .= ob_get_clean();
    126             }
    127             $response->setContent($content);
    128         }))->where('any', '.*')->name('wordpress');
    12973    }
    13074    /**
     
    15094    protected function registerRequestHandler(IlluminateHttpKernel $kernel, Request $request): void
    15195    {
    152         $path = $this->getPath($request);
    153         $isWpLoad = $this->isWpLoad($path);
     96        $isDirectRequest = HttpUtils::isDirectRequest();
    15497        // Handle the request if the route exists
    155         $hook = $isWpLoad ? 'wp_loaded' : 'parse_request';
     98        $hook = $isDirectRequest ? 'wp_loaded' : 'parse_request';
    15699        add_action($hook, fn() => $this->handleRequest($kernel, $request));
     100    }
     101    /**
     102     * Disable WordPress automatic actions during direct requests.
     103     *
     104     * Prevents WordPress from:
     105     * - Redirecting (we use Laravel Response for redirects)
     106     * - Running auto-updates during our operations
     107     * - Running wp_cron during our requests
     108     */
     109    protected function disableWordPressAutoActions(): void
     110    {
     111        // Prevent WordPress redirects (we use Laravel Response)
     112        add_filter('wp_redirect', '__return_false');
     113        // Disable auto updates during our operations
     114        add_filter('auto_update_core', '__return_false', \PHP_INT_MAX);
     115        add_filter('auto_update_translation', '__return_false', \PHP_INT_MAX);
     116        add_filter('auto_update_theme', '__return_false', \PHP_INT_MAX);
     117        add_filter('auto_update_plugin', '__return_false', \PHP_INT_MAX);
     118        add_filter('automatic_updater_disabled', '__return_true');
     119        // Prevent wp_cron from running during our requests
     120        remove_action('init', 'wp_cron');
    157121    }
    158122    /**
     
    174138     * Boot the Application for HTTP requests.
    175139     *
     140     * Only two entry points are allowed:
     141     * - wp-cron.php with DOING_CRON (cron requests)
     142     * - wp-load.php with valid params (direct requests)
     143     *
    176144     * @param IlluminateHttpKernel $kernel
    177145     * @param Request $request
     
    180148    protected function bootHttp(IlluminateHttpKernel $kernel, Request $request): void
    181149    {
    182         if (!HttpUtils::isCron() && ($this->isExcluded($request) || !HttpUtils::isDirectRequest())) {
     150        $isCron = HttpUtils::isCron();
     151        $isDirectRequest = HttpUtils::isDirectRequest();
     152        // Only process cron (wp-cron.php) or direct request (wp-load.php)
     153        if (!$isCron && !$isDirectRequest) {
    183154            return;
    184155        }
    185         Log::debug('Booting the Application for HTTP requests', ['is_direct_request' => HttpUtils::isDirectRequest(), 'is_cron' => HttpUtils::isCron(), 'uri' => $request->fullUrl()]);
     156        Log::debug('Bootloader: Processing request', ['is_cron' => $isCron, 'is_direct_request' => $isDirectRequest]);
    186157        $this->configRequest();
    187         $this->registerDefaultRoute();
    188         add_action('plugins_loaded', function () use ($kernel, $request) {
     158        // Apply login compatibility fixes early (before plugins_loaded)
     159        // so they can register their own plugins_loaded actions
     160        if ($isDirectRequest) {
     161            $this->disableWordPressAutoActions();
     162            LoginCompatibilities::beforeLogin();
     163        }
     164        add_action('plugins_loaded', function () use ($kernel, $request, $isCron, $isDirectRequest) {
    189165            try {
    190                 // First, we need to search for the route to confirm if it exists and check if the modular request is valid.
    191166                $route = apply_filters('ares/routes/match', \false);
    192                 if (HttpUtils::isDirectRequest()) {
    193                     if ($route->getName() === 'wordpress') {
    194                         // If the route is not found, return false.
     167                if ($isDirectRequest) {
     168                    if ($route->getName() === 'default') {
    195169                        \Modular\ConnectorDependencies\abort(404);
    196170                    }
    197171                    add_action('after_setup_theme', fn() => $this->registerRequestHandler($kernel, $request), 0);
    198                 } elseif (HttpUtils::isCron()) {
     172                } elseif ($isCron) {
    199173                    $this->bootCron($kernel, $request);
    200174                }
  • modular-connector/trunk/vendor/ares/framework/src/Foundation/Compatibilities/Compatibilities.php

    r3343003 r3444723  
    55class Compatibilities
    66{
     7    /**
     8     * Get general compatibility fixes.
     9     *
     10     * Note: Login-specific fixes (WpSimpleFirewall, WPEngine, Wp2Fa,
     11     * ShieldUserManagementICWP, LoginLockdown, AllInOneSecurity, DuoFactor)
     12     * have been moved to LoginCompatibilities and are only applied during login.
     13     *
     14     * @return array
     15     */
    716    public static function getCompatibilityFixes()
    817    {
    9         return [WPForms::class, AllInOneSecurity::class, WpSimpleFirewall::class, DuoFactor::class, ShieldUserManagementICWP::class, SidekickPlugin::class, SpamShield::class, WPO365Login::class, JetPlugins::class, WPEngine::class, LoginLockdown::class, Office365forPostSMTPExtension::class, ConstantContactForms::class, Wp2Fa::class, ShieldSecurity::class, Translatepress::class];
     18        return [WPForms::class, SidekickPlugin::class, SpamShield::class, JetPlugins::class, ShieldSecurity::class, Translatepress::class];
    1019    }
    1120    /**
  • modular-connector/trunk/vendor/ares/framework/src/Foundation/Http/HttpUtils.php

    r3441222 r3444723  
    4444    }
    4545    /**
    46      * @return bool
    47      * @deprecated Use isCron() & isAjax() instead.
    48      */
    49     public static function isAjax(): bool
    50     {
    51         $request = \Modular\ConnectorDependencies\app('request');
    52         return defined('DOING_AJAX') && \DOING_AJAX && Str::startsWith($request->get('action'), 'modular_');
    53     }
    54     /**
     46     * Check if this is a valid cron request.
     47     * Must be from wp-cron.php AND have DOING_CRON defined.
     48     *
    5549     * @return bool
    5650     */
    5751    public static function isCron(): bool
    5852    {
    59         return defined('DOING_CRON') && \DOING_CRON;
     53        if (!defined('DOING_CRON') || !\DOING_CRON) {
     54            return \false;
     55        }
     56        $request = \Modular\ConnectorDependencies\app('request');
     57        $scriptName = $request->server('SCRIPT_NAME', $request->server('PHP_SELF', ''));
     58        return Str::endsWith($scriptName, 'wp-cron.php');
     59    }
     60    /**
     61     * Validate that the request comes from wp-load.php only.
     62     *
     63     * @return bool
     64     */
     65    public static function isValidEntryPoint(): bool
     66    {
     67        $request = \Modular\ConnectorDependencies\app('request');
     68        $scriptName = $request->server('SCRIPT_NAME', $request->server('PHP_SELF', ''));
     69        if (!Str::endsWith($scriptName, 'wp-load.php')) {
     70            \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - invalid entry point', ['script_name' => $scriptName, 'expected' => 'wp-load.php']);
     71            return \false;
     72        }
     73        return \true;
     74    }
     75    /**
     76     * Validate User-Agent header matches expected pattern.
     77     *
     78     * @return bool
     79     */
     80    public static function isValidUserAgent(): bool
     81    {
     82        $request = \Modular\ConnectorDependencies\app('request');
     83        $userAgent = $request->userAgent() ?? '';
     84        if (!Str::is('ModularConnector/* (Linux)', $userAgent)) {
     85            \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - invalid User-Agent', ['user_agent' => $userAgent, 'expected_pattern' => 'ModularConnector/* (Linux)']);
     86            return \false;
     87        }
     88        return \true;
    6089    }
    6190    /**
     
    6594    {
    6695        $request = \Modular\ConnectorDependencies\app('request');
    67         // Validate that the request method is GET
    68         if (!$request->isMethod('GET')) {
    69             return \false;
    70         }
    71         $originQuery = $request->has('origin') && $request->get('origin') === 'mo';
    72         if (!$originQuery) {
    73             return \false;
    74         }
    75         $isFromQuery = $originQuery && $request->has('type');
    76         // When is wp-load.php request
    77         if ($isFromQuery) {
    78             // Validate allowed parameters based on type
    79             $type = $request->get('type');
    80             $origin = $request->get('origin');
    81             $allParams = array_keys($request->query->all());
    82             // Validate that type only contains allowed values
    83             $allowedTypes = ['lb', 'request', 'oauth'];
    84             if (!in_array($type, $allowedTypes, \true)) {
    85                 return \false;
    86             }
    87             // Validate that origin is exactly 'mo'
    88             if ($origin !== 'mo') {
    89                 return \false;
    90             }
    91             switch ($type) {
    92                 case 'request':
    93                     $allowedParams = ['origin', 'type', 'mrid', 'sig'];
    94                     break;
    95                 case 'lb':
    96                     $allowedParams = ['origin', 'type', 'nonce'];
    97                     break;
    98                 case 'oauth':
    99                     $allowedParams = ['origin', 'code', 'type', 'state'];
    100                     break;
    101                 default:
    102                     return \false;
    103             }
    104             // Check if all parameters are allowed
    105             foreach ($allParams as $param) {
    106                 if (!in_array($param, $allowedParams, \true)) {
    107                     return \false;
     96        // Validate entry point is wp-load.php only (prevents wp-cron.php, /wp-json/, etc.)
     97        if (!self::isValidEntryPoint()) {
     98            return \false;
     99        }
     100        // Validate REAL HTTP method is GET (prevents X-HTTP-Method-Override)
     101        if ($request->getRealMethod() !== 'GET') {
     102            \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - invalid HTTP method', ['real_method' => $request->getRealMethod(), 'spoofed_method' => $request->method()]);
     103            return \false;
     104        }
     105        // Must have origin=mo (fast check, most requests will fail here)
     106        if ($request->get('origin') !== 'mo') {
     107            return \false;
     108        }
     109        // Type: must be in query OR header, but not both
     110        $hasTypeQuery = $request->has('type');
     111        $hasTypeHeader = $request->hasHeader('x-mo-type');
     112        if (!$hasTypeQuery && !$hasTypeHeader) {
     113            return \false;
     114        }
     115        if ($hasTypeQuery && $hasTypeHeader) {
     116            \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - type in both query and header');
     117            return \false;
     118        }
     119        $type = $hasTypeQuery ? $request->get('type') : $request->header('x-mo-type');
     120        // Validate that type only contains allowed values
     121        $allowedTypes = ['lb', 'request', 'oauth'];
     122        if (!in_array($type, $allowedTypes, \true)) {
     123            return \false;
     124        }
     125        $allParams = array_keys($request->query->all());
     126        // Validate all query parameters are strings (prevents array ?type[]=x)
     127        foreach ($allParams as $param) {
     128            $value = $request->get($param);
     129            if (!is_string($value)) {
     130                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - parameter is not a string', ['param' => $param, 'type' => gettype($value)]);
     131                return \false;
     132            }
     133        }
     134        $hasAuthHeader = $request->hasHeader('x-mo-authentication');
     135        $hasSigParam = $request->has('sig');
     136        // Mutual exclusivity: cannot have both header and sig
     137        if ($hasAuthHeader && $hasSigParam) {
     138            \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - cannot use both x-mo-authentication and sig');
     139            return \false;
     140        }
     141        // User-Agent validation only when sig is NOT present (internal loopback requests)
     142        if (!$hasSigParam && !self::isValidUserAgent()) {
     143            return \false;
     144        }
     145        if ($type === 'request') {
     146            // type=request: requires either x-mo-authentication header OR sig parameter (not both)
     147            if (!$hasAuthHeader && !$hasSigParam) {
     148                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - authentication required (header or sig)', ['type' => $type]);
     149                return \false;
     150            }
     151        } else if (!$hasAuthHeader) {
     152            \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - x-mo-authentication header required', ['type' => $type]);
     153            return \false;
     154        }
     155        // mrid: can be in query OR header, but not both (only for type=request)
     156        $hasMridQuery = $request->has('mrid');
     157        $hasMridHeader = $request->hasHeader('x-mo-mrid');
     158        if ($hasMridQuery && $hasMridHeader) {
     159            \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - mrid in both query and header');
     160            return \false;
     161        }
     162        // For type=request, mrid is required (in query OR header) and must be UUID
     163        if ($type === 'request') {
     164            if (!$hasMridQuery && !$hasMridHeader) {
     165                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - mrid required for type=request');
     166                return \false;
     167            }
     168            $mrid = $hasMridQuery ? $request->get('mrid') : $request->header('x-mo-mrid');
     169            if (!Str::isUuid($mrid)) {
     170                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - mrid must be a valid UUID', ['mrid' => $mrid]);
     171                return \false;
     172            }
     173        }
     174        // code validation (only for type=oauth)
     175        $hasCodeQuery = \false;
     176        if ($type === 'oauth') {
     177            $hasCodeQuery = $request->has('code');
     178            $hasCodeHeader = $request->hasHeader('x-mo-code');
     179            // code: can be in query OR header, but not both
     180            if ($hasCodeQuery && $hasCodeHeader) {
     181                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - code in both query and header');
     182                return \false;
     183            }
     184            // code is required (in query OR header)
     185            if (!$hasCodeQuery && !$hasCodeHeader) {
     186                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - code required for type=oauth');
     187                return \false;
     188            }
     189        }
     190        // Define allowed query parameters per type (exclude params that come via header)
     191        $baseParams = ['origin'];
     192        if ($hasTypeQuery) {
     193            $baseParams[] = 'type';
     194        }
     195        switch ($type) {
     196            case 'request':
     197                $allowedParams = $baseParams;
     198                if ($hasMridQuery) {
     199                    $allowedParams[] = 'mrid';
    108200                }
    109             }
    110             // Validate that parameters are not empty (except state)
    111             foreach ($allParams as $param) {
    112                 if ($param === 'state') {
    113                     continue;
     201                if ($hasSigParam) {
     202                    $allowedParams[] = 'sig';
    114203                }
    115                 $value = $request->get($param);
    116                 if ($value === null || $value === '') {
    117                     return \false;
     204                break;
     205            case 'lb':
     206                $allowedParams = array_merge($baseParams, ['lbn']);
     207                break;
     208            case 'oauth':
     209                $allowedParams = $baseParams;
     210                if ($hasCodeQuery) {
     211                    $allowedParams[] = 'code';
    118212                }
    119             }
    120             // Validate that sig parameter and x-mo-Authentication header are mutually exclusive
    121             $hasSigParam = $request->has('sig');
    122             $hasAuthHeader = $request->hasHeader('x-mo-authentication');
    123             if ($hasSigParam && $hasAuthHeader) {
    124                 return \false;
    125             }
    126             // Validate required headers for oauth type
    127             if ($type === 'oauth') {
    128                 if (!$request->hasHeader('x-mo-authentication')) {
    129                     return \false;
    130                 }
    131             }
    132             // Validate required header or parameter for lb type
    133             if ($type === 'lb') {
    134                 $hasAuthHeader = $request->hasHeader('Authentication');
    135                 $hasNonceParam = $request->has('nonce');
    136                 if (!$hasAuthHeader && !$hasNonceParam) {
    137                     return \false;
    138                 }
    139             }
    140             return \true;
    141         }
    142         return \false;
     213                $allowedParams[] = 'state';
     214                break;
     215            default:
     216                return \false;
     217        }
     218        // Validate all parameters: must be allowed and not empty (except 'state')
     219        foreach ($allParams as $param) {
     220            if (!in_array($param, $allowedParams, \true)) {
     221                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - unexpected parameter', ['param' => $param, 'allowed' => $allowedParams]);
     222                return \false;
     223            }
     224            // 'state' can be empty
     225            if ($param === 'state') {
     226                continue;
     227            }
     228            $value = $request->get($param);
     229            if ($value === null || $value === '') {
     230                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - empty required parameter', ['param' => $param]);
     231                return \false;
     232            }
     233        }
     234        // Validate lbn format for loopback requests (32 hex chars)
     235        if ($type === 'lb') {
     236            $lbn = $request->get('lbn');
     237            if (!preg_match('/^[a-f0-9]{32}$/i', $lbn)) {
     238                \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Rejected - invalid lbn format', ['lbn' => $lbn, 'expected' => '32 hex characters']);
     239                return \false;
     240            }
     241        }
     242        \Modular\ConnectorDependencies\app('log')->debug('isDirectRequest: Request validated successfully', ['type' => $type]);
     243        return \true;
    143244    }
    144245    /**
     
    174275    {
    175276        Cache::forever('illuminate:queue:restart', $timestamp);
    176         Log::info('Broadcasting queue restart signal.');
     277        \Modular\ConnectorDependencies\app('log')->info('Broadcasting queue restart signal.');
    177278    }
    178279}
  • modular-connector/trunk/vendor/ares/framework/src/Foundation/ScreenSimulation.php

    r3441222 r3444723  
    44
    55use Modular\ConnectorDependencies\Ares\Framework\Foundation\Compatibilities\Compatibilities;
    6 use Modular\ConnectorDependencies\Ares\Framework\Foundation\Http\HttpUtils;
    76use Modular\ConnectorDependencies\Illuminate\Support\Facades\Log;
     7/**
     8 * Simulates WordPress admin environment for plugin/theme management operations.
     9 *
     10 * This class is used by Manager jobs (ManagerInstallJob, ManagerUpdateJob, ManagerManageItemJob)
     11 * to simulate the wp-admin environment needed for WordPress upgrader operations.
     12 *
     13 * Usage:
     14 *   ScreenSimulation::simulateAdmin();  // Call at start of job handle()
     15 *   ScreenSimulation::includeUpgrader(); // Called by Manager services as needed
     16 *
     17 * @see \Modular\Connector\Jobs\ManagerInstallJob
     18 * @see \Modular\Connector\Jobs\ManagerUpdateJob
     19 * @see \Modular\Connector\Jobs\ManagerManageItemJob
     20 */
    821class ScreenSimulation
    922{
    1023    /**
    11      * Indicates if the screen has "booted".
     24     * Indicates if the admin environment has been simulated.
     25     */
     26    private static bool $adminSimulated = \false;
     27    /**
     28     * Simulate WordPress admin environment for plugin/theme management.
    1229     *
    13      * @var bool
     30     * Call this at the start of Manager jobs that need to install, update,
     31     * activate, or delete plugins/themes.
     32     *
     33     * @param string $path The admin page to simulate (default: update-core.php)
    1434     */
    15     protected $booted = \false;
    16     /**
    17      * Indicates if the screen has "loaded".
    18      *
    19      * @var bool
    20      */
    21     protected $loaded = \false;
    22     /**
    23      * The Bootloader instance.
    24      */
    25     protected static $instance;
    26     /**
    27      * @var mixed
    28      */
    29     protected $callResponse;
    30     /**
    31      * @var mixed
    32      */
    33     protected $callBody;
    34     /**
    35      * Get the Bootloader instance.
    36      */
    37     public static function getInstance(): self
     35    public static function simulateAdmin(string $path = 'update-core.php'): void
    3836    {
    39         return static::$instance ??= new static();
    40     }
    41     /**
    42      * Determine if the screen has booted.
    43      *
    44      * @return bool
    45      */
    46     public function isBooted()
    47     {
    48         return $this->booted;
    49     }
    50     /**
    51      * Determine if the screen has booted.
    52      *
    53      * @return bool
    54      */
    55     public function isLoaded()
    56     {
    57         return $this->loaded;
    58     }
    59     /**
    60      * Boot the screen's service providers.
    61      *
    62      * @return void
    63      */
    64     public function boot(string $path = 'update-core.php')
    65     {
    66         if ($this->isBooted()) {
     37        if (self::$adminSimulated) {
    6738            return;
    6839        }
    69         // A lot of sites have issues with the updater, so we need to tell WordPress that we are in the update-core.php file.
     40        self::$adminSimulated = \true;
     41        Log::debug('ScreenSimulation: Simulating admin environment', ['path' => $path]);
     42        // Simulate being in wp-admin
    7043        $_SERVER['PHP_SELF'] = '/wp-admin/' . $path;
    71         $_COOKIE['redirect_count'] = '10';
    7244        if (defined('FORCE_SSL_ADMIN') && \FORCE_SSL_ADMIN) {
    7345            $_SERVER['HTTPS'] = 'on';
     
    7749            $GLOBALS['pagenow'] = $path;
    7850        }
    79         // We use Laravel Response to make our redirections.
    80         add_filter('wp_redirect', '__return_false');
    81         if (HttpUtils::isDirectRequest()) {
    82             if (!defined('DOING_AJAX')) {
    83                 define('DOING_AJAX', \true);
    84             }
    85             // When it's a modular request, we need to avoid the cron execution.
    86             remove_action('init', 'wp_cron');
    87             // Disable auto updates for core, themes, plugins and translations.
    88             add_filter('auto_update_core', '__return_false', \PHP_INT_MAX);
    89             add_filter('auto_update_translation', '__return_false', \PHP_INT_MAX);
    90             add_filter('auto_update_theme', '__return_false', \PHP_INT_MAX);
    91             add_filter('auto_update_plugin', '__return_false', \PHP_INT_MAX);
    92             // Disable Automatic updates.
    93             add_filter('automatic_updater_disabled', '__return_true');
     51        if (!isset($GLOBALS['hook_suffix'])) {
     52            $GLOBALS['hook_suffix'] = '';
    9453        }
     54        // Include WordPress screen classes
    9555        if (!class_exists('WP_Screen')) {
    9656            require_once \ABSPATH . 'wp-admin/includes/class-wp-screen.php';
     
    10262            require_once \ABSPATH . 'wp-admin/includes/template.php';
    10363        }
    104         if (!isset($GLOBALS['hook_suffix'])) {
    105             $GLOBALS['hook_suffix'] = '';
    106         }
    107         $this->forceCompability();
    108         if (HttpUtils::isMuPlugin()) {
    109             $this->loadAdmin();
    110         }
     64        // Apply general compatibility fixes for plugins that interfere with updates
     65        self::applyCompatibilityFixes();
     66        // Logout user when request terminates
    11167        \Modular\ConnectorDependencies\app()->terminating(function () {
    11268            ServerSetup::logout();
    11369        });
    114         $this->booted = \true;
    11570    }
    11671    /**
    11772     * Makes the necessary WordPress upgrader includes
    11873     * to handle plugin and themes functionality.
    119      *
    120      * @return void
    12174     */
    12275    public static function includeUpgrader(): void
     
    14598    }
    14699    /**
    147      * @param $response
    148      * @param $args
    149      * @param $url
    150      * @return mixed
     100     * Apply general compatibility fixes for plugins that interfere with updates.
    151101     */
    152     public function interceptUpdateCall($response, $args, $url)
     102    private static function applyCompatibilityFixes(): void
    153103    {
    154         if ($url !== 'https://api.wordpress.org/plugins/update-check/1.1/') {
    155             return $response;
    156         }
    157         $this->callResponse = $response;
    158         $this->callBody = $args['body'];
    159         return $response;
    160     }
    161     /**
    162      * @param $response
    163      * @param $args
    164      * @param $url
    165      * @return mixed
    166      */
    167     public function interceptUpdateCache($response, $args, $url)
    168     {
    169         if ($url !== 'https://api.wordpress.org/plugins/update-check/1.1/') {
    170             return $response;
    171         }
    172         if ($this->callResponse === null) {
    173             return $response;
    174         }
    175         if ($this->callBody !== http_build_query($args['body'])) {
    176             return $response;
    177         }
    178         return $this->callResponse;
    179     }
    180     /**
    181      * @return void
    182      */
    183     private function loadAdmin()
    184     {
    185         #region Simulate admin mode
    186         /**
    187          * Only we want to simulate the admin if we are in a MU Plugin.
    188          */
    189         if (!defined('WP_ADMIN')) {
    190             define('WP_ADMIN', \true);
    191         }
    192         if (!defined('WP_NETWORK_ADMIN')) {
    193             define('WP_NETWORK_ADMIN', HttpUtils::isMultisite());
    194         }
    195         if (!defined('WP_BLOG_ADMIN')) {
    196             define('WP_BLOG_ADMIN', \true);
    197         }
    198         if (!defined('WP_USER_ADMIN')) {
    199             define('WP_USER_ADMIN', \false);
    200         }
    201         #endregion
    202         add_action('wp_loaded', function () {
    203             // When we're in Direct Request (wp-load.php) or wp-cron.php, we need to load the main admin files.
    204             if (HttpUtils::isDirectRequest() || HttpUtils::isCron()) {
    205                 // Initialize ob_start to avoid any content that has already been sent.
    206                 @ob_start();
    207                 try {
    208                     require_once \ABSPATH . 'wp-admin/includes/admin.php';
    209                     do_action('admin_init');
    210                 } catch (\Throwable $e) {
    211                     // Handle any exceptions that might occur during the loading process.
    212                     Log::error($e, ['message' => 'Error loading admin files in ScreenSimulation']);
    213                 }
    214                 @ob_end_flush();
    215                 if (@ob_get_length() > 0) {
    216                     @ob_end_clean();
    217                 }
    218             }
    219             set_current_screen();
    220         }, \PHP_INT_MAX);
    221     }
    222     /**
    223      * @return void
    224      */
    225     private function forceCompability()
    226     {
    227         add_filter('http_response', [$this, 'interceptUpdateCall'], \PHP_INT_MAX, 3);
    228         add_filter('pre_http_request', [$this, 'interceptUpdateCache'], \PHP_INT_MAX, 3);
    229104        $compatibilityFixes = Compatibilities::getCompatibilityFixes();
    230105        array_walk($compatibilityFixes, fn($compatibility) => $compatibility::fix());
  • modular-connector/trunk/vendor/ares/framework/src/Foundation/ServerSetup.php

    r3290091 r3444723  
    33namespace Modular\ConnectorDependencies\Ares\Framework\Foundation;
    44
     5use Modular\ConnectorDependencies\Ares\Framework\Foundation\Compatibilities\LoginCompatibilities;
    56use Modular\ConnectorDependencies\Ares\Framework\Foundation\Database\Models\User;
    67use Modular\ConnectorDependencies\Illuminate\Support\Collection;
     
    3738     * @param null $user
    3839     * @param bool $withCookies
    39      * @return void
     40     * @return array
    4041     */
    4142    public static function loginAs($user = null, bool $withCookies = \false)
     
    4546        }
    4647        if (!$withCookies && is_user_logged_in()) {
    47             return;
     48            return [];
    4849        }
    4950        if (!$user) {
     
    5152        }
    5253        if (!$user) {
    53             return;
     54            return [];
    5455        }
    55         Log::debug('Login as user', ['user' => $user->ID, 'login' => $user->user_login]);
     56        $id = intval(\Modular\ConnectorDependencies\data_get($user, 'ID'));
     57        Log::debug('Login as user', ['user' => $id, 'login' => $user->user_login]);
    5658        // Authenticated user
    5759        wp_cookie_constants();
    58         $id = intval(\Modular\ConnectorDependencies\data_get($user, 'ID'));
    5960        // Log in with the new user
    6061        wp_set_current_user($id, \Modular\ConnectorDependencies\data_get($user, 'user_login'));
     62        // Apply post-login fixes AFTER user is set
     63        if ($withCookies) {
     64            LoginCompatibilities::afterLogin($id);
     65        }
    6166        if ($withCookies) {
    6267            try {
     
    6671            }
    6772        }
    68         return apply_filters('ares/login/match', [], $id, is_ssl());
     73        return $withCookies ? LoginCompatibilities::getLoginCookies($id, is_ssl()) : [];
    6974    }
    7075    /**
  • modular-connector/trunk/vendor/autoload.php

    r3371802 r3444723  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInit20dc4b5b6916718faedab6064b350e72::getLoader();
     22return ComposerAutoloaderInit117d74cb38cf02066bc2c9688a2868a1::getLoader();
  • modular-connector/trunk/vendor/composer/autoload_classmap.php

    r3441222 r3444723  
    2222    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Cache\\WordPressStore' => $vendorDir . '/ares/framework/src/Foundation/Cache/WordPressStore.php',
    2323    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Cache\\WordPressStoreRepository' => $vendorDir . '/ares/framework/src/Foundation/Cache/WordPressStoreRepository.php',
    24     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\AllInOneSecurity' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/AllInOneSecurity.php',
    2524    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Compatibilities' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/Compatibilities.php',
    26     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\ConstantContactForms' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/ConstantContactForms.php',
    27     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\DuoFactor' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/DuoFactor.php',
    2825    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\JetPlugins' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/JetPlugins.php',
    29     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\LoginLockdown' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/LoginLockdown.php',
    30     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Office365forPostSMTPExtension' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/Office365forPostSMTPExtension.php',
     26    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\LoginCompatibilities' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/LoginCompatibilities.php',
    3127    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\ShieldSecurity' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/ShieldSecurity.php',
    32     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\ShieldUserManagementICWP' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/ShieldUserManagementICWP.php',
    3328    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\SidekickPlugin' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/SidekickPlugin.php',
    3429    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\SpamShield' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/SpamShield.php',
    3530    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Translatepress' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/Translatepress.php',
    36     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WPEngine' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/WPEngine.php',
    3731    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WPForms' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/WPForms.php',
    38     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WPO365Login' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/WPO365Login.php',
    39     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Wp2Fa' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/Wp2Fa.php',
    40     'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WpSimpleFirewall' => $vendorDir . '/ares/framework/src/Foundation/Compatibilities/WpSimpleFirewall.php',
    4132    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Console\\Command' => $vendorDir . '/ares/framework/src/Foundation/Console/Command.php',
    4233    'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Console\\Scheduling\\Event' => $vendorDir . '/ares/framework/src/Foundation/Console/Scheduling/Event.php',
  • modular-connector/trunk/vendor/composer/autoload_files.php

    r3441222 r3444723  
    77
    88return array(
    9     'be0e863a0b7d410051e3679684b89d05' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
    10     'cdccba37285717201be0cda22130b7c1' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
    11     '4da8a5f965edcd26473fcbf2be82d7d7' => $vendorDir . '/symfony/deprecation-contracts/function.php',
    12     '5d7599fb41d4880e3bb858d832901e9a' => $vendorDir . '/illuminate/collections/helpers.php',
    13     '91ee1bbb29b3989967f6f8639a6d635d' => $vendorDir . '/symfony/translation/Resources/functions.php',
    14     'b72b50162266450392ddd5c515a75818' => $vendorDir . '/illuminate/support/helpers.php',
    15     '9f49441cfe0691e56c9c67bd097c4350' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
    16     '2754c0fa2f40527b67501543ab0dae51' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
    17     '67396cf9772d27504ccab5def06d1e52' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
    18     '49299b7cf704dda84b41286413c4d7e4' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
    19     '36a37457274e471b69dac0ebf51b90b3' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
    20     'e121a84a0c75bdd4c6e143812fa796a1' => $vendorDir . '/symfony/string/Resources/functions.php',
    21     'f758949f401dc2a1f6a702b8afe6dfe4' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
    22     '4b27ba2df9dd92700018e46af777f34f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
    23     '5004fdd59b9e9307e6cd434a40d345f8' => $vendorDir . '/illuminate/events/functions.php',
    24     '92149af1b8cbd5859e99da0ff318c72f' => $vendorDir . '/opis/closure/functions.php',
    25     '929e580c79e3d98067c7165de1418f14' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
    26     '2720919b2893441fad9f879d73593754' => $vendorDir . '/ramsey/uuid/src/functions.php',
    27     'c0255d9fc9194fa59c7865314fa4fccd' => $vendorDir . '/ares/framework/src/helpers.php',
    28     'abffc1041942c7350c813eb59081cf24' => $vendorDir . '/ares/framework/illuminate/Foundation/helpers.php',
    29     '7cb02eee968935cda8344cc3dbfa9620' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
     9    '8419c93626fe7598ccbef010564c3a4b' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
     10    '7bf789b8cc0d56c6855b298256ff6115' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
     11    '9e04c4aabe502bb16013b09736a2ddbd' => $vendorDir . '/symfony/deprecation-contracts/function.php',
     12    '0ce5926b030d9c07cbd62c1b14d18006' => $vendorDir . '/illuminate/collections/helpers.php',
     13    '7a3fd1ce6fda5c86e7fdfeb50092a4de' => $vendorDir . '/symfony/translation/Resources/functions.php',
     14    '8bd8682b7413a305bfd18ab0b047b432' => $vendorDir . '/illuminate/support/helpers.php',
     15    '7b9d7df53ffe0b69f28a3b6e0b3529a9' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
     16    '7c3fa93b8961a4fe2cab57c63da2e84c' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
     17    '32b6f9e9af021004a341671cdaea72f5' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
     18    '343adb70f1591f131423a9171703882c' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
     19    '77c294005b48468474622f6437ac536d' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
     20    '76d345642e8cbc8b74f6a855ce27c3dd' => $vendorDir . '/symfony/string/Resources/functions.php',
     21    '2f8283d81eee04908281bbf23212b9a2' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
     22    '1e55f1386e412dbd32526655015b0a42' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
     23    '408f897df7b1881ca8d62de223242437' => $vendorDir . '/illuminate/events/functions.php',
     24    '0dab8d3562207ef34a1f138bec21d376' => $vendorDir . '/opis/closure/functions.php',
     25    '3d85a28d6d55084676a3a89ff2abc2c9' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
     26    '35962e3ca5a7baa6a36e18d1bb6e925a' => $vendorDir . '/ramsey/uuid/src/functions.php',
     27    '66f6c64bea6c96c0f30a5bc81bd5d371' => $vendorDir . '/ares/framework/src/helpers.php',
     28    'dc37a2ed37121e04227fa943fbc992e9' => $vendorDir . '/ares/framework/illuminate/Foundation/helpers.php',
     29    '6533f4592bad35b0c0e9f64c67fd1c53' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
    3030);
  • modular-connector/trunk/vendor/composer/autoload_real.php

    r3371802 r3444723  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit20dc4b5b6916718faedab6064b350e72
     5class ComposerAutoloaderInit117d74cb38cf02066bc2c9688a2868a1
    66{
    77    private static $loader;
     
    2323        }
    2424
    25         spl_autoload_register(array('ComposerAutoloaderInit20dc4b5b6916718faedab6064b350e72', 'loadClassLoader'), true, true);
     25        spl_autoload_register(array('ComposerAutoloaderInit117d74cb38cf02066bc2c9688a2868a1', 'loadClassLoader'), true, true);
    2626        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    27         spl_autoload_unregister(array('ComposerAutoloaderInit20dc4b5b6916718faedab6064b350e72', 'loadClassLoader'));
     27        spl_autoload_unregister(array('ComposerAutoloaderInit117d74cb38cf02066bc2c9688a2868a1', 'loadClassLoader'));
    2828
    2929        require __DIR__ . '/autoload_static.php';
    30         call_user_func(\Composer\Autoload\ComposerStaticInit20dc4b5b6916718faedab6064b350e72::getInitializer($loader));
     30        call_user_func(\Composer\Autoload\ComposerStaticInit117d74cb38cf02066bc2c9688a2868a1::getInitializer($loader));
    3131
    3232        $loader->setClassMapAuthoritative(true);
    3333        $loader->register(true);
    3434
    35         $filesToLoad = \Composer\Autoload\ComposerStaticInit20dc4b5b6916718faedab6064b350e72::$files;
     35        $filesToLoad = \Composer\Autoload\ComposerStaticInit117d74cb38cf02066bc2c9688a2868a1::$files;
    3636        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
    3737            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
  • modular-connector/trunk/vendor/composer/autoload_static.php

    r3441222 r3444723  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit20dc4b5b6916718faedab6064b350e72
     7class ComposerStaticInit117d74cb38cf02066bc2c9688a2868a1
    88{
    99    public static $files = array (
    10         'be0e863a0b7d410051e3679684b89d05' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
    11         'cdccba37285717201be0cda22130b7c1' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
    12         '4da8a5f965edcd26473fcbf2be82d7d7' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
    13         '5d7599fb41d4880e3bb858d832901e9a' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
    14         '91ee1bbb29b3989967f6f8639a6d635d' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
    15         'b72b50162266450392ddd5c515a75818' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
    16         '9f49441cfe0691e56c9c67bd097c4350' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
    17         '2754c0fa2f40527b67501543ab0dae51' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
    18         '67396cf9772d27504ccab5def06d1e52' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
    19         '49299b7cf704dda84b41286413c4d7e4' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
    20         '36a37457274e471b69dac0ebf51b90b3' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
    21         'e121a84a0c75bdd4c6e143812fa796a1' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
    22         'f758949f401dc2a1f6a702b8afe6dfe4' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
    23         '4b27ba2df9dd92700018e46af777f34f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
    24         '5004fdd59b9e9307e6cd434a40d345f8' => __DIR__ . '/..' . '/illuminate/events/functions.php',
    25         '92149af1b8cbd5859e99da0ff318c72f' => __DIR__ . '/..' . '/opis/closure/functions.php',
    26         '929e580c79e3d98067c7165de1418f14' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
    27         '2720919b2893441fad9f879d73593754' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
    28         'c0255d9fc9194fa59c7865314fa4fccd' => __DIR__ . '/..' . '/ares/framework/src/helpers.php',
    29         'abffc1041942c7350c813eb59081cf24' => __DIR__ . '/..' . '/ares/framework/illuminate/Foundation/helpers.php',
    30         '7cb02eee968935cda8344cc3dbfa9620' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
     10        '8419c93626fe7598ccbef010564c3a4b' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
     11        '7bf789b8cc0d56c6855b298256ff6115' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
     12        '9e04c4aabe502bb16013b09736a2ddbd' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
     13        '0ce5926b030d9c07cbd62c1b14d18006' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
     14        '7a3fd1ce6fda5c86e7fdfeb50092a4de' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
     15        '8bd8682b7413a305bfd18ab0b047b432' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
     16        '7b9d7df53ffe0b69f28a3b6e0b3529a9' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
     17        '7c3fa93b8961a4fe2cab57c63da2e84c' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
     18        '32b6f9e9af021004a341671cdaea72f5' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
     19        '343adb70f1591f131423a9171703882c' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
     20        '77c294005b48468474622f6437ac536d' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
     21        '76d345642e8cbc8b74f6a855ce27c3dd' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
     22        '2f8283d81eee04908281bbf23212b9a2' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
     23        '1e55f1386e412dbd32526655015b0a42' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
     24        '408f897df7b1881ca8d62de223242437' => __DIR__ . '/..' . '/illuminate/events/functions.php',
     25        '0dab8d3562207ef34a1f138bec21d376' => __DIR__ . '/..' . '/opis/closure/functions.php',
     26        '3d85a28d6d55084676a3a89ff2abc2c9' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
     27        '35962e3ca5a7baa6a36e18d1bb6e925a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
     28        '66f6c64bea6c96c0f30a5bc81bd5d371' => __DIR__ . '/..' . '/ares/framework/src/helpers.php',
     29        'dc37a2ed37121e04227fa943fbc992e9' => __DIR__ . '/..' . '/ares/framework/illuminate/Foundation/helpers.php',
     30        '6533f4592bad35b0c0e9f64c67fd1c53' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
    3131    );
    3232
     
    422422        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Cache\\WordPressStore' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Cache/WordPressStore.php',
    423423        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Cache\\WordPressStoreRepository' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Cache/WordPressStoreRepository.php',
    424         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\AllInOneSecurity' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/AllInOneSecurity.php',
    425424        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Compatibilities' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/Compatibilities.php',
    426         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\ConstantContactForms' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/ConstantContactForms.php',
    427         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\DuoFactor' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/DuoFactor.php',
    428425        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\JetPlugins' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/JetPlugins.php',
    429         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\LoginLockdown' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/LoginLockdown.php',
    430         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Office365forPostSMTPExtension' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/Office365forPostSMTPExtension.php',
     426        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\LoginCompatibilities' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/LoginCompatibilities.php',
    431427        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\ShieldSecurity' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/ShieldSecurity.php',
    432         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\ShieldUserManagementICWP' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/ShieldUserManagementICWP.php',
    433428        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\SidekickPlugin' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/SidekickPlugin.php',
    434429        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\SpamShield' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/SpamShield.php',
    435430        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Translatepress' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/Translatepress.php',
    436         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WPEngine' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/WPEngine.php',
    437431        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WPForms' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/WPForms.php',
    438         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WPO365Login' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/WPO365Login.php',
    439         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\Wp2Fa' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/Wp2Fa.php',
    440         'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Compatibilities\\WpSimpleFirewall' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Compatibilities/WpSimpleFirewall.php',
    441432        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Console\\Command' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Console/Command.php',
    442433        'Modular\\ConnectorDependencies\\Ares\\Framework\\Foundation\\Console\\Scheduling\\Event' => __DIR__ . '/..' . '/ares/framework/src/Foundation/Console/Scheduling/Event.php',
     
    27882779    {
    27892780        return \Closure::bind(function () use ($loader) {
    2790             $loader->prefixLengthsPsr4 = ComposerStaticInit20dc4b5b6916718faedab6064b350e72::$prefixLengthsPsr4;
    2791             $loader->prefixDirsPsr4 = ComposerStaticInit20dc4b5b6916718faedab6064b350e72::$prefixDirsPsr4;
    2792             $loader->classMap = ComposerStaticInit20dc4b5b6916718faedab6064b350e72::$classMap;
     2781            $loader->prefixLengthsPsr4 = ComposerStaticInit117d74cb38cf02066bc2c9688a2868a1::$prefixLengthsPsr4;
     2782            $loader->prefixDirsPsr4 = ComposerStaticInit117d74cb38cf02066bc2c9688a2868a1::$prefixDirsPsr4;
     2783            $loader->classMap = ComposerStaticInit117d74cb38cf02066bc2c9688a2868a1::$classMap;
    27932784
    27942785        }, null, ClassLoader::class);
  • modular-connector/trunk/vendor/composer/installed.json

    r3441222 r3444723  
    33        {
    44            "name": "ares/framework",
    5             "version": "3.6.17",
    6             "version_normalized": "3.6.17.0",
     5            "version": "dev-master",
     6            "version_normalized": "dev-master",
    77            "source": {
    88                "type": "git",
    99                "url": "[email protected]:modular/connector/ares.git",
    10                 "reference": "a912d44484836fec6ba90420f2bf2efa67084ec6"
    11             },
    12             "dist": {
    13                 "type": "zip",
    14                 "url": "https://gitlab.modulards.com/api/v4/projects/modular%2Fconnector%2Fares/repository/archive.zip?sha=a912d44484836fec6ba90420f2bf2efa67084ec6",
    15                 "reference": "a912d44484836fec6ba90420f2bf2efa67084ec6",
     10                "reference": "3cb619269631ea6f37435da09c317b2bc6ec626d"
     11            },
     12            "dist": {
     13                "type": "zip",
     14                "url": "https://gitlab.modulards.com/api/v4/projects/modular%2Fconnector%2Fares/repository/archive.zip?sha=3cb619269631ea6f37435da09c317b2bc6ec626d",
     15                "reference": "3cb619269631ea6f37435da09c317b2bc6ec626d",
    1616                "shasum": ""
    1717            },
     
    3636                "php": "^7.4|^8.0",
    3737                "symfony/http-kernel": "^5.4",
    38                 "symfony/var-dumper": "^5.1",
    3938                "vlucas/phpdotenv": "^5.2"
    4039            },
    4140            "require-dev": {
    42                 "filp/whoops": "^2.12"
    43             },
    44             "time": "2026-01-16T19:10:38+01:00",
     41                "filp/whoops": "^2.12",
     42                "symfony/var-dumper": "^5.1"
     43            },
     44            "time": "2026-01-21T20:45:12+01:00",
     45            "default-branch": true,
    4546            "type": "library",
    4647            "installation-source": "dist",
     
    6970            ],
    7071            "support": {
    71                 "source": "https://gitlab.modulards.com/modular/connector/ares/-/tree/3.6.17",
     72                "source": "https://gitlab.modulards.com/modular/connector/ares/-/tree/3.7.0",
    7273                "issues": "https://gitlab.modulards.com/modular/connector/ares/-/issues"
    7374            },
  • modular-connector/trunk/vendor/composer/installed.php

    r3441222 r3444723  
    44        'pretty_version' => 'dev-master',
    55        'version' => 'dev-master',
    6         'reference' => 'ff508e7a68350177872cefc7c0cf72cab74fe5a1',
     6        'reference' => '2e631ebf6037a39cc86072b30ded5111b2e67810',
    77        'type' => 'wordpres-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    1212    'versions' => array(
    1313        'ares/framework' => array(
    14             'pretty_version' => '3.6.17',
    15             'version' => '3.6.17.0',
    16             'reference' => 'a912d44484836fec6ba90420f2bf2efa67084ec6',
     14            'pretty_version' => 'dev-master',
     15            'version' => 'dev-master',
     16            'reference' => '3cb619269631ea6f37435da09c317b2bc6ec626d',
    1717            'type' => 'library',
    1818            'install_path' => __DIR__ . '/../ares/framework',
    19             'aliases' => array(),
     19            'aliases' => array(
     20                0 => '9999999-dev',
     21            ),
    2022            'dev_requirement' => false,
    2123        ),
     
    302304            'pretty_version' => 'dev-master',
    303305            'version' => 'dev-master',
    304             'reference' => 'ff508e7a68350177872cefc7c0cf72cab74fe5a1',
     306            'reference' => '2e631ebf6037a39cc86072b30ded5111b2e67810',
    305307            'type' => 'wordpres-plugin',
    306308            'install_path' => __DIR__ . '/../../',
  • modular-connector/trunk/vendor/scoper-autoload.php

    r3441222 r3444723  
    1515    $GLOBALS['__composer_autoload_files'] = \array_merge(
    1616        $existingComposerAutoloadFiles,
    17         \array_fill_keys(['9f49441cfe0691e56c9c67bd097c4350', '9eaa6b0f3f04e58e17ae5ecb754ea313', '36a37457274e471b69dac0ebf51b90b3', 'acbe0d033c55cd0a032b415e08d14f4c', 'f758949f401dc2a1f6a702b8afe6dfe4', 'b48cbeb76a71e226a23fa64ac2b94dc6', '67396cf9772d27504ccab5def06d1e52', '36dfd6ed9dd74e8062aa61f09caf8554', 'cdccba37285717201be0cda22130b7c1', '5928a00fa978807cf85d90ec3f4b0147', '2754c0fa2f40527b67501543ab0dae51', 'be0e863a0b7d410051e3679684b89d05', '4b27ba2df9dd92700018e46af777f34f', 'b178954ba4692b8876c08a4a97e6ce23', '28099935d0ea91a1b5e09408e356eacb', 'c5e5dfa7f2077b89dbc43523332b50aa', '674e404d8857dd99db32bc218bb5643a', '83cc8b953df9a6f7e51f674d84d57730', '9250916e8af80e0d1bb31401fd2e15a7', '99b27172349c9ec3abea78f62e2938bb', 'a875add15ea9a7df1a6c0c26cc9e4590', '1cbb53d50065225a14c2360be2ccbf6f', '54b9ab13bc86d8251a04a939888e357e', 'a89966141ddd51b9b7e868bc3b2f9bb0', '7bdb062931f6e7102434c3ad28423eb6', 'f49032536fdd06afd9df7191c3f21453', '18e965175c6bcd96deba6bc791a44373', '51421aa3e5e8003b70a289762d146a2a', '7edcabe1b67fbb38f4972a722bbbb429', '7b0b5d7b98f96ad751222ae5cc98cfcb', 'd1fb64fd99fc22e28e29a95cc0ea533a'], true)
     17        \array_fill_keys(['7b9d7df53ffe0b69f28a3b6e0b3529a9', '9eaa6b0f3f04e58e17ae5ecb754ea313', '77c294005b48468474622f6437ac536d', 'acbe0d033c55cd0a032b415e08d14f4c', '2f8283d81eee04908281bbf23212b9a2', 'b48cbeb76a71e226a23fa64ac2b94dc6', '32b6f9e9af021004a341671cdaea72f5', '36dfd6ed9dd74e8062aa61f09caf8554', '7bf789b8cc0d56c6855b298256ff6115', '5928a00fa978807cf85d90ec3f4b0147', '7c3fa93b8961a4fe2cab57c63da2e84c', '8419c93626fe7598ccbef010564c3a4b', '1e55f1386e412dbd32526655015b0a42', 'b178954ba4692b8876c08a4a97e6ce23', '28099935d0ea91a1b5e09408e356eacb', 'c5e5dfa7f2077b89dbc43523332b50aa', '674e404d8857dd99db32bc218bb5643a', '83cc8b953df9a6f7e51f674d84d57730', '9250916e8af80e0d1bb31401fd2e15a7', '99b27172349c9ec3abea78f62e2938bb', 'a875add15ea9a7df1a6c0c26cc9e4590', '1cbb53d50065225a14c2360be2ccbf6f', '54b9ab13bc86d8251a04a939888e357e', 'a89966141ddd51b9b7e868bc3b2f9bb0', '7bdb062931f6e7102434c3ad28423eb6', 'f49032536fdd06afd9df7191c3f21453', '18e965175c6bcd96deba6bc791a44373', '51421aa3e5e8003b70a289762d146a2a', '7edcabe1b67fbb38f4972a722bbbb429', '7b0b5d7b98f96ad751222ae5cc98cfcb', 'd1fb64fd99fc22e28e29a95cc0ea533a'], true)
    1818    );
    1919
     
    3939humbug_phpscoper_expose_class('UnhandledMatchError', 'Modular\ConnectorDependencies\UnhandledMatchError');
    4040humbug_phpscoper_expose_class('JsonException', 'Modular\ConnectorDependencies\JsonException');
     41humbug_phpscoper_expose_class('ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth', 'Modular\ConnectorDependencies\ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth');
    4142
    4243// Function aliases. For more information see:
Note: See TracChangeset for help on using the changeset viewer.