@@ -53,7 +53,6 @@ public function get() {
5353 $ wp_config_content = ( isset ( $ wp_config_file ) && file_exists ( $ wp_config_file ) )
5454 ? file_get_contents ( $ wp_config_file )
5555 : '' ;
56-
5756 // Look for the unique filename
5857 if ( strpos ( $ wp_config_content , 'wp-content/freighter.php ' ) === false ) {
5958 // Return as array for Vue compatibility
@@ -81,12 +80,10 @@ public function update_config( $key, $value ) {
8180 global $ wpdb ;
8281 $ this ->configurations [ $ key ] = $ value ;
8382 $ configurations_serialize = serialize ( $ this ->configurations );
84-
8583 $ exists = $ wpdb ->get_var ( $ wpdb ->prepare (
8684 "SELECT option_id from {$ this ->db_prefix_primary }options where option_name = %s " ,
8785 'stacked_configurations '
8886 ) );
89-
9087 if ( ! $ exists ) {
9188 $ wpdb ->query ( $ wpdb ->prepare (
9289 "INSERT INTO {$ this ->db_prefix_primary }options ( option_name, option_value) VALUES ( %s, %s ) " ,
@@ -104,7 +101,6 @@ public function update_config( $key, $value ) {
104101
105102 public function update ( $ configurations ) {
106103 global $ wpdb ;
107-
108104 // 1. Sanitize: Remove 'errors' so we don't save dynamic checks to DB
109105 $ data = (array ) $ configurations ;
110106 if ( isset ( $ data ['errors ' ] ) ) {
@@ -113,12 +109,10 @@ public function update( $configurations ) {
113109
114110 $ this ->configurations = $ data ;
115111 $ configurations_serialize = serialize ( $ this ->configurations );
116-
117112 $ exists = $ wpdb ->get_var ( $ wpdb ->prepare (
118113 "SELECT option_id from {$ this ->db_prefix_primary }options where option_name = %s " ,
119114 'stacked_configurations '
120115 ) );
121-
122116 if ( ! $ exists ) {
123117 $ wpdb ->query ( $ wpdb ->prepare (
124118 "INSERT INTO {$ this ->db_prefix_primary }options ( option_name, option_value) VALUES ( %s, %s ) " ,
@@ -145,14 +139,12 @@ public function domain_mapping() {
145139
146140 public function refresh_configs () {
147141 global $ wpdb ;
148-
149142 // 1. Generate & Write Bootstrap File
150143 $ bootstrap_content = $ this ->get_bootstrap_content ();
151144 $ bootstrap_path = WP_CONTENT_DIR . '/freighter.php ' ;
152145
153146 // Attempt write
154147 $ bootstrap_written = @file_put_contents ( $ bootstrap_path , $ bootstrap_content );
155-
156148 // Fallback check: maybe it already exists and is valid?
157149 if ( ! $ bootstrap_written ) {
158150 if ( file_exists ( $ bootstrap_path ) && md5_file ( $ bootstrap_path ) === md5 ( $ bootstrap_content ) ) {
@@ -168,7 +160,6 @@ public function refresh_configs() {
168160 $ lines_to_add = [
169161 "if ( file_exists( dirname( __FILE__ ) . '/wp-content/freighter.php' ) ) { require_once( dirname( __FILE__ ) . '/wp-content/freighter.php' ); } "
170162 ];
171-
172163 // 3. Update wp-config.php
173164 if ( file_exists ( ABSPATH . "wp-config.php " ) ) {
174165 $ wp_config_file = ABSPATH . "wp-config.php " ;
@@ -181,10 +172,8 @@ public function refresh_configs() {
181172 if ( is_writable ( $ wp_config_file ) ) {
182173 $ wp_config_content = file_get_contents ( $ wp_config_file );
183174 $ working = preg_split ( '/\R/ ' , $ wp_config_content );
184-
185175 // Clean OLD logic and NEW logic
186176 $ working = $ this ->clean_wp_config_lines ( $ working );
187-
188177 // Find insertion point ($table_prefix)
189178 $ table_prefix_line = 0 ;
190179 foreach ( $ working as $ key => $ line ) {
@@ -200,7 +189,6 @@ public function refresh_configs() {
200189 $ lines_to_add ,
201190 array_slice ( $ working , $ table_prefix_line + 1 , count ( $ working ), true )
202191 );
203-
204192 file_put_contents ( $ wp_config_file , implode ( PHP_EOL , $ updated ) );
205193 }
206194 }
@@ -210,7 +198,6 @@ public function refresh_configs() {
210198 */
211199 private function get_bootstrap_content () {
212200 global $ wpdb ;
213-
214201 $ configurations = (object ) $ this ->configurations ;
215202
216203 // Fetch URL cleanly directly from DB
@@ -228,15 +215,13 @@ private function get_bootstrap_content() {
228215
229216 // Logic Blocks based on File Mode
230217 $ mode_logic = "" ;
231-
232218 // --- DEDICATED MODE ---
233219 if ( $ configurations ->files == 'dedicated ' ) {
234220 $ mode_logic = <<<PHP
235221 if ( ! empty( \$stacked_site_id ) ) {
236222 \$table_prefix = "stacked_{ \$stacked_site_id}_";
237223 define( 'WP_CONTENT_URL', "https://" . ( isset( \$stacked_home) ? \$stacked_home : ' $ site_url' ) . "/content/{ \$stacked_site_id}" );
238224 define( 'WP_CONTENT_DIR', ABSPATH . "content/{ \$stacked_site_id}" );
239-
240225 // Define URLs for non-mapped sites (cookie based)
241226 if ( empty( \$stacked_home ) ) {
242227 define( 'WP_HOME', "https:// $ site_url" );
@@ -266,7 +251,6 @@ private function get_bootstrap_content() {
266251 $ mode_logic = <<<PHP
267252 if ( ! empty( \$stacked_site_id ) ) {
268253 \$table_prefix = "stacked_{ \$stacked_site_id}_";
269-
270254 if ( empty( \$stacked_home ) ) {
271255 define( 'WP_HOME', "https:// $ site_url" );
272256 define( 'WP_SITEURL', "https:// $ site_url" );
@@ -291,6 +275,30 @@ private function get_bootstrap_content() {
291275// 2. Identify Stacked Site ID
292276\$stacked_site_id = ( isset( \$_COOKIE[ "stacked_site_id" ] ) ? \$_COOKIE[ "stacked_site_id" ] : "" );
293277
278+ // [GATEKEEPER] Enforce strict access control for cookie-based access
279+ if ( ! empty( \$stacked_site_id ) && isset( \$_COOKIE['stacked_site_id'] ) ) {
280+
281+ // Whitelist login page (so Magic Login can function)
282+ \$is_login = ( isset( \$_SERVER['SCRIPT_NAME'] ) && strpos( \$_SERVER['SCRIPT_NAME'], 'wp-login.php' ) !== false );
283+
284+ // Check for WordPress Auth Cookie (Raw Check)
285+ // We check if *any* cookie starts with 'wordpress_logged_in_' because we can't validate the hash yet.
286+ \$has_auth_cookie = false;
287+ foreach ( \$_COOKIE as \$key => \$value ) {
288+ if ( strpos( \$key, 'wordpress_logged_in_' ) === 0 ) {
289+ \$has_auth_cookie = true;
290+ break;
291+ }
292+ }
293+
294+ // If not logging in, and no auth cookie is present, REVOKE ACCESS immediately.
295+ if ( ! \$is_login && ! \$has_auth_cookie ) {
296+ setcookie( 'stacked_site_id', '', time() - 3600, '/' );
297+ unset( \$_COOKIE['stacked_site_id'] );
298+ \$stacked_site_id = ""; // Revert to Main Site context for this request
299+ }
300+ }
301+
294302// CLI Support
295303if ( defined( 'WP_CLI' ) && WP_CLI ) {
296304 \$env_id = getenv( 'STACKED_SITE_ID' );
@@ -328,7 +336,6 @@ private function get_bootstrap_content() {
328336 */
329337 private function clean_wp_config_lines ( $ lines ) {
330338 $ is_legacy_block = false ;
331-
332339 foreach ( $ lines as $ key => $ line ) {
333340
334341 // 1. Remove the One-Liner (Matches by unique filename)
@@ -346,15 +353,13 @@ private function clean_wp_config_lines( $lines ) {
346353 continue ;
347354 }
348355
349- if ( $ is_legacy_block ||
350- strpos ( $ line , '$stacked_site_id ' ) !== false ||
351- strpos ( $ line , '$stacked_mappings ' ) !== false ) {
356+ if ( $ is_legacy_block || strpos ( $ line , '$stacked_site_id ' ) !== false || strpos ( $ line , '$stacked_mappings ' ) !== false ) {
352357
353- unset( $ lines [ $ key ] );
358+ unset( $ lines [ $ key ] );
354359
355- if ( trim ( $ line ) === '} ' || trim ( $ line ) === '' ) {
360+ if ( trim ( $ line ) === '} ' || trim ( $ line ) === '' ) {
356361 $ is_legacy_block = false ;
357- }
362+ }
358363 }
359364 }
360365 return $ lines ;
0 commit comments