Do not automatically try to enable index.php-less URLs (#24539)

The current logic for mod_rewrite relies on the fact that people have properly configured ownCloud, basically it reads from the `overwrite.cli.ur
l` entry and then derives the `RewriteBase` from it.

This usually works. However, since the ownCloud packages seem to install themselves at `/owncloud` (because subfolders are cool or so…) _a lot_ of people have just created a new Virtual Host for it or have simply symlinked the path etc.

This means that `overwrite.cli.url` is wrong, which fails hard if it is used as RewriteBase since Apache does not know where it should serve files from. In the end the ownCloud instance will not be accessible anymore and users will be frustrated. Also some shared hosters like 1&1 (because using shared hosters is so awesome… ;-)) have somewhat dubious Apache configurations or use versions of mod_rewrite from the mediveal age. (because updating is money or so…)

Anyhow. This makes this explicitly an opt-in configuration flag. If `htaccess.RewriteBase` is set then it will configure index.php-less URLs, if
admins set that after installation and don't want to wait until the next ownCloud version they can run `occ maintenance:update:htaccess`.

For ownCloud 9.0 we also have to add a repair step to make sure that instances that already have a RewriteBase configured continue to use it by copying it into the config file. That way all existing URLs stay valid. That one is not in this PR since this is unneccessary in master.

Effectively this reduces another risk of breakage when updating from ownCloud 8 to ownCloud 9.

Fixes https://github.com/owncloud/core/issues/24525, https://github.com/owncloud/core/issues/24426 and probably some more.
This commit is contained in:
Lukas Reschke 2016-05-12 09:43:26 +02:00 committed by Thomas Müller
parent dd9ee10bc0
commit 52add798d4
5 changed files with 100 additions and 37 deletions

View File

@ -59,23 +59,6 @@
RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.* RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*
RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L] RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
# Rewrite rules for `front_controller_active`
Options -MultiViews
RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$
RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$
RewriteCond %{REQUEST_FILENAME} !/remote.php
RewriteCond %{REQUEST_FILENAME} !/public.php
RewriteCond %{REQUEST_FILENAME} !/cron.php
RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php
RewriteCond %{REQUEST_FILENAME} !/status.php
RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php
RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php
RewriteCond %{REQUEST_FILENAME} !/updater/
RewriteCond %{REQUEST_FILENAME} !/ocs-provider/
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*
</IfModule> </IfModule>
<IfModule mod_mime.c> <IfModule mod_mime.c>
AddType image/svg+xml svg svgz AddType image/svg+xml svg svgz

View File

@ -361,6 +361,31 @@ $CONFIG = array(
*/ */
'overwrite.cli.url' => '', 'overwrite.cli.url' => '',
/**
* To have clean URLs without `/index.php` this parameter needs to be configured.
*
* This parameter will be written as "RewriteBase" on update and installation of
* ownCloud to your `.htaccess` file. While this value is often simply the URL
* path of the ownCloud installation it cannot be set automatically properly in
* every scenario and needs thus some manual configuration.
*
* In a standard Apache setup this usually equals the folder that ownCloud is
* accessible at. So if ownCloud is accessible via "https://mycloud.org/owncloud"
* the correct value would most likely be "/owncloud". If ownCloud is running
* under "https://mycloud.org/" then it would be "/".
*
* Note that above rule is not valid in every case, there are some rare setup
* cases where this may not apply. However, to avoid any update problems this
* configuration value is explicitly opt-in.
*
* After setting this value run `occ maintenance:update:htaccess` and when following
* conditions are met ownCloud uses URLs without index.php in it:
*
* - `mod_rewrite` is installed
* - `mod_env` is installed
*/
'htaccess.RewriteBase' => '/',
/** /**
* The URL of your proxy server, for example ``proxy.example.com:8081``. * The URL of your proxy server, for example ``proxy.example.com:8081``.
*/ */

View File

@ -0,0 +1,44 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Core\Command\Maintenance;
use InvalidArgumentException;
use OC\Setup;
use OCP\IConfig;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class UpdateHtaccess extends Command {
protected function configure() {
$this
->setName('maintenance:update:htaccess')
->setDescription('Updates the .htaccess file');
}
protected function execute(InputInterface $input, OutputInterface $output) {
\OC\Setup::updateHtaccess();
$output->writeln('.htaccess has been updated');
return 0;
}
}

View File

@ -116,6 +116,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
new \OC\Repair(\OC\Repair::getRepairSteps(), \OC::$server->getEventDispatcher()), \OC::$server->getConfig(), new \OC\Repair(\OC\Repair::getRepairSteps(), \OC::$server->getEventDispatcher()), \OC::$server->getConfig(),
\OC::$server->getEventDispatcher())); \OC::$server->getEventDispatcher()));
$application->add(new OC\Core\Command\Maintenance\SingleUser(\OC::$server->getConfig())); $application->add(new OC\Core\Command\Maintenance\SingleUser(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Maintenance\UpdateHtaccess());
$application->add(new OC\Core\Command\Upgrade(\OC::$server->getConfig(), \OC::$server->getLogger())); $application->add(new OC\Core\Command\Upgrade(\OC::$server->getConfig(), \OC::$server->getLogger()));

View File

@ -433,37 +433,47 @@ class Setup {
$htaccessContent = file_get_contents($setupHelper->pathToHtaccess()); $htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
$content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n"; $content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
if(strpos($htaccessContent, $content) === false) { $htaccessContent = explode($content, $htaccessContent, 2)[0];
//custom 403 error page
$content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php";
//custom 404 error page //custom 403 error page
$content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php"; $content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php";
// ownCloud may be configured to live at the root folder without a //custom 404 error page
// trailing slash being specified. In this case manually set the $content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php";
// rewrite base to `/`
$rewriteBase = $webRoot;
if($webRoot === '') {
$rewriteBase = '/';
}
// Add rewrite base // Add rewrite rules if the RewriteBase is configured
$rewriteBase = $config->getSystemValue('htaccess.RewriteBase', '');
if($rewriteBase !== '') {
$content .= "\n<IfModule mod_rewrite.c>"; $content .= "\n<IfModule mod_rewrite.c>";
$content .= "\n Options -MultiViews";
$content .= "\n RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
$content .= "\n RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/remote.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/public.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/cron.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/status.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/updater/";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
$content .= "\n RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*";
$content .= "\n RewriteRule . index.php [PT,E=PATH_INFO:$1]"; $content .= "\n RewriteRule . index.php [PT,E=PATH_INFO:$1]";
$content .= "\n RewriteBase ".$rewriteBase; $content .= "\n RewriteBase " . $rewriteBase;
$content .= "\n <IfModule mod_env.c>"; $content .= "\n <IfModule mod_env.c>";
$content .= "\n SetEnv front_controller_active true"; $content .= "\n SetEnv front_controller_active true";
$content .= "\n <IfModule mod_dir.c>"; $content .= "\n <IfModule mod_dir.c>";
$content .= "\n DirectorySlash off"; $content .= "\n DirectorySlash off";
$content .= "\n </IfModule>"; $content .= "\n </IfModule>";
$content.="\n </IfModule>"; $content .= "\n </IfModule>";
$content.="\n</IfModule>"; $content .= "\n</IfModule>";
}
if ($content !== '') { if ($content !== '') {
//suppress errors in case we don't have permissions for it //suppress errors in case we don't have permissions for it
@file_put_contents($setupHelper->pathToHtaccess(), $content . "\n", FILE_APPEND); @file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent.$content . "\n");
}
} }
} }