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