Make WordPress Core

Ticket #8974: 8974.2.diff

File 8974.2.diff, 14.8 KB (added by Denis-de-Bernardy, 16 years ago)

against 11256

  • 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         * @access public
     1706         *
     1707         * @return string
     1708         */
     1709        function iis7_url_rewrite_rules(){
     1710               
     1711                if ( ! $this->using_permalinks()) {
     1712                        return '';
     1713                }
     1714                $rules =  "<rule name=\"wordpress\" patternSyntax=\"Wildcard\">\n";
     1715                $rules .= "     <match url=\"*\" />\n";
     1716                $rules .= "     <conditions>\n";
     1717                $rules .= "             <add input=\"{REQUEST_FILENAME}\" matchType=\"IsFile\" negate=\"true\" />\n";
     1718                $rules .= "             <add input=\"{REQUEST_FILENAME}\" matchType=\"IsDirectory\" negate=\"true\" />\n";
     1719                $rules .= "     </conditions>\n";
     1720                $rules .= "     <action type=\"Rewrite\" url=\"index.php\" />\n";
     1721                $rules .= "</rule>";
     1722                               
     1723                $rules = apply_filters('iis7_url_rewrite_rules', $rules);
     1724               
     1725                return $rules;
     1726        }
    16981727
    16991728        /**
    17001729         * Add a straight rewrite rule.
     
    17901819                $this->wp_rewrite_rules();
    17911820                if ( function_exists('save_mod_rewrite_rules') )
    17921821                        save_mod_rewrite_rules();
     1822                if ( function_exists('iis7_save_url_rewrite_rules'))
     1823                        iis7_save_url_rewrite_rules();
    17931824        }
    17941825
    17951826        /**
  • 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 *
     143 * @return bool True if web.config was updated successfully
     144 */
     145function iis7_save_url_rewrite_rules(){
     146        global $wp_rewrite;
     147       
     148        $home_path = get_home_path();
     149        $web_config_file = $home_path.'web.config';
     150
     151        // Using win_is_writable() instead of is_writable() because of a bug in Windows PHP     
     152        if ((!file_exists($web_config_file) && win_is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks()) || win_is_writable($web_config_file)) {
     153                if ( iis7_supports_permalinks() ) {
     154                        $rule = $wp_rewrite -> iis7_url_rewrite_rules();
     155                        if ( !empty($rule) ) //
     156                                return iis7_add_rewrite_rule($web_config_file, $rule);
     157                        else{
     158                                return iis7_delete_rewrite_rule($web_config_file);
     159                        }
     160                }
     161        }
     162        return false;
     163}
     164
     165/**
    139166 * {@internal Missing Short Description}}
    140167 *
    141168 * @since unknown
     
    370397                exit;
    371398        }
    372399}
    373 ?>
    374  No newline at end of file
     400
     401// IIS 7 specific functions
     402/**
     403 * Check if IIS 7 supports pretty permalinks
     404 *
     405 *
     406 * @return bool
     407 */
     408function iis7_supports_permalinks(){
     409        global $is_iis7;
     410
     411        $supports_permalinks = false;   
     412        if ($is_iis7){
     413                // First we check if the DOMDocument class exists. If it does not exist,
     414                // which is the case for PHP 4.X, then we cannot easily update the xml configuration file,
     415                // hence we just bail out and tell user that pretty permalinks cannot be used.
     416                // This is not a big issue because PHP 4.X is going to be depricated and for IIS it
     417                // is recommended to use PHP 5.X NTS.
     418                // Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
     419                // URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
     420                // Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
     421                // via ISAPI then pretty permalinks will not work.
     422                $supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && (php_sapi_name() == 'cgi-fcgi');
     423        }
     424               
     425        return apply_filters('iis7_supports_permalinks', $supports_permalinks);
     426}
     427
     428/**
     429 * Check if rewrite rule for WordPress already exists in the IIS 7 configuration file
     430 *
     431 *
     432 * @return bool
     433 * @param string $filename The file path to the configuration file
     434 */
     435function iis7_rewrite_rule_exists($filename)
     436{       
     437        if (!file_exists($filename)) return false;     
     438        if (!class_exists('DOMDocument')) return false;
     439       
     440        $doc = new DOMDocument();
     441        if ($doc -> load($filename) === false) return false;
     442        $xpath = new DOMXPath($doc);
     443        $rules = $xpath -> query('/configuration/system.webServer/rewrite/rules/rule[@name=\'wordpress\']');
     444        if ($rules -> length == 0)
     445                return false;
     446        else
     447                return true;   
     448}
     449
     450/**
     451 * Delete WordPress rewrite rule from web.config file if it exists there
     452 * @return
     453 * @param string $filename Name of the configuration file
     454 */
     455function iis7_delete_rewrite_rule($filename)
     456{       
     457        // If configuration file does not exist then rules also do not exist so there is nothing to delete
     458        if (!file_exists($filename)) return true;
     459       
     460        if (!class_exists('DOMDocument')) return false;
     461       
     462        $doc = new DOMDocument();
     463        $doc -> preserveWhiteSpace = false;
     464
     465        if ($doc -> load($filename) === false) return false;
     466        $xpath = new DOMXPath($doc);
     467        $rules = $xpath -> query('/configuration/system.webServer/rewrite/rules/rule[@name=\'wordpress\']');
     468        if ($rules -> length > 0) {
     469                $child = $rules -> item(0);
     470                $parent = $child -> parentNode;
     471                $parent -> removeChild($child);
     472                $doc -> formatOutput = true;
     473                saveDomDocument($doc, $filename);
     474        }
     475        return true;
     476}
     477
     478/**
     479 * Add WordPress rewrite rule to the IIS 7 configuration file.
     480 *
     481 *
     482 * @return bool
     483 * @param string $filename The file path to the configuration file
     484 * @param string $rewrite_rule The XML fragment with URL Rewrite rule
     485 */
     486function iis7_add_rewrite_rule($filename, $rewrite_rule)
     487{       
     488        if (!class_exists('DOMDocument')) return false;
     489       
     490        // If configuration file does not exist then we create one.
     491        if (!file_exists($filename)) {
     492                $fp = fopen( $filename, 'w');
     493                fwrite($fp, '<configuration/>');
     494                fclose($fp);
     495        }
     496       
     497        $doc = new DOMDocument();
     498        $doc -> preserveWhiteSpace = false;
     499
     500        if ($doc -> load($filename) === false) return false;
     501       
     502        $xpath = new DOMXPath($doc);
     503
     504        // First check if the rule already exists as in that case there is no need to re-add it
     505        $wordpress_rules = $xpath -> query('/configuration/system.webServer/rewrite/rules/rule[@name=\'wordpress\']');
     506        if ($wordpress_rules -> length > 0) return true;
     507
     508        // Check the XPath to the rewrite rule and create XML nodes if they do not exist
     509        $xmlnodes = $xpath -> query('/configuration/system.webServer/rewrite/rules');
     510        if ($xmlnodes -> length > 0){
     511                $rules_node = $xmlnodes -> item(0);
     512        }
     513        else{
     514                $rules_node = $doc -> createElement('rules');
     515               
     516                $xmlnodes = $xpath -> query('/configuration/system.webServer/rewrite');
     517                if ($xmlnodes -> length > 0){
     518                        $rewrite_node = $xmlnodes -> item(0);
     519                        $rewrite_node -> appendChild($rules_node);
     520                }
     521                else{
     522                        $rewrite_node = $doc -> createElement('rewrite');
     523                        $rewrite_node -> appendChild($rules_node);
     524
     525                        $xmlnodes = $xpath -> query('/configuration/system.webServer');
     526                        if ($xmlnodes -> length > 0){
     527                                $system_webServer_node = $xmlnodes -> item(0);
     528                                $system_webServer_node -> appendChild($rewrite_node);
     529                        }
     530                        else{
     531                                $system_webServer_node = $doc -> createElement('system.webServer');
     532                                $system_webServer_node -> appendChild($rewrite_node);
     533               
     534                                $xmlnodes = $xpath -> query('/configuration');
     535                                if ($xmlnodes -> length > 0){
     536                                        $config_node = $xmlnodes -> item(0);
     537                                        $config_node -> appendChild($system_webServer_node);
     538                                }
     539                                else{
     540                                        $config_node = $doc -> createElement('configuration');
     541                                        $doc -> appendChild($config_node);
     542                                        $config_node -> appendChild($system_webServer_node);
     543                                }
     544                        }               
     545                }
     546        }
     547       
     548        $rule_fragment = $doc -> createDocumentFragment();
     549        $rule_fragment -> appendXML($rewrite_rule);
     550        $rules_node -> appendChild($rule_fragment);
     551
     552        $doc -> formatOutput = true;   
     553        saveDomDocument($doc, $filename);
     554
     555        return true;   
     556}
     557
     558/**
     559 * Saves the XML document into a file
     560 *
     561 * @param DOMDocument $doc
     562 * @param string $filename
     563 */
     564function saveDomDocument($doc, $filename)
     565{
     566        $config = $doc -> saveXML();   
     567        $config = preg_replace("/([^\r])\n/", "$1\r\n", $config);
     568        $fp = fopen($filename, 'w');
     569        fwrite($fp, $config);
     570        fclose($fp);
     571}
     572
     573/**
     574 * Workaround for Windows bug in is_writable() function
     575 *
     576 * @return
     577 * @param object $path
     578 */
     579function win_is_writable($path) {
     580//will work in despite of Windows ACLs bug
     581//NOTE: use a trailing slash for folders!!!
     582//see http://bugs.php.net/bug.php?id=27609
     583//see http://bugs.php.net/bug.php?id=30931
     584
     585    if ($path{strlen($path)-1}=='/') // recursively return a temporary file path
     586        return win_is_writable($path.uniqid(mt_rand()).'.tmp');
     587    else if (is_dir($path))
     588        return win_is_writable($path.'/'.uniqid(mt_rand()).'.tmp');
     589    // check tmp file for read/write capabilities
     590    $rm = file_exists($path);
     591    $f = @fopen($path, 'a');
     592    if ($f===false)
     593        return false;
     594    fclose($f);
     595    if (!$rm)
     596        unlink($path);
     597    return true;
     598}
     599?>
  • 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}
     110else{
     111        if ( (!file_exists($home_path.'.htaccess') && is_writable($home_path)) || is_writable($home_path.'.htaccess') )
     112                $writable = true;
     113        else
     114                $writable = false;
     115}
    107116
    108117if ($wp_rewrite->using_index_permalinks())
    109118        $usingpi = true;
     
    115124
    116125<?php if (isset($_POST['submit'])) : ?>
    117126<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.');
     127if ($iis7_permalinks){
     128        if ($permalink_structure && !$usingpi && !$writable)
     129                _e('You should update your web.config now');
     130        else if ($permalink_structure && !$usingpi && $writable)
     131                _e('Permalink structure updated. Remove write access on web.config file now!');
     132        else
     133                _e('Permalink structure updated');
     134}
     135else{
     136        if ( $permalink_structure && !$usingpi && !$writable )
     137                _e('You should update your .htaccess now.');
     138        else
     139                _e('Permalink structure updated.');
     140}
    122141?></p></div>
    123142<?php endif; ?>
    124143
     
    134153<?php
    135154$prefix = '';
    136155
    137 if ( ! got_mod_rewrite() )
     156if ( !got_mod_rewrite() && !$iis7_permalinks )
    138157        $prefix = '/index.php';
    139158
    140159$structures = array(
     
    179198</table>
    180199
    181200<h3><?php _e('Optional'); ?></h3>
    182 <?php if ($is_apache) : ?>
     201<?php if ($is_apache || $iis7_permalinks) : ?>
    183202        <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>
    184203<?php else : ?>
    185204        <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>
     
    203222        <input type="submit" name="submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" />
    204223</p>
    205224  </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>
     225<?php if ($iis7_permalinks) :
     226        if ( isset($_POST['submit']) && $permalink_structure && !$usingpi && !$writable ) : ?>
     227<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>
    208228<form action="options-permalink.php" method="post">
    209229<?php wp_nonce_field('update-permalink') ?>
     230        <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>
     231</form>
     232<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> 
     233        <?php endif; ?>
     234<?php else :
     235        if ( $permalink_structure && !$usingpi && !writable ) :?>       
     236<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>
     237<form action="options-permalink.php" method="post">
     238<?php wp_nonce_field('update-permalink') ?>
    210239        <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>
    211240</form>
     241        <?php endif; ?>
    212242<?php endif; ?>
    213243
    214244</div>
    215245
    216 <?php require('./admin-footer.php'); ?>
     246<?php require('./admin-footer.php'); ?>
     247 No newline at end of file