WordPress.org

Make WordPress Core

Ticket #8974: 8974.3.diff

File 8974.3.diff, 15.0 KB (added by sivel, 9 years ago)
  • wp-includes/vars.php

     
    7373 */
    7474$is_IIS = (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false) ? true : false;
    7575
     76/**
     77 * Whether the server software is IIS 7.X
     78 * @global bool $is_IIS7
     79 */
     80$is_iis7 = ($is_IIS && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7.') !== false) ? true : false;
     81
     82
    7683?>
     84 No newline at end of file
  • wp-includes/rewrite.php

     
    16951695
    16961696                return $rules;
    16971697        }
     1698       
     1699        /**
     1700         * Retrieve IIS7 URL Rewrite formatted rewrite rules to write to web.config file.
     1701         *
     1702         * Does not actually write to the web.config file, but creates the rules for
     1703         * the process that will.
     1704         *
     1705         * @since 2.8.0
     1706         * @access public
     1707         *
     1708         * @return string
     1709         */
     1710        function iis7_url_rewrite_rules(){
     1711               
     1712                if ( ! $this->using_permalinks()) {
     1713                        return '';
     1714                }
     1715                $rules  = "<rule name=\"wordpress\" patternSyntax=\"Wildcard\">\n";
     1716                $rules .= "     <match url=\"*\" />\n";
     1717                $rules .= "     <conditions>\n";
     1718                $rules .= "             <add input=\"{REQUEST_FILENAME}\" matchType=\"IsFile\" negate=\"true\" />\n";
     1719                $rules .= "             <add input=\"{REQUEST_FILENAME}\" matchType=\"IsDirectory\" negate=\"true\" />\n";
     1720                $rules .= "     </conditions>\n";
     1721                $rules .= "     <action type=\"Rewrite\" url=\"index.php\" />\n";
     1722                $rules .= "</rule>";
     1723                               
     1724                $rules = apply_filters('iis7_url_rewrite_rules', $rules);
     1725               
     1726                return $rules;
     1727        }
    16981728
    16991729        /**
    17001730         * Add a straight rewrite rule.
     
    17901820                $this->wp_rewrite_rules();
    17911821                if ( function_exists('save_mod_rewrite_rules') )
    17921822                        save_mod_rewrite_rules();
     1823                if ( function_exists('iis7_save_url_rewrite_rules') )
     1824                        iis7_save_url_rewrite_rules();
    17931825        }
    17941826
    17951827        /**
  • wp-admin/includes/misc.php

     
    136136}
    137137
    138138/**
     139 * Updates the IIS web.config file with the current rules if it is writable.
     140 * If the permalinks do not require rewrite rules then the rules are deleted from the web.config file.
     141 *
     142 * @since 2.8.0
     143 *
     144 * @return bool True if web.config was updated successfully
     145 */
     146function iis7_save_url_rewrite_rules(){
     147        global $wp_rewrite;
     148       
     149        $home_path = get_home_path();
     150        $web_config_file = $home_path . 'web.config';
     151
     152        // Using win_is_writable() instead of is_writable() because of a bug in Windows PHP     
     153        if ( ( ! file_exists($web_config_file) && win_is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks() ) || win_is_writable($web_config_file) ) {
     154                if ( iis7_supports_permalinks() ) {
     155                        $rule = $wp_rewrite->iis7_url_rewrite_rules();
     156                        if ( ! empty($rule) ) {
     157                                return iis7_add_rewrite_rule($web_config_file, $rule);
     158                        } else {
     159                                return iis7_delete_rewrite_rule($web_config_file);
     160                        }
     161                }
     162        }
     163        return false;
     164}
     165
     166/**
    139167 * {@internal Missing Short Description}}
    140168 *
    141169 * @since unknown
     
    370398                exit;
    371399        }
    372400}
    373 ?>
    374  No newline at end of file
     401
     402/**
     403 * Check if IIS 7 supports pretty permalinks
     404 *
     405 * @since 2.8.0
     406 *
     407 * @return bool
     408 */
     409function iis7_supports_permalinks() {
     410        global $is_iis7;
     411
     412        $supports_permalinks = false;   
     413        if ( $is_iis7 ) {
     414                /* First we check if the DOMDocument class exists. If it does not exist,
     415                 * which is the case for PHP 4.X, then we cannot easily update the xml configuration file,
     416                 * hence we just bail out and tell user that pretty permalinks cannot be used.
     417                 * This is not a big issue because PHP 4.X is going to be depricated and for IIS it
     418                 * is recommended to use PHP 5.X NTS.
     419                 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
     420                 * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
     421                 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
     422                 * via ISAPI then pretty permalinks will not work.
     423                 */
     424                $supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && ( php_sapi_name() == 'cgi-fcgi' );
     425        }
     426               
     427        return apply_filters('iis7_supports_permalinks', $supports_permalinks);
     428}
     429
     430/**
     431 * Check if rewrite rule for WordPress already exists in the IIS 7 configuration file
     432 *
     433 * @since 2.8.0
     434 *
     435 * @return bool
     436 * @param string $filename The file path to the configuration file
     437 */
     438function iis7_rewrite_rule_exists($filename) { 
     439        if ( ! file_exists($filename) )
     440                return false;   
     441        if ( ! class_exists('DOMDocument') )
     442                return false;
     443       
     444        $doc = new DOMDocument();
     445        if ( $doc->load($filename) === false )
     446                return false;
     447        $xpath = new DOMXPath($doc);
     448        $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[@name=\'wordpress\']');
     449        if ( $rules->length == 0 )
     450                return false;
     451        else
     452                return true;   
     453}
     454
     455/**
     456 * Delete WordPress rewrite rule from web.config file if it exists there
     457 *
     458 * @since 2.8.0
     459 *
     460 * @param string $filename Name of the configuration file
     461 * @return bool
     462 */
     463function iis7_delete_rewrite_rule($filename) { 
     464        // If configuration file does not exist then rules also do not exist so there is nothing to delete
     465        if ( ! file_exists($filename) )
     466                return true;
     467       
     468        if ( ! class_exists('DOMDocument') )
     469                return false;
     470       
     471        $doc = new DOMDocument();
     472        $doc->preserveWhiteSpace = false;
     473
     474        if ( $doc -> load($filename) === false )
     475                return false;
     476        $xpath = new DOMXPath($doc);
     477        $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[@name=\'wordpress\']');
     478        if ( $rules->length > 0 ) {
     479                $child = $rules->item(0);
     480                $parent = $child->parentNode;
     481                $parent->removeChild($child);
     482                $doc->formatOutput = true;
     483                saveDomDocument($doc, $filename);
     484        }
     485        return true;
     486}
     487
     488/**
     489 * Add WordPress rewrite rule to the IIS 7 configuration file.
     490 *
     491 * @since 2.8.0
     492 *
     493 * @param string $filename The file path to the configuration file
     494 * @param string $rewrite_rule The XML fragment with URL Rewrite rule
     495 * @return bool
     496 */
     497function iis7_add_rewrite_rule($filename, $rewrite_rule) {     
     498        if ( ! class_exists('DOMDocument') )
     499                return false;
     500       
     501        // If configuration file does not exist then we create one.
     502        if ( ! file_exists($filename) ) {
     503                $fp = fopen( $filename, 'w');
     504                fwrite($fp, '<configuration/>');
     505                fclose($fp);
     506        }
     507       
     508        $doc = new DOMDocument();
     509        $doc->preserveWhiteSpace = false;
     510
     511        if ( $doc->load($filename) === false )
     512                return false;
     513       
     514        $xpath = new DOMXPath($doc);
     515
     516        // First check if the rule already exists as in that case there is no need to re-add it
     517        $wordpress_rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[@name=\'wordpress\']');
     518        if ( $wordpress_rules->length > 0 )
     519                return true;
     520
     521        // Check the XPath to the rewrite rule and create XML nodes if they do not exist
     522        $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite/rules');
     523        if ( $xmlnodes->length > 0 ) {
     524                $rules_node = $xmlnodes->item(0);
     525        } else {
     526                $rules_node = $doc->createElement('rules');
     527               
     528                $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite');
     529                if ( $xmlnodes->length > 0 ) {
     530                        $rewrite_node = $xmlnodes->item(0);
     531                        $rewrite_node->appendChild($rules_node);
     532                } else {
     533                        $rewrite_node = $doc->createElement('rewrite');
     534                        $rewrite_node->appendChild($rules_node);
     535
     536                        $xmlnodes = $xpath->query('/configuration/system.webServer');
     537                        if ( $xmlnodes->length > 0 ) {
     538                                $system_webServer_node = $xmlnodes->item(0);
     539                                $system_webServer_node->appendChild($rewrite_node);
     540                        } else {
     541                                $system_webServer_node = $doc->createElement('system.webServer');
     542                                $system_webServer_node->appendChild($rewrite_node);
     543               
     544                                $xmlnodes = $xpath->query('/configuration');
     545                                if ( $xmlnodes->length > 0 ) {
     546                                        $config_node = $xmlnodes->item(0);
     547                                        $config_node->appendChild($system_webServer_node);
     548                                } else {
     549                                        $config_node = $doc->createElement('configuration');
     550                                        $doc->appendChild($config_node);
     551                                        $config_node->appendChild($system_webServer_node);
     552                                }
     553                        }
     554                }
     555        }
     556       
     557        $rule_fragment = $doc->createDocumentFragment();
     558        $rule_fragment->appendXML($rewrite_rule);
     559        $rules_node->appendChild($rule_fragment);
     560
     561        $doc->formatOutput = true;     
     562        saveDomDocument($doc, $filename);
     563
     564        return true;   
     565}
     566
     567/**
     568 * Saves the XML document into a file
     569 *
     570 * @since 2.8.0
     571 *
     572 * @param DOMDocument $doc
     573 * @param string $filename
     574 */
     575function saveDomDocument($doc, $filename) {
     576        $config = $doc->saveXML();
     577        $config = preg_replace("/([^\r])\n/", "$1\r\n", $config);
     578        $fp = fopen($filename, 'w');
     579        fwrite($fp, $config);
     580        fclose($fp);
     581}
     582
     583/**
     584 * Workaround for Windows bug in is_writable() function
     585 *
     586 * @since 2.8.0
     587 *
     588 * @param object $path
     589 * @return bool
     590 */
     591function win_is_writable($path) {
     592        /* will work in despite of Windows ACLs bug
     593         * NOTE: use a trailing slash for folders!!!
     594         * see http://bugs.php.net/bug.php?id=27609
     595         * see http://bugs.php.net/bug.php?id=30931
     596         */
     597
     598    if ( $path{strlen($path)-1} == '/' ) // recursively return a temporary file path
     599        return win_is_writable($path . uniqid(mt_rand()) . '.tmp');
     600    else if ( is_dir($path) )
     601        return win_is_writable($path . '/' . uniqid(mt_rand()) . '.tmp');
     602    // check tmp file for read/write capabilities
     603    $rm = file_exists($path);
     604    $f = @fopen($path, 'a');
     605    if ($f===false)
     606        return false;
     607    fclose($f);
     608    if ( ! $rm )
     609        unlink($path);
     610    return true;
     611}
     612?>
  • wp-admin/options-permalink.php

     
    7070include('admin-header.php');
    7171
    7272$home_path = get_home_path();
     73$iis7_permalinks = iis7_supports_permalinks();
    7374
    7475if ( isset($_POST['permalink_structure']) || isset($_POST['category_base']) ) {
    7576        check_admin_referer('update-permalink');
     
    100101$category_base = get_option('category_base');
    101102$tag_base = get_option( 'tag_base' );
    102103
    103 if ( (!file_exists($home_path.'.htaccess') && is_writable($home_path)) || is_writable($home_path.'.htaccess') )
    104         $writable = true;
    105 else
    106         $writable = false;
     104if ( $iis7_permalinks ) {
     105        if ( ( ! file_exists($home_path . 'web.config') && win_is_writable($home_path) ) || win_is_writable($home_path . 'web.config') )
     106                $writable = true;
     107        else
     108                $writable = false;
     109} else {
     110        if ( ( ! file_exists($home_path . '.htaccess') && is_writable($home_path) ) || is_writable($home_path . '.htaccess') )
     111                $writable = true;
     112        else
     113                $writable = false;
     114}
    107115
    108 if ($wp_rewrite->using_index_permalinks())
     116if ( $wp_rewrite->using_index_permalinks() )
    109117        $usingpi = true;
    110118else
    111119        $usingpi = false;
     
    115123
    116124<?php if (isset($_POST['submit'])) : ?>
    117125<div id="message" class="updated fade"><p><?php
    118 if ( $permalink_structure && !$usingpi && !$writable )
    119         _e('You should update your .htaccess now.');
    120 else
    121         _e('Permalink structure updated.');
    122 ?></p></div>
     126if ( $iis7_permalinks ) {
     127        if ( $permalink_structure && ! $usingpi && ! $writable )
     128                _e('You should update your web.config now');
     129        else if ( $permalink_structure && ! $usingpi && $writable)
     130                _e('Permalink structure updated. Remove write access on web.config file now!');
     131        else
     132                _e('Permalink structure updated');
     133} else {
     134        if ( $permalink_structure && ! $usingpi && ! $writable )
     135                _e('You should update your .htaccess now.');
     136        else
     137                _e('Permalink structure updated.');
     138}
     139?>
     140</p></div>
    123141<?php endif; ?>
    124142
    125143<div class="wrap">
     
    134152<?php
    135153$prefix = '';
    136154
    137 if ( ! got_mod_rewrite() )
     155if ( ! got_mod_rewrite() && ! $iis7_permalinks )
    138156        $prefix = '/index.php';
    139157
    140158$structures = array(
     
    179197</table>
    180198
    181199<h3><?php _e('Optional'); ?></h3>
    182 <?php if ($is_apache) : ?>
     200<?php if ( $is_apache || $iis7_permalinks ) : ?>
    183201        <p><?php _e('If you like, you may enter custom structures for your category and tag <abbr title="Universal Resource Locator">URL</abbr>s here. For example, using <kbd>topics</kbd> as your category base would make your category links like <code>http://example.org/topics/uncategorized/</code>. If you leave these blank the defaults will be used.') ?></p>
    184202<?php else : ?>
    185203        <p><?php _e('If you like, you may enter custom structures for your category and tag <abbr title="Universal Resource Locator">URL</abbr>s here. For example, using <code>topics</code> as your category base would make your category links like <code>http://example.org/index.php/topics/uncategorized/</code>. If you leave these blank the defaults will be used.') ?></p>
     
    203221        <input type="submit" name="submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" />
    204222</p>
    205223  </form>
    206 <?php if ( $permalink_structure && !$usingpi && !$writable ) : ?>
    207   <p><?php _e('If your <code>.htaccess</code> file were <a href="http://codex.wordpress.org/Changing_File_Permissions">writable</a>, we could do this automatically, but it isn&#8217;t so these are the mod_rewrite rules you should have in your <code>.htaccess</code> file. Click in the field and press <kbd>CTRL + a</kbd> to select all.') ?></p>
     224<?php if ($iis7_permalinks) :
     225        if ( isset($_POST['submit']) && $permalink_structure && ! $usingpi && ! $writable ) : ?>
     226<p><?php _e('If your <code>web.config</code> file were <a href="http://codex.wordpress.org/Changing_File_Permissions">writable</a>, we could do this automatically, but it isn&#8217;t so this is the url rewrite rule you should have in your <code>web.config</code> file. Click in the field and press <kbd>CTRL + a</kbd> to select all. Then insert this rule inside of the <code>/&lt;configuration&gt;/&lt;system.webServer&gt;/&lt;rewrite&gt;/&lt;rules&gt;</code> element in <code>web.config</code> file.') ?></p>
    208227<form action="options-permalink.php" method="post">
    209228<?php wp_nonce_field('update-permalink') ?>
     229        <p><textarea rows="10" class="large-text readonly" name="rules" id="rules" readonly="readonly"><?php echo wp_specialchars($wp_rewrite->iis7_url_rewrite_rules()); ?></textarea></p>
     230</form>
     231<p><?php _e('If you temporarily make your <code>web.config</code> file writable for us to generate rewrite rules automatically, do not forget to revert the permissions after rule has been saved.')  ?></p> 
     232        <?php endif; ?>
     233<?php else :
     234        if ( $permalink_structure && ! $usingpi && ! $writable ) : ?>
     235<p><?php _e('If your <code>.htaccess</code> file were <a href="http://codex.wordpress.org/Changing_File_Permissions">writable</a>, we could do this automatically, but it isn&#8217;t so these are the mod_rewrite rules you should have in your <code>.htaccess</code> file. Click in the field and press <kbd>CTRL + a</kbd> to select all.') ?></p>
     236<form action="options-permalink.php" method="post">
     237<?php wp_nonce_field('update-permalink') ?>
    210238        <p><textarea rows="6" class="large-text readonly" name="rules" id="rules" readonly="readonly"><?php echo wp_specialchars($wp_rewrite->mod_rewrite_rules()); ?></textarea></p>
    211239</form>
     240        <?php endif; ?>
    212241<?php endif; ?>
    213242
    214243</div>