angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

network.php (25131B)


      1 <?php
      2 /**
      3  * WordPress Network Administration API.
      4  *
      5  * @package WordPress
      6  * @subpackage Administration
      7  * @since 4.4.0
      8  */
      9 
     10 /**
     11  * Check for an existing network.
     12  *
     13  * @since 3.0.0
     14  *
     15  * @global wpdb $wpdb WordPress database abstraction object.
     16  *
     17  * @return string|false Base domain if network exists, otherwise false.
     18  */
     19 function network_domain_check() {
     20 	global $wpdb;
     21 
     22 	$sql = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $wpdb->site ) );
     23 	if ( $wpdb->get_var( $sql ) ) {
     24 		return $wpdb->get_var( "SELECT domain FROM $wpdb->site ORDER BY id ASC LIMIT 1" );
     25 	}
     26 	return false;
     27 }
     28 
     29 /**
     30  * Allow subdomain installation
     31  *
     32  * @since 3.0.0
     33  * @return bool Whether subdomain installation is allowed
     34  */
     35 function allow_subdomain_install() {
     36 	$domain = preg_replace( '|https?://([^/]+)|', '$1', get_option( 'home' ) );
     37 	if ( parse_url( get_option( 'home' ), PHP_URL_PATH ) || 'localhost' === $domain || preg_match( '|^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$|', $domain ) ) {
     38 		return false;
     39 	}
     40 
     41 	return true;
     42 }
     43 
     44 /**
     45  * Allow subdirectory installation.
     46  *
     47  * @since 3.0.0
     48  *
     49  * @global wpdb $wpdb WordPress database abstraction object.
     50  *
     51  * @return bool Whether subdirectory installation is allowed
     52  */
     53 function allow_subdirectory_install() {
     54 	global $wpdb;
     55 
     56 	/**
     57 	 * Filters whether to enable the subdirectory installation feature in Multisite.
     58 	 *
     59 	 * @since 3.0.0
     60 	 *
     61 	 * @param bool $allow Whether to enable the subdirectory installation feature in Multisite.
     62 	 *                    Default false.
     63 	 */
     64 	if ( apply_filters( 'allow_subdirectory_install', false ) ) {
     65 		return true;
     66 	}
     67 
     68 	if ( defined( 'ALLOW_SUBDIRECTORY_INSTALL' ) && ALLOW_SUBDIRECTORY_INSTALL ) {
     69 		return true;
     70 	}
     71 
     72 	$post = $wpdb->get_row( "SELECT ID FROM $wpdb->posts WHERE post_date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND post_status = 'publish'" );
     73 	if ( empty( $post ) ) {
     74 		return true;
     75 	}
     76 
     77 	return false;
     78 }
     79 
     80 /**
     81  * Get base domain of network.
     82  *
     83  * @since 3.0.0
     84  * @return string Base domain.
     85  */
     86 function get_clean_basedomain() {
     87 	$existing_domain = network_domain_check();
     88 	if ( $existing_domain ) {
     89 		return $existing_domain;
     90 	}
     91 	$domain = preg_replace( '|https?://|', '', get_option( 'siteurl' ) );
     92 	$slash  = strpos( $domain, '/' );
     93 	if ( $slash ) {
     94 		$domain = substr( $domain, 0, $slash );
     95 	}
     96 	return $domain;
     97 }
     98 
     99 /**
    100  * Prints step 1 for Network installation process.
    101  *
    102  * @todo Realistically, step 1 should be a welcome screen explaining what a Network is and such.
    103  *       Navigating to Tools > Network should not be a sudden "Welcome to a new install process!
    104  *       Fill this out and click here." See also contextual help todo.
    105  *
    106  * @since 3.0.0
    107  *
    108  * @global bool $is_apache
    109  *
    110  * @param false|WP_Error $errors Optional. Error object. Default false.
    111  */
    112 function network_step1( $errors = false ) {
    113 	global $is_apache;
    114 
    115 	if ( defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) {
    116 		echo '<div class="error"><p><strong>' . __( 'Error:' ) . '</strong> ' . sprintf(
    117 			/* translators: %s: DO_NOT_UPGRADE_GLOBAL_TABLES */
    118 			__( 'The constant %s cannot be defined when creating a network.' ),
    119 			'<code>DO_NOT_UPGRADE_GLOBAL_TABLES</code>'
    120 		) . '</p></div>';
    121 		echo '</div>';
    122 		require_once ABSPATH . 'wp-admin/admin-footer.php';
    123 		die();
    124 	}
    125 
    126 	$active_plugins = get_option( 'active_plugins' );
    127 	if ( ! empty( $active_plugins ) ) {
    128 		echo '<div class="notice notice-warning"><p><strong>' . __( 'Warning:' ) . '</strong> ' . sprintf(
    129 			/* translators: %s: URL to Plugins screen. */
    130 			__( 'Please <a href="%s">deactivate your plugins</a> before enabling the Network feature.' ),
    131 			admin_url( 'plugins.php?plugin_status=active' )
    132 		) . '</p></div>';
    133 		echo '<p>' . __( 'Once the network is created, you may reactivate your plugins.' ) . '</p>';
    134 		echo '</div>';
    135 		require_once ABSPATH . 'wp-admin/admin-footer.php';
    136 		die();
    137 	}
    138 
    139 	$hostname  = get_clean_basedomain();
    140 	$has_ports = strstr( $hostname, ':' );
    141 	if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443' ), true ) ) ) {
    142 		echo '<div class="error"><p><strong>' . __( 'Error:' ) . '</strong> ' . __( 'You cannot install a network of sites with your server address.' ) . '</p></div>';
    143 		echo '<p>' . sprintf(
    144 			/* translators: %s: Port number. */
    145 			__( 'You cannot use port numbers such as %s.' ),
    146 			'<code>' . $has_ports . '</code>'
    147 		) . '</p>';
    148 		echo '<a href="' . esc_url( admin_url() ) . '">' . __( 'Go to Dashboard' ) . '</a>';
    149 		echo '</div>';
    150 		require_once ABSPATH . 'wp-admin/admin-footer.php';
    151 		die();
    152 	}
    153 
    154 	echo '<form method="post">';
    155 
    156 	wp_nonce_field( 'install-network-1' );
    157 
    158 	$error_codes = array();
    159 	if ( is_wp_error( $errors ) ) {
    160 		echo '<div class="error"><p><strong>' . __( 'Error: The network could not be created.' ) . '</strong></p>';
    161 		foreach ( $errors->get_error_messages() as $error ) {
    162 			echo "<p>$error</p>";
    163 		}
    164 		echo '</div>';
    165 		$error_codes = $errors->get_error_codes();
    166 	}
    167 
    168 	if ( ! empty( $_POST['sitename'] ) && ! in_array( 'empty_sitename', $error_codes, true ) ) {
    169 		$site_name = $_POST['sitename'];
    170 	} else {
    171 		/* translators: %s: Default network title. */
    172 		$site_name = sprintf( __( '%s Sites' ), get_option( 'blogname' ) );
    173 	}
    174 
    175 	if ( ! empty( $_POST['email'] ) && ! in_array( 'invalid_email', $error_codes, true ) ) {
    176 		$admin_email = $_POST['email'];
    177 	} else {
    178 		$admin_email = get_option( 'admin_email' );
    179 	}
    180 	?>
    181 	<p><?php _e( 'Welcome to the Network installation process!' ); ?></p>
    182 	<p><?php _e( 'Fill in the information below and you&#8217;ll be on your way to creating a network of WordPress sites. We will create configuration files in the next step.' ); ?></p>
    183 	<?php
    184 
    185 	if ( isset( $_POST['subdomain_install'] ) ) {
    186 		$subdomain_install = (bool) $_POST['subdomain_install'];
    187 	} elseif ( apache_mod_loaded( 'mod_rewrite' ) ) { // Assume nothing.
    188 		$subdomain_install = true;
    189 	} elseif ( ! allow_subdirectory_install() ) {
    190 		$subdomain_install = true;
    191 	} else {
    192 		$subdomain_install = false;
    193 		$got_mod_rewrite   = got_mod_rewrite();
    194 		if ( $got_mod_rewrite ) { // Dangerous assumptions.
    195 			echo '<div class="updated inline"><p><strong>' . __( 'Note:' ) . '</strong> ';
    196 			printf(
    197 				/* translators: %s: mod_rewrite */
    198 				__( 'Please make sure the Apache %s module is installed as it will be used at the end of this installation.' ),
    199 				'<code>mod_rewrite</code>'
    200 			);
    201 			echo '</p>';
    202 		} elseif ( $is_apache ) {
    203 			echo '<div class="error inline"><p><strong>' . __( 'Warning:' ) . '</strong> ';
    204 			printf(
    205 				/* translators: %s: mod_rewrite */
    206 				__( 'It looks like the Apache %s module is not installed.' ),
    207 				'<code>mod_rewrite</code>'
    208 			);
    209 			echo '</p>';
    210 		}
    211 
    212 		if ( $got_mod_rewrite || $is_apache ) { // Protect against mod_rewrite mimicry (but ! Apache).
    213 			echo '<p>';
    214 			printf(
    215 				/* translators: 1: mod_rewrite, 2: mod_rewrite documentation URL, 3: Google search for mod_rewrite. */
    216 				__( 'If %1$s is disabled, ask your administrator to enable that module, or look at the <a href="%2$s">Apache documentation</a> or <a href="%3$s">elsewhere</a> for help setting it up.' ),
    217 				'<code>mod_rewrite</code>',
    218 				'https://httpd.apache.org/docs/mod/mod_rewrite.html',
    219 				'https://www.google.com/search?q=apache+mod_rewrite'
    220 			);
    221 			echo '</p></div>';
    222 		}
    223 	}
    224 
    225 	if ( allow_subdomain_install() && allow_subdirectory_install() ) :
    226 		?>
    227 		<h3><?php esc_html_e( 'Addresses of Sites in your Network' ); ?></h3>
    228 		<p><?php _e( 'Please choose whether you would like sites in your WordPress network to use sub-domains or sub-directories.' ); ?>
    229 			<strong><?php _e( 'You cannot change this later.' ); ?></strong></p>
    230 		<p><?php _e( 'You will need a wildcard DNS record if you are going to use the virtual host (sub-domain) functionality.' ); ?></p>
    231 		<?php // @todo Link to an MS readme? ?>
    232 		<table class="form-table" role="presentation">
    233 			<tr>
    234 				<th><label><input type="radio" name="subdomain_install" value="1"<?php checked( $subdomain_install ); ?> /> <?php _e( 'Sub-domains' ); ?></label></th>
    235 				<td>
    236 				<?php
    237 				printf(
    238 					/* translators: 1: Host name. */
    239 					_x( 'like <code>site1.%1$s</code> and <code>site2.%1$s</code>', 'subdomain examples' ),
    240 					$hostname
    241 				);
    242 				?>
    243 				</td>
    244 			</tr>
    245 			<tr>
    246 				<th><label><input type="radio" name="subdomain_install" value="0"<?php checked( ! $subdomain_install ); ?> /> <?php _e( 'Sub-directories' ); ?></label></th>
    247 				<td>
    248 				<?php
    249 				printf(
    250 					/* translators: 1: Host name. */
    251 					_x( 'like <code>%1$s/site1</code> and <code>%1$s/site2</code>', 'subdirectory examples' ),
    252 					$hostname
    253 				);
    254 				?>
    255 				</td>
    256 			</tr>
    257 		</table>
    258 
    259 		<?php
    260 	endif;
    261 
    262 	if ( WP_CONTENT_DIR !== ABSPATH . 'wp-content' && ( allow_subdirectory_install() || ! allow_subdomain_install() ) ) {
    263 		echo '<div class="error inline"><p><strong>' . __( 'Warning:' ) . '</strong> ' . __( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</p></div>';
    264 	}
    265 
    266 	$is_www = ( 0 === strpos( $hostname, 'www.' ) );
    267 	if ( $is_www ) :
    268 		?>
    269 		<h3><?php esc_html_e( 'Server Address' ); ?></h3>
    270 		<p>
    271 		<?php
    272 		printf(
    273 			/* translators: 1: Site URL, 2: Host name, 3: www. */
    274 			__( 'We recommend you change your site domain to %1$s before enabling the network feature. It will still be possible to visit your site using the %3$s prefix with an address like %2$s but any links will not have the %3$s prefix.' ),
    275 			'<code>' . substr( $hostname, 4 ) . '</code>',
    276 			'<code>' . $hostname . '</code>',
    277 			'<code>www</code>'
    278 		);
    279 		?>
    280 		</p>
    281 		<table class="form-table" role="presentation">
    282 			<tr>
    283 			<th scope='row'><?php esc_html_e( 'Server Address' ); ?></th>
    284 			<td>
    285 				<?php
    286 					printf(
    287 						/* translators: %s: Host name. */
    288 						__( 'The internet address of your network will be %s.' ),
    289 						'<code>' . $hostname . '</code>'
    290 					);
    291 				?>
    292 				</td>
    293 			</tr>
    294 		</table>
    295 		<?php endif; ?>
    296 
    297 		<h3><?php esc_html_e( 'Network Details' ); ?></h3>
    298 		<table class="form-table" role="presentation">
    299 		<?php if ( 'localhost' === $hostname ) : ?>
    300 			<tr>
    301 				<th scope="row"><?php esc_html_e( 'Sub-directory Installation' ); ?></th>
    302 				<td>
    303 				<?php
    304 					printf(
    305 						/* translators: 1: localhost, 2: localhost.localdomain */
    306 						__( 'Because you are using %1$s, the sites in your WordPress network must use sub-directories. Consider using %2$s if you wish to use sub-domains.' ),
    307 						'<code>localhost</code>',
    308 						'<code>localhost.localdomain</code>'
    309 					);
    310 					// Uh oh:
    311 				if ( ! allow_subdirectory_install() ) {
    312 					echo ' <strong>' . __( 'Warning:' ) . ' ' . __( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
    313 				}
    314 				?>
    315 				</td>
    316 			</tr>
    317 		<?php elseif ( ! allow_subdomain_install() ) : ?>
    318 			<tr>
    319 				<th scope="row"><?php esc_html_e( 'Sub-directory Installation' ); ?></th>
    320 				<td>
    321 				<?php
    322 					_e( 'Because your installation is in a directory, the sites in your WordPress network must use sub-directories.' );
    323 					// Uh oh:
    324 				if ( ! allow_subdirectory_install() ) {
    325 					echo ' <strong>' . __( 'Warning:' ) . ' ' . __( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
    326 				}
    327 				?>
    328 				</td>
    329 			</tr>
    330 		<?php elseif ( ! allow_subdirectory_install() ) : ?>
    331 			<tr>
    332 				<th scope="row"><?php esc_html_e( 'Sub-domain Installation' ); ?></th>
    333 				<td>
    334 				<?php
    335 				_e( 'Because your installation is not new, the sites in your WordPress network must use sub-domains.' );
    336 					echo ' <strong>' . __( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
    337 				?>
    338 				</td>
    339 			</tr>
    340 		<?php endif; ?>
    341 		<?php if ( ! $is_www ) : ?>
    342 			<tr>
    343 				<th scope='row'><?php esc_html_e( 'Server Address' ); ?></th>
    344 				<td>
    345 					<?php
    346 					printf(
    347 						/* translators: %s: Host name. */
    348 						__( 'The internet address of your network will be %s.' ),
    349 						'<code>' . $hostname . '</code>'
    350 					);
    351 					?>
    352 				</td>
    353 			</tr>
    354 		<?php endif; ?>
    355 			<tr>
    356 				<th scope='row'><label for="sitename"><?php esc_html_e( 'Network Title' ); ?></label></th>
    357 				<td>
    358 					<input name='sitename' id='sitename' type='text' size='45' value='<?php echo esc_attr( $site_name ); ?>' />
    359 					<p class="description">
    360 						<?php _e( 'What would you like to call your network?' ); ?>
    361 					</p>
    362 				</td>
    363 			</tr>
    364 			<tr>
    365 				<th scope='row'><label for="email"><?php esc_html_e( 'Network Admin Email' ); ?></label></th>
    366 				<td>
    367 					<input name='email' id='email' type='text' size='45' value='<?php echo esc_attr( $admin_email ); ?>' />
    368 					<p class="description">
    369 						<?php _e( 'Your email address.' ); ?>
    370 					</p>
    371 				</td>
    372 			</tr>
    373 		</table>
    374 		<?php submit_button( __( 'Install' ), 'primary', 'submit' ); ?>
    375 	</form>
    376 	<?php
    377 }
    378 
    379 /**
    380  * Prints step 2 for Network installation process.
    381  *
    382  * @since 3.0.0
    383  *
    384  * @global wpdb $wpdb     WordPress database abstraction object.
    385  * @global bool $is_nginx Whether the server software is Nginx or something else.
    386  *
    387  * @param false|WP_Error $errors Optional. Error object. Default false.
    388  */
    389 function network_step2( $errors = false ) {
    390 	global $wpdb, $is_nginx;
    391 
    392 	$hostname          = get_clean_basedomain();
    393 	$slashed_home      = trailingslashit( get_option( 'home' ) );
    394 	$base              = parse_url( $slashed_home, PHP_URL_PATH );
    395 	$document_root_fix = str_replace( '\\', '/', realpath( $_SERVER['DOCUMENT_ROOT'] ) );
    396 	$abspath_fix       = str_replace( '\\', '/', ABSPATH );
    397 	$home_path         = 0 === strpos( $abspath_fix, $document_root_fix ) ? $document_root_fix . $base : get_home_path();
    398 	$wp_siteurl_subdir = preg_replace( '#^' . preg_quote( $home_path, '#' ) . '#', '', $abspath_fix );
    399 	$rewrite_base      = ! empty( $wp_siteurl_subdir ) ? ltrim( trailingslashit( $wp_siteurl_subdir ), '/' ) : '';
    400 
    401 	$location_of_wp_config = $abspath_fix;
    402 	if ( ! file_exists( ABSPATH . 'wp-config.php' ) && file_exists( dirname( ABSPATH ) . '/wp-config.php' ) ) {
    403 		$location_of_wp_config = dirname( $abspath_fix );
    404 	}
    405 	$location_of_wp_config = trailingslashit( $location_of_wp_config );
    406 
    407 	// Wildcard DNS message.
    408 	if ( is_wp_error( $errors ) ) {
    409 		echo '<div class="error">' . $errors->get_error_message() . '</div>';
    410 	}
    411 
    412 	if ( $_POST ) {
    413 		if ( allow_subdomain_install() ) {
    414 			$subdomain_install = allow_subdirectory_install() ? ! empty( $_POST['subdomain_install'] ) : true;
    415 		} else {
    416 			$subdomain_install = false;
    417 		}
    418 	} else {
    419 		if ( is_multisite() ) {
    420 			$subdomain_install = is_subdomain_install();
    421 			?>
    422 	<p><?php _e( 'The original configuration steps are shown here for reference.' ); ?></p>
    423 			<?php
    424 		} else {
    425 			$subdomain_install = (bool) $wpdb->get_var( "SELECT meta_value FROM $wpdb->sitemeta WHERE site_id = 1 AND meta_key = 'subdomain_install'" );
    426 			?>
    427 	<div class="error"><p><strong><?php _e( 'Warning:' ); ?></strong> <?php _e( 'An existing WordPress network was detected.' ); ?></p></div>
    428 	<p><?php _e( 'Please complete the configuration steps. To create a new network, you will need to empty or remove the network database tables.' ); ?></p>
    429 			<?php
    430 		}
    431 	}
    432 
    433 	$subdir_match          = $subdomain_install ? '' : '([_0-9a-zA-Z-]+/)?';
    434 	$subdir_replacement_01 = $subdomain_install ? '' : '$1';
    435 	$subdir_replacement_12 = $subdomain_install ? '$1' : '$2';
    436 
    437 	if ( $_POST || ! is_multisite() ) {
    438 		?>
    439 		<h3><?php esc_html_e( 'Enabling the Network' ); ?></h3>
    440 		<p><?php _e( 'Complete the following steps to enable the features for creating a network of sites.' ); ?></p>
    441 		<div class="notice notice-warning inline"><p>
    442 		<?php
    443 		if ( file_exists( $home_path . '.htaccess' ) ) {
    444 			echo '<strong>' . __( 'Caution:' ) . '</strong> ';
    445 			printf(
    446 				/* translators: 1: wp-config.php, 2: .htaccess */
    447 				__( 'We recommend you back up your existing %1$s and %2$s files.' ),
    448 				'<code>wp-config.php</code>',
    449 				'<code>.htaccess</code>'
    450 			);
    451 		} elseif ( file_exists( $home_path . 'web.config' ) ) {
    452 			echo '<strong>' . __( 'Caution:' ) . '</strong> ';
    453 			printf(
    454 				/* translators: 1: wp-config.php, 2: web.config */
    455 				__( 'We recommend you back up your existing %1$s and %2$s files.' ),
    456 				'<code>wp-config.php</code>',
    457 				'<code>web.config</code>'
    458 			);
    459 		} else {
    460 			echo '<strong>' . __( 'Caution:' ) . '</strong> ';
    461 			printf(
    462 				/* translators: %s: wp-config.php */
    463 				__( 'We recommend you back up your existing %s file.' ),
    464 				'<code>wp-config.php</code>'
    465 			);
    466 		}
    467 		?>
    468 		</p></div>
    469 		<?php
    470 	}
    471 	?>
    472 	<ol>
    473 		<li><p>
    474 		<?php
    475 		printf(
    476 			/* translators: 1: wp-config.php, 2: Location of wp-config file, 3: Translated version of "That's all, stop editing! Happy publishing." */
    477 			__( 'Add the following to your %1$s file in %2$s <strong>above</strong> the line reading %3$s:' ),
    478 			'<code>wp-config.php</code>',
    479 			'<code>' . $location_of_wp_config . '</code>',
    480 			/*
    481 			 * translators: This string should only be translated if wp-config-sample.php is localized.
    482 			 * You can check the localized release package or
    483 			 * https://i18n.svn.wordpress.org/<locale code>/branches/<wp version>/dist/wp-config-sample.php
    484 			 */
    485 			'<code>/* ' . __( 'That&#8217;s all, stop editing! Happy publishing.' ) . ' */</code>'
    486 		);
    487 		?>
    488 		</p>
    489 		<textarea class="code" readonly="readonly" cols="100" rows="7">
    490 define( 'MULTISITE', true );
    491 define( 'SUBDOMAIN_INSTALL', <?php echo $subdomain_install ? 'true' : 'false'; ?> );
    492 define( 'DOMAIN_CURRENT_SITE', '<?php echo $hostname; ?>' );
    493 define( 'PATH_CURRENT_SITE', '<?php echo $base; ?>' );
    494 define( 'SITE_ID_CURRENT_SITE', 1 );
    495 define( 'BLOG_ID_CURRENT_SITE', 1 );
    496 </textarea>
    497 		<?php
    498 		$keys_salts = array(
    499 			'AUTH_KEY'         => '',
    500 			'SECURE_AUTH_KEY'  => '',
    501 			'LOGGED_IN_KEY'    => '',
    502 			'NONCE_KEY'        => '',
    503 			'AUTH_SALT'        => '',
    504 			'SECURE_AUTH_SALT' => '',
    505 			'LOGGED_IN_SALT'   => '',
    506 			'NONCE_SALT'       => '',
    507 		);
    508 		foreach ( $keys_salts as $c => $v ) {
    509 			if ( defined( $c ) ) {
    510 				unset( $keys_salts[ $c ] );
    511 			}
    512 		}
    513 
    514 		if ( ! empty( $keys_salts ) ) {
    515 			$keys_salts_str = '';
    516 			$from_api       = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
    517 			if ( is_wp_error( $from_api ) ) {
    518 				foreach ( $keys_salts as $c => $v ) {
    519 					$keys_salts_str .= "\ndefine( '$c', '" . wp_generate_password( 64, true, true ) . "' );";
    520 				}
    521 			} else {
    522 				$from_api = explode( "\n", wp_remote_retrieve_body( $from_api ) );
    523 				foreach ( $keys_salts as $c => $v ) {
    524 					$keys_salts_str .= "\ndefine( '$c', '" . substr( array_shift( $from_api ), 28, 64 ) . "' );";
    525 				}
    526 			}
    527 			$num_keys_salts = count( $keys_salts );
    528 			?>
    529 		<p>
    530 			<?php
    531 			if ( 1 === $num_keys_salts ) {
    532 				printf(
    533 					/* translators: %s: wp-config.php */
    534 					__( 'This unique authentication key is also missing from your %s file.' ),
    535 					'<code>wp-config.php</code>'
    536 				);
    537 			} else {
    538 				printf(
    539 					/* translators: %s: wp-config.php */
    540 					__( 'These unique authentication keys are also missing from your %s file.' ),
    541 					'<code>wp-config.php</code>'
    542 				);
    543 			}
    544 			?>
    545 			<?php _e( 'To make your installation more secure, you should also add:' ); ?>
    546 		</p>
    547 		<textarea class="code" readonly="readonly" cols="100" rows="<?php echo $num_keys_salts; ?>"><?php echo esc_textarea( $keys_salts_str ); ?></textarea>
    548 			<?php
    549 		}
    550 		?>
    551 		</li>
    552 	<?php
    553 	if ( iis7_supports_permalinks() ) :
    554 		// IIS doesn't support RewriteBase, all your RewriteBase are belong to us.
    555 		$iis_subdir_match       = ltrim( $base, '/' ) . $subdir_match;
    556 		$iis_rewrite_base       = ltrim( $base, '/' ) . $rewrite_base;
    557 		$iis_subdir_replacement = $subdomain_install ? '' : '{R:1}';
    558 
    559 		$web_config_file = '<?xml version="1.0" encoding="UTF-8"?>
    560 <configuration>
    561     <system.webServer>
    562         <rewrite>
    563             <rules>
    564                 <rule name="WordPress Rule 1" stopProcessing="true">
    565                     <match url="^index\.php$" ignoreCase="false" />
    566                     <action type="None" />
    567                 </rule>';
    568 		if ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) {
    569 			$web_config_file .= '
    570                 <rule name="WordPress Rule for Files" stopProcessing="true">
    571                     <match url="^' . $iis_subdir_match . 'files/(.+)" ignoreCase="false" />
    572                     <action type="Rewrite" url="' . $iis_rewrite_base . WPINC . '/ms-files.php?file={R:1}" appendQueryString="false" />
    573                 </rule>';
    574 		}
    575 			$web_config_file .= '
    576                 <rule name="WordPress Rule 2" stopProcessing="true">
    577                     <match url="^' . $iis_subdir_match . 'wp-admin$" ignoreCase="false" />
    578                     <action type="Redirect" url="' . $iis_subdir_replacement . 'wp-admin/" redirectType="Permanent" />
    579                 </rule>
    580                 <rule name="WordPress Rule 3" stopProcessing="true">
    581                     <match url="^" ignoreCase="false" />
    582                     <conditions logicalGrouping="MatchAny">
    583                         <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" />
    584                         <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" />
    585                     </conditions>
    586                     <action type="None" />
    587                 </rule>
    588                 <rule name="WordPress Rule 4" stopProcessing="true">
    589                     <match url="^' . $iis_subdir_match . '(wp-(content|admin|includes).*)" ignoreCase="false" />
    590                     <action type="Rewrite" url="' . $iis_rewrite_base . '{R:1}" />
    591                 </rule>
    592                 <rule name="WordPress Rule 5" stopProcessing="true">
    593                     <match url="^' . $iis_subdir_match . '([_0-9a-zA-Z-]+/)?(.*\.php)$" ignoreCase="false" />
    594                     <action type="Rewrite" url="' . $iis_rewrite_base . '{R:2}" />
    595                 </rule>
    596                 <rule name="WordPress Rule 6" stopProcessing="true">
    597                     <match url="." ignoreCase="false" />
    598                     <action type="Rewrite" url="index.php" />
    599                 </rule>
    600             </rules>
    601         </rewrite>
    602     </system.webServer>
    603 </configuration>
    604 ';
    605 
    606 			echo '<li><p>';
    607 			printf(
    608 				/* translators: 1: File name (.htaccess or web.config), 2: File path. */
    609 				__( 'Add the following to your %1$s file in %2$s, <strong>replacing</strong> other WordPress rules:' ),
    610 				'<code>web.config</code>',
    611 				'<code>' . $home_path . '</code>'
    612 			);
    613 		echo '</p>';
    614 		if ( ! $subdomain_install && WP_CONTENT_DIR !== ABSPATH . 'wp-content' ) {
    615 			echo '<p><strong>' . __( 'Warning:' ) . ' ' . __( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</strong></p>';
    616 		}
    617 		?>
    618 		<textarea class="code" readonly="readonly" cols="100" rows="20"><?php echo esc_textarea( $web_config_file ); ?></textarea>
    619 		</li>
    620 	</ol>
    621 
    622 		<?php
    623 	elseif ( $is_nginx ) : // End iis7_supports_permalinks(). Link to Nginx documentation instead:
    624 
    625 		echo '<li><p>';
    626 		printf(
    627 			/* translators: %s: Documentation URL. */
    628 			__( 'It seems your network is running with Nginx web server. <a href="%s">Learn more about further configuration</a>.' ),
    629 			__( 'https://wordpress.org/support/article/nginx/' )
    630 		);
    631 		echo '</p></li>';
    632 
    633 	else : // End $is_nginx. Construct an .htaccess file instead:
    634 
    635 		$ms_files_rewriting = '';
    636 		if ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) {
    637 			$ms_files_rewriting  = "\n# uploaded files\nRewriteRule ^";
    638 			$ms_files_rewriting .= $subdir_match . "files/(.+) {$rewrite_base}" . WPINC . "/ms-files.php?file={$subdir_replacement_12} [L]" . "\n";
    639 		}
    640 
    641 		$htaccess_file = <<<EOF
    642 RewriteEngine On
    643 RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    644 RewriteBase {$base}
    645 RewriteRule ^index\.php$ - [L]
    646 {$ms_files_rewriting}
    647 # add a trailing slash to /wp-admin
    648 RewriteRule ^{$subdir_match}wp-admin$ {$subdir_replacement_01}wp-admin/ [R=301,L]
    649 
    650 RewriteCond %{REQUEST_FILENAME} -f [OR]
    651 RewriteCond %{REQUEST_FILENAME} -d
    652 RewriteRule ^ - [L]
    653 RewriteRule ^{$subdir_match}(wp-(content|admin|includes).*) {$rewrite_base}{$subdir_replacement_12} [L]
    654 RewriteRule ^{$subdir_match}(.*\.php)$ {$rewrite_base}$subdir_replacement_12 [L]
    655 RewriteRule . index.php [L]
    656 
    657 EOF;
    658 
    659 		echo '<li><p>';
    660 		printf(
    661 			/* translators: 1: File name (.htaccess or web.config), 2: File path. */
    662 			__( 'Add the following to your %1$s file in %2$s, <strong>replacing</strong> other WordPress rules:' ),
    663 			'<code>.htaccess</code>',
    664 			'<code>' . $home_path . '</code>'
    665 		);
    666 		echo '</p>';
    667 		if ( ! $subdomain_install && WP_CONTENT_DIR !== ABSPATH . 'wp-content' ) {
    668 			echo '<p><strong>' . __( 'Warning:' ) . ' ' . __( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</strong></p>';
    669 		}
    670 		?>
    671 		<textarea class="code" readonly="readonly" cols="100" rows="<?php echo substr_count( $htaccess_file, "\n" ) + 1; ?>"><?php echo esc_textarea( $htaccess_file ); ?></textarea>
    672 		</li>
    673 	</ol>
    674 
    675 		<?php
    676 	endif; // End IIS/Nginx/Apache code branches.
    677 
    678 	if ( ! is_multisite() ) {
    679 		?>
    680 		<p><?php _e( 'Once you complete these steps, your network is enabled and configured. You will have to log in again.' ); ?> <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log In' ); ?></a></p>
    681 		<?php
    682 	}
    683 }