diff --git a/.htaccess b/.htaccess index df074f7f80..5bf7b321f0 100644 --- a/.htaccess +++ b/.htaccess @@ -59,23 +59,6 @@ RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.* 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/.* AddType image/svg+xml svg svgz diff --git a/config/config.sample.php b/config/config.sample.php index 4321e5bab8..a0f04c0925 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -361,6 +361,31 @@ $CONFIG = array( */ '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``. */ diff --git a/core/Command/Maintenance/UpdateHtaccess.php b/core/Command/Maintenance/UpdateHtaccess.php new file mode 100644 index 0000000000..ad5bf5d8bd --- /dev/null +++ b/core/Command/Maintenance/UpdateHtaccess.php @@ -0,0 +1,44 @@ + + * + * @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 + * + */ +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; + } +} diff --git a/core/register_command.php b/core/register_command.php index e06ff436f5..b074339f4c 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -113,6 +113,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) { $application->add(new OC\Core\Command\Maintenance\Mode(\OC::$server->getConfig())); $application->add(new OC\Core\Command\Maintenance\Repair(new \OC\Repair(\OC\Repair::getRepairSteps()), \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(), diff --git a/lib/private/setup.php b/lib/private/setup.php index 196ae8a8bc..a38f594ff7 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -420,37 +420,47 @@ class Setup { $htaccessContent = file_get_contents($setupHelper->pathToHtaccess()); $content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n"; - if(strpos($htaccessContent, $content) === false) { - //custom 403 error page - $content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php"; + $htaccessContent = explode($content, $htaccessContent, 2)[0]; - //custom 404 error page - $content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php"; + //custom 403 error page + $content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php"; - // ownCloud may be configured to live at the root folder without a - // trailing slash being specified. In this case manually set the - // rewrite base to `/` - $rewriteBase = $webRoot; - if($webRoot === '') { - $rewriteBase = '/'; - } + //custom 404 error page + $content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php"; - // Add rewrite base + // Add rewrite rules if the RewriteBase is configured + $rewriteBase = $config->getSystemValue('htaccess.RewriteBase', ''); + if($rewriteBase !== '') { $content .= "\n"; + $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 RewriteBase ".$rewriteBase; + $content .= "\n RewriteBase " . $rewriteBase; $content .= "\n "; $content .= "\n SetEnv front_controller_active true"; $content .= "\n "; $content .= "\n DirectorySlash off"; $content .= "\n "; - $content.="\n "; - $content.="\n"; + $content .= "\n "; + $content .= "\n"; + } - if ($content !== '') { - //suppress errors in case we don't have permissions for it - @file_put_contents($setupHelper->pathToHtaccess(), $content . "\n", FILE_APPEND); - } + if ($content !== '') { + //suppress errors in case we don't have permissions for it + @file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent.$content . "\n"); } }