Improved styling of input groups
authorAlexander Ebert <ebert@woltlab.com>
Wed, 20 Jan 2016 16:10:21 +0000 (17:10 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 20 Jan 2016 16:10:21 +0000 (17:10 +0100)
wcfsetup/install/files/acp/templates/index.tpl
wcfsetup/install/files/acp/templates/login.tpl
wcfsetup/install/files/acp/templates/pageHeader.tpl
wcfsetup/install/files/acp/templates/rescueMode.tpl [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/RescueModeForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/IndexPage.class.php
wcfsetup/install/files/lib/system/WCFACP.class.php
wcfsetup/install/files/lib/system/request/RequestHandler.class.php
wcfsetup/install/files/style/layout/form.scss
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 92e002f2ee142c59134bcaae07bcb2b1124c3399..dbe64d96f2949f0b9873264e27b6532d5f14d806 100644 (file)
        <h1>{lang}wcf.global.acp{/lang}</h1>
 </header>
 
-{if $inRescueMode}
-       <p style="background-color: rgb(255, 153, 153); border: 2px solid rgb(255, 0, 0); padding: 1em;">{lang}wcf.acp.index.inRescueMode{/lang}</p>
-{/if}
-
 {if TMP_DIR !== WCF_DIR|concat:'tmp/'}
        <p class="error">{lang}wcf.acp.index.tmpBroken{/lang}</p>
 {/if}
index c98705fa0fffa280f0287592838e91f06dc98684..0c20f605bf6916246ea8b6ea5fba35940b2bfd3f 100644 (file)
@@ -1,4 +1,4 @@
-{include file='header' pageTitle='wcf.user.login'}
+{include file='header' pageTitle='wcf.user.login' __isLogin=true}
 
 <div id="login" style="display: none">
        <form method="post" action="{link controller='Login'}{/link}">
index ef9735d1311acd33e6e902ff3edafea52b515ec4..5214b6d34175406ee8019950ad473c88be9cd7bb 100644 (file)
@@ -4,11 +4,14 @@
                        <div class="layoutBoundary">
                                {include file='pageHeaderLogo'}
                                
-                               {include file='pageHeaderSearch'}
-                               
-                               {include file='pageHeaderMenu'}
-                               
-                               {include file='pageHeaderUser'}
+                               {* hide everything except the logo during login / in rescue mode *}
+                               {if $__isLogin|empty}
+                                       {include file='pageHeaderSearch'}
+                                       
+                                       {include file='pageHeaderMenu'}
+                                       
+                                       {include file='pageHeaderUser'}
+                               {/if}
                        </div>
                </div>
                
diff --git a/wcfsetup/install/files/acp/templates/rescueMode.tpl b/wcfsetup/install/files/acp/templates/rescueMode.tpl
new file mode 100644 (file)
index 0000000..5936b1d
--- /dev/null
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<html dir="{@$__wcf->getLanguage()->getPageDirection()}" lang="{@$__wcf->getLanguage()->getFixedLanguageCode()}">
+<head>
+       <meta charset="utf-8" />
+       <meta name="robots" content="noindex" />
+       <title>{lang}wcf.acp.rescueMode{/lang} - {lang}wcf.global.acp{/lang}{if PACKAGE_ID} - {PAGE_TITLE|language}{/if}</title>
+       
+       <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:400,300,600">
+       <link rel="stylesheet" href="{$pageURL}&proxy=css">
+</head>
+
+<body id="tpl{$templateName|ucfirst}" data-template="{$templateName}" data-application="{$templateNameApplication}" class="wcfAcp">
+<a id="top"></a>
+
+<div id="pageContainer" class="pageContainer">
+       <div class="pageHeaderContainer">
+               <header id="pageHeader" class="pageHeader">
+                       <div>
+                               <div class="layoutBoundary">
+                                       <div id="logo" class="logo">
+                                               <a href="{$pageURL}">
+                                                       <img src="{$pageURL}&proxy=logo" alt="" class="large">
+                                               </a>
+                                       </div>
+                               </div>
+                       </div>
+               </header>
+       </div>
+       
+       <section id="main" class="main" role="main">
+               <div class="layoutBoundary">
+                       <div id="content" class="content">
+
+{* content above was taken from 'header.tpl' *}
+
+<header class="boxHeadline">
+       <h1>{lang}wcf.acp.rescueMode{/lang}</h1>
+</header>
+
+<p class="info">{lang}wcf.acp.rescueMode.description{/lang}</p>
+
+{include file='formError'}
+
+<form method="post" action="{$pageURL}">
+       <section class="section">
+               <header class="sectionHeader">
+                       <h2 class="sectionTitle">{lang}wcf.acp.rescueMode.credentials{/lang}</h2>
+                       <small class="sectionDescription">{lang}wcf.acp.rescueMode.credentials.description{/lang}</small>
+               </header>
+               
+               <dl{if $errorField == 'username'} class="formError"{/if}>
+                       <dt><label for="username">{lang}wcf.user.username{/lang}</label></dt>
+                       <dd>
+                               <input type="text" id="username" name="username" value="{$username}" class="long" />
+                               {if $errorField == 'username'}
+                                       <small class="innerError">
+                                               {if $errorType == 'empty'}
+                                                       {lang}wcf.global.form.error.empty{/lang}
+                                               {elseif $errorType == 'notAuthorized'}
+                                                       {lang}wcf.acp.rescueMode.username.notAuthorized{/lang}
+                                               {else}
+                                                       {lang}wcf.user.username.error.{@$errorType}{/lang}
+                                               {/if}
+                                       </small>
+                               {/if}
+                       </dd>
+               </dl>
+               
+               <dl{if $errorField == 'password'} class="formError"{/if}>
+                       <dt><label for="password">{lang}wcf.user.password{/lang}</label></dt>
+                       <dd>
+                               <input type="password" id="password" name="password" value="" class="long" />
+                               {if $errorField == 'password'}
+                                       <small class="innerError">
+                                               {if $errorType == 'empty'}
+                                                       {lang}wcf.global.form.error.empty{/lang}
+                                               {else}
+                                                       {lang}wcf.user.password.error.{@$errorType}{/lang}
+                                               {/if}
+                                       </small>
+                               {/if}
+                       </dd>
+               </dl>
+       </section>
+       
+       {include file='captcha'}
+       
+       <section class="section">
+               <header class="sectionHeader">
+                       <h2 class="sectionTitle">{lang}wcf.acp.rescueMode.application{/lang}</h2>
+                       <small class="sectionDescription">{lang}wcf.acp.rescueMode.application.description{/lang}</small>
+               </header>
+               
+               {foreach from=$applications item=application}
+                       {capture assign=applicationSectionDomain}application_{@$application->packageID}_domainName{/capture}
+                       {capture assign=applicationSectionPath}application_{@$application->packageID}_domainPath{/capture}
+                       
+                       <dl{if $errorField == $applicationSectionDomain || $errorField == $applicationSectionPath} class="formError"{/if}>
+                               <dt><label for="application{@$application->packageID}">{$application->getPackage()}</label></dt>
+                               <dd>
+                                       <div class="inputAddon">
+                                               <span class="inputPrefix">{lang}wcf.acp.application.domainName{/lang}</span>
+                                               <input type="text" name="applicationValues[{@$application->packageID}][domainName]" id="application{@$application->packageID}" value="{$applicationValues[$application->packageID][domainName]}" class="long">
+                                       </div>
+                                       {if $errorField == $applicationSectionDomain}
+                                               <small class="innerError">
+                                                       {if $errorType == 'empty'}
+                                                               {lang}wcf.global.form.error.empty{/lang}
+                                                       {else}
+                                                               {lang}wcf.acp.application.domainName.error.{@$errorType}{/lang}
+                                                       {/if}
+                                               </small>
+                                       {/if}
+                               </dd>
+                               <dd>
+                                       <div class="inputAddon">
+                                               <span class="inputPrefix">{lang}wcf.acp.application.domainPath{/lang}</span>
+                                               <input type="text" name="applicationValues[{@$application->packageID}][domainPath]" value="{$applicationValues[$application->packageID][domainPath]}" class="long">
+                                       </div>
+                                       {if $errorField == $applicationSectionPath}
+                                               <small class="innerError">
+                                                       {if $errorType == 'empty'}
+                                                               {lang}wcf.global.form.error.empty{/lang}
+                                                       {else}
+                                                               {lang}wcf.acp.application.domainPath.error.{@$errorType}{/lang}
+                                                       {/if}
+                                               </small>
+                                       {/if}
+                               </dd>
+                       </dl>
+               {/foreach}
+       </section>
+       
+       <div class="formSubmit">
+               <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
+               
+               {* do not use the security token here because we cannot rely on working cookies *}
+       </div>
+</form>
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/lib/acp/form/RescueModeForm.class.php b/wcfsetup/install/files/lib/acp/form/RescueModeForm.class.php
new file mode 100644 (file)
index 0000000..9f3e16d
--- /dev/null
@@ -0,0 +1,340 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\application\Application;
+use wcf\data\application\ApplicationAction;
+use wcf\data\application\ApplicationEditor;
+use wcf\data\application\ApplicationList;
+use wcf\data\user\authentication\failure\UserAuthenticationFailure;
+use wcf\data\user\authentication\failure\UserAuthenticationFailureAction;
+use wcf\data\user\User;
+use wcf\form\AbstractCaptchaForm;
+use wcf\system\application\ApplicationHandler;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\exception\NamedUserException;
+use wcf\system\exception\UserInputException;
+use wcf\system\style\StyleHandler;
+use wcf\system\user\authentication\EmailUserAuthentication;
+use wcf\system\user\authentication\UserAuthenticationFactory;
+use wcf\system\WCF;
+use wcf\system\WCFACP;
+use wcf\util\FileUtil;
+use wcf\util\HeaderUtil;
+use wcf\util\StringUtil;
+use wcf\util\UserUtil;
+
+/**
+ * Shows the rescue mode form.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage acp.form
+ * @category   Community Framework
+ */
+class RescueModeForm extends AbstractCaptchaForm {
+       /**
+        * @var Application[]
+        */
+       public $applications;
+       
+       /**
+        * @var string[]
+        */
+       public $applicationValues = [];
+       
+       /**
+        * login password
+        * @var string
+        */
+       public $password = '';
+       
+       /**
+        * @var User
+        */
+       public $user;
+       
+       /**
+        * login username
+        * @var string
+        */
+       public $username = '';
+       
+       /**
+        * @inheritDoc
+        */
+       public $useCaptcha = false;
+       
+       /**
+        * @inheritDoc
+        */
+       public function __run() {
+               if (!WCFACP::inRescueMode()) {
+                       // redirect to currently active application's ACP
+                       HeaderUtil::redirect(ApplicationHandler::getInstance()->getActiveApplication()->getPageURL() . 'acp/');
+                       exit;
+               }
+               
+               parent::__run();
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               // request style generation to prevent issues when using the proxy parameter
+               StyleHandler::getInstance()->getStylesheet(true);
+               
+               if (isset($_GET['proxy'])) {
+                       switch ($_GET['proxy']) {
+                               case 'css':
+                                       $file = WCF_DIR . 'acp/style/style.css';
+                                       
+                                       header('Content-Type: text/css');
+                                       break;
+                               
+                               case 'logo':
+                                       $file = WCF_DIR . 'images/default-logo.png';
+                                       
+                                       header('Content-Type: image/png');
+                                       break;
+                               
+                               default:
+                                       throw new IllegalLinkException();
+                                       break;
+                       }
+                       
+                       header('Expires: '.gmdate('D, d M Y H:i:s', time() + 3600).' GMT');
+                       header('Last-Modified: Mon, 26 Jul 1997 05:00:00 GMT');
+                       header('Cache-Control: public, max-age=3600');
+                       
+                       readfile($file);
+                       exit;
+               }
+               
+               // check authentication failures
+               if (ENABLE_USER_AUTHENTICATION_FAILURE) {
+                       $failures = UserAuthenticationFailure::countIPFailures(UserUtil::getIpAddress());
+                       if (USER_AUTHENTICATION_FAILURE_IP_BLOCK && $failures >= USER_AUTHENTICATION_FAILURE_IP_BLOCK) {
+                               throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.user.login.blocked'));
+                       }
+                       if (USER_AUTHENTICATION_FAILURE_IP_CAPTCHA && $failures >= USER_AUTHENTICATION_FAILURE_IP_CAPTCHA) {
+                               $this->useCaptcha = true;
+                       }
+                       else if (USER_AUTHENTICATION_FAILURE_USER_CAPTCHA) {
+                               if (isset($_POST['username'])) {
+                                       $user = User::getUserByUsername(StringUtil::trim($_POST['username']));
+                                       if (!$user->userID) $user = User::getUserByEmail(StringUtil::trim($_POST['username']));
+                                       
+                                       if ($user->userID) {
+                                               $failures = UserAuthenticationFailure::countUserFailures($user->userID);
+                                               if (USER_AUTHENTICATION_FAILURE_USER_CAPTCHA && $failures >= USER_AUTHENTICATION_FAILURE_USER_CAPTCHA) {
+                                                       $this->useCaptcha = true;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               // read applications
+               $applicationList = new ApplicationList();
+               $applicationList->readObjects();
+               $this->applications = $applicationList->getObjects();
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (isset($_POST['username'])) $this->username = StringUtil::trim($_POST['username']);
+               if (isset($_POST['password'])) $this->password = $_POST['password'];
+               if (isset($_POST['applicationValues']) && is_array($_POST['applicationValues'])) $this->applicationValues = $_POST['applicationValues'];
+       }
+       
+       /**
+        * Validates the user access data.
+        */
+       protected function validateUser() {
+               try {
+                       $this->user = UserAuthenticationFactory::getInstance()->getUserAuthentication()->loginManually($this->username, $this->password);
+               }
+               catch (UserInputException $e) {
+                       if ($e->getField() == 'username') {
+                               try {
+                                       $this->user = EmailUserAuthentication::getInstance()->loginManually($this->username, $this->password);
+                               }
+                               catch (UserInputException $e2) {
+                                       if ($e2->getField() == 'username') throw $e;
+                                       throw $e2;
+                               }
+                       }
+                       else {
+                               throw $e;
+                       }
+               }
+               
+               // simulate login in order to access permissions
+               WCF::getSession()->disableUpdate();
+               WCF::getSession()->changeUser($this->user, true);
+               
+               if (!WCF::getSession()->getPermission('admin.system.canManageApplication')) {
+                       throw new UserInputException('username', 'notAuthorized');
+               }
+       }
+       
+       protected function validateApplications() {
+               $usedPaths = [];
+               foreach ($this->applications as $application) {
+                       $packageID = $application->packageID;
+                       
+                       $domainName = $this->applicationValues[$packageID]['domainName'];
+                       $domainName = preg_replace('~^https?://~', '', $domainName);
+                       $domainName = FileUtil::removeTrailingSlash($domainName);
+                       $domainName = StringUtil::trim($domainName);
+                       
+                       if (empty($domainName)) {
+                               throw new UserInputException("application_{$packageID}_domainName");
+                       }
+                       else if (preg_match('~[/#\?&]~', $domainName)) {
+                               throw new UserInputException("application_{$packageID}_domainName", 'containsPath');
+                       }
+                       
+                       $domainPath = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash($this->applicationValues[$packageID]['domainPath']));
+                       
+                       $this->applicationValues[$packageID]['domainName'] = $domainName;
+                       $this->applicationValues[$packageID]['domainPath'] = $domainPath;
+                       
+                       if (isset($usedPaths[$domainName])) {
+                               if(isset($usedPaths[$domainName][$domainPath])) {
+                                       WCF::getTPL()->assign('conflictApplication', $this->applications[$usedPaths[$domainName][$domainPath]]->getPackage());
+                                       throw new UserInputException("application_{$packageID}_domainPath", 'conflict');
+                               }
+                       }
+                       else {
+                               $usedPaths[$domainName] = [];
+                       }
+                       
+                       $usedPaths[$domainName][$domainPath] = $packageID;
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function submit() {
+               parent::submit();
+               
+               // save authentication failure
+               if (ENABLE_USER_AUTHENTICATION_FAILURE) {
+                       if ($this->errorField == 'username' || $this->errorField == 'password') {
+                               $action = new UserAuthenticationFailureAction([], 'create', [
+                                       'data' => [
+                                               'environment' => 'admin',
+                                               'userID' => ($this->user !== null ? $this->user->userID : null),
+                                               'username' => $this->username,
+                                               'time' => TIME_NOW,
+                                               'ipAddress' => UserUtil::getIpAddress(),
+                                               'userAgent' => UserUtil::getUserAgent()
+                                       ]
+                               ]);
+                               $action->executeAction();
+                               
+                               if ($this->captchaObjectType) {
+                                       $this->captchaObjectType->getProcessor()->reset();
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function validate() {
+               // bypass security token validation
+               $_POST['t'] = WCF::getSession()->getSecurityToken();
+               
+               parent::validate();
+               
+               // error handling
+               if (empty($this->username)) {
+                       throw new UserInputException('username');
+               }
+               
+               if (empty($this->password)) {
+                       throw new UserInputException('password');
+               }
+               
+               $this->validateUser();
+               $this->validateApplications();
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function save() {
+               parent::save();
+               
+               // update applications
+               foreach ($this->applications as $application) {
+                       $applicationEditor = new ApplicationEditor($application);
+                       $applicationEditor->update([
+                               'domainName' => $this->applicationValues[$application->packageID]['domainName'],
+                               'domainPath' => $this->applicationValues[$application->packageID]['domainPath'],
+                               'cookieDomain' => $this->applicationValues[$application->packageID]['domainName']
+                       ]);
+               }
+               
+               // rebuild cookie domain and paths
+               $applicationAction = new ApplicationAction([], 'rebuild');
+               $applicationAction->executeAction();
+               
+               // reload currently active application to avoid outdated cache data
+               $application = ApplicationHandler::getInstance()->getActiveApplication();
+               $application = new Application($application->packageID);
+               
+               // redirect to ACP of currently active application
+               HeaderUtil::redirect($application->getPageURL() . 'acp/');
+               exit;
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function readData() {
+               parent::readData();
+               
+               // get preferred username
+               if (empty($_POST)) {
+                       if (isset($_COOKIE[COOKIE_PREFIX.'userID'])) {
+                               $user = new User(intval($_COOKIE[COOKIE_PREFIX.'userID']));
+                               if ($user->userID) $this->username = $user->username;
+                       }
+                       
+                       foreach ($this->applications as $application) {
+                               $this->applicationValues[$application->packageID] = [
+                                       'domainName' => $application->domainName,
+                                       'domainPath' => $application->domainPath
+                               ];
+                       }
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign([
+                       'applications' => $this->applications,
+                       'applicationValues' => $this->applicationValues,
+                       'pageURL' => WCFACP::getRescueModePageURL() . 'acp/index.php?rescue-mode/',
+                       'password' => $this->password,
+                       'username' => $this->username
+               ]);
+       }
+}
index e34de6bea37c9c6f69e39a3c8c3104bee18e0087..93bb2d0ab7ac7da6db28f6e70cba56a164509350 100755 (executable)
@@ -2,14 +2,13 @@
 namespace wcf\acp\page;
 use wcf\page\AbstractPage;
 use wcf\system\package\PackageInstallationDispatcher;
-use wcf\system\request\RequestHandler;
 use wcf\system\WCF;
 
 /**
  * Shows the welcome page in admin control panel.
  * 
  * @author     Marcel Werk
- * @copyright  2001-2015 WoltLab GmbH
+ * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage acp.page
@@ -18,22 +17,22 @@ use wcf\system\WCF;
 class IndexPage extends AbstractPage {
        /**
         * server information
-        * @var array
+        * @var string[]
         */
-       public $server = array();
+       public $server = [];
        
        /**
-        * @see \wcf\page\IPage::readData()
+        * @inheritDoc
         */
        public function readData() {
                parent::readData();
                
-               $this->server = array(
+               $this->server = [
                        'os' => PHP_OS,
                        'webserver' => (isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : ''),
                        'mySQLVersion' => WCF::getDB()->getVersion(),
                        'load' => ''
-               );
+               ];
                
                // get load
                if (function_exists('sys_getloadavg')) {
@@ -45,7 +44,7 @@ class IndexPage extends AbstractPage {
        }
        
        /**
-        * @see \wcf\page\IPage::assignVariables()
+        * @inheritDoc
         */
        public function assignVariables() {
                parent::assignVariables();
@@ -61,15 +60,14 @@ class IndexPage extends AbstractPage {
                        $usersAwaitingApproval = $row['count'];
                }
                
-               WCF::getTPL()->assign(array(
-                       'inRescueMode' => RequestHandler::getInstance()->inRescueMode(),
+               WCF::getTPL()->assign([
                        'server' => $this->server,
                        'usersAwaitingApproval' => $usersAwaitingApproval
-               ));
+               ]);
        }
        
        /**
-        * @see \wcf\page\IPage::show()
+        * @inheritDoc
         */
        public function show() {
                // check package installation queue
@@ -77,9 +75,7 @@ class IndexPage extends AbstractPage {
                        $queueID = PackageInstallationDispatcher::checkPackageInstallationQueue();
                        
                        if ($queueID) {
-                               WCF::getTPL()->assign(array(
-                                       'queueID' => $queueID
-                               ));
+                               WCF::getTPL()->assign(['queueID' => $queueID]);
                                WCF::getTPL()->display('packageInstallationSetup');
                                exit;
                        }
index 9513e839b605ca91eb201dcaa0dcdde2c6b4bd54..a9c1316f1eed93957e5051e20cbfba320c1ff659 100644 (file)
@@ -25,6 +25,18 @@ use wcf\util\HeaderUtil;
  * @category   Community Framework
  */
 class WCFACP extends WCF {
+       /**
+        * rescue mode
+        * @var boolean
+        */
+       protected static $inRescueMode;
+       
+       /**
+        * URL to WCF within rescue mode
+        * @var string
+        */
+       protected static $rescueModePageURL;
+       
        /**
         * Calls all init functions of the WCF and the WCFACP class. 
         */
@@ -56,6 +68,47 @@ class WCFACP extends WCF {
                EventHandler::getInstance()->fireAction($this, 'initialized');
        }
        
+       /**
+        * Returns true if ACP is currently in rescue mode.
+        * 
+        * @return      boolean
+        */
+       public static function inRescueMode() {
+               if (self::$inRescueMode === null) {
+                       self::$inRescueMode = false;
+                       
+                       if (isset($_SERVER['HTTP_HOST'])) {
+                               self::$inRescueMode = true;
+                               
+                               foreach (ApplicationHandler::getInstance()->getApplications() as $application) {
+                                       if ($application->domainName === $_SERVER['HTTP_HOST']) {
+                                               self::$inRescueMode = false;
+                                               break;
+                                       }
+                               }
+                               
+                               if (self::$inRescueMode) {
+                                       self::$rescueModePageURL = RouteHandler::getProtocol() . $_SERVER['HTTP_HOST'] . RouteHandler::getPath(['acp']);
+                               }
+                       }
+               }
+               
+               return self::$inRescueMode;
+       }
+       
+       /**
+        * Returns URL for rescue mode page.
+        * 
+        * @return string
+        */
+       public static function getRescueModePageURL() {
+               if (self::inRescueMode()) {
+                       return self::$rescueModePageURL;
+               }
+               
+               return '';
+       }
+       
        /**
         * Does the user authentication.
         */
@@ -63,7 +116,16 @@ class WCFACP extends WCF {
                // this is a work-around since neither RequestHandler
                // nor RouteHandler are populated right now
                $pathInfo = RouteHandler::getPathInfo();
-               if (empty($pathInfo) || !preg_match('~^/?(acp-?captcha|login|logout)/~i', $pathInfo)) {
+               
+               if (self::inRescueMode()) {
+                       if (!preg_match('~^/?rescue-mode/~', $pathInfo)) {
+                               $redirectURI =  self::$rescueModePageURL . 'acp/index.php?rescue-mode/';
+                               
+                               HeaderUtil::redirect($redirectURI);
+                               exit;
+                       }
+               }
+               else if (empty($pathInfo) || !preg_match('~^/?(acp-?captcha|login|logout)/~i', $pathInfo)) {
                        if (WCF::getUser()->userID == 0) {
                                // work-around for AJAX-requests within ACP
                                if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
@@ -76,18 +138,10 @@ class WCFACP extends WCF {
                                        throw new SystemException("You have aborted the installation, therefore this installation is unusable. You are required to reinstall the software.");
                                }
                                
-                               // fallback for unknown host (rescue mode)
-                               if ($application->domainName != $_SERVER['HTTP_HOST']) {
-                                       $pageURL = RouteHandler::getProtocol() . $_SERVER['HTTP_HOST'] . RouteHandler::getPath(array('acp'));
-                               }
-                               else {
-                                       $pageURL = $application->getPageURL();
-                               }
-                               
                                // drop session id
                                $redirectURI = preg_replace('~[&\?]s=[a-f0-9]{40}(&|$)~', '', WCF::getSession()->requestURI);
                                
-                               $path = $pageURL . 'acp/index.php?login/' . SID_ARG_2ND_NOT_ENCODED . '&url=' . rawurlencode(RouteHandler::getProtocol() . $_SERVER['HTTP_HOST'] . $redirectURI);
+                               $path = $application->getPageURL() . 'acp/index.php?login/' . SID_ARG_2ND_NOT_ENCODED . '&url=' . rawurlencode(RouteHandler::getProtocol() . $_SERVER['HTTP_HOST'] . $redirectURI);
                                
                                HeaderUtil::redirect($path);
                                exit;
index 00f838396571a2aabff155301bc0424fb2c8e7aa..df6ae2b03bc41b60bf207e594f2bdb64bd8b7c14 100644 (file)
@@ -26,13 +26,13 @@ class RequestHandler extends SingletonFactory {
         * active request object
         * @var Request
         */
-       protected $activeRequest = null;
+       protected $activeRequest;
        
        /**
         * true, if current domain mismatch any known domain
         * @var boolean
         */
-       protected $inRescueMode = true;
+       protected $inRescueMode = false;
        
        /**
         * indicates if the request is an acp request
@@ -44,29 +44,7 @@ class RequestHandler extends SingletonFactory {
         * @see \wcf\system\SingletonFactory::init()
         */
        protected function init() {
-               if (isset($_SERVER['HTTP_HOST'])) {
-                       foreach (ApplicationHandler::getInstance()->getApplications() as $application) {
-                               if ($application->domainName == $_SERVER['HTTP_HOST']) {
-                                       $this->inRescueMode = false;
-                                       break;
-                               }
-                       }
-                       
-                       // check if WCF is running as standalone
-                       if ($this->inRescueMode() && PACKAGE_ID == 1) {
-                               if (ApplicationHandler::getInstance()->getWCF()->domainName == $_SERVER['HTTP_HOST']) {
-                                       $this->inRescueMode = false;
-                               }
-                       }
-               }
-               else {
-                       // when using cli, no rescue mode is provided
-                       $this->inRescueMode = false;
-               }
-               
-               if (class_exists('wcf\system\WCFACP', false)) {
-                       $this->isACPRequest = true;
-               }
+               $this->isACPRequest = class_exists('wcf\system\WCFACP', false);
        }
        
        /**
index 6a0e65574f42efd874fece20d8a38489cba6c3a0..a1dbd514e1bd5cee1e85f59e53b4a123f182432e 100644 (file)
@@ -189,21 +189,12 @@ textarea {
                margin-bottom: 5px;
        }
        
-       > .inputPrefix {
-               flex: 0 0 auto;
-               
-               &.button {
-                       border-radius: 0;
-                       margin-right: 5px;
-               }
-       }
-       
+       > .inputPrefix,
        > .inputSuffix {
                flex: 0 0 auto;
                
                &.button {
                        border-radius: 0;
-                       margin-left: 5px;
                }
                
                &:not(.button) {
@@ -211,13 +202,24 @@ textarea {
                        border: 1px solid $wcfButtonBorder;
                        color: $wcfButtonText;
                        cursor: default;
-                       margin-left: 5px;
                        padding: 3px 5px;
                }
        }
        
+       > .inputPrefix {
+               margin-right: 5px;
+       }
+       
+       > .inputSuffix {
+               margin-left: 5px;
+       }
+       
        input {
                flex: 1 auto;
+               
+               & + .inputPrefix {
+                       margin-left: 5px;
+               }
        }
 }
 
index 01f81406c3607a87bc8e9dd95ff46e394a0220ea..133bcd7544815c67847af0021ff2377545c4c3f5 100644 (file)
@@ -1317,6 +1317,16 @@ GmbH=Gesellschaft mit beschränkter Haftung]]></item>
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.statDaily.description"><![CDATA[Erzeugt die täglichen Statistiken neu]]></item>
        </category>
        
+       <category name="wcf.acp.rescueMode">
+               <item name="wcf.acp.rescueMode"><![CDATA[Systemwiederherstellung]]></item>
+               <item name="wcf.acp.rescueMode.application"><![CDATA[Installierte Anwendungen]]></item>
+               <item name="wcf.acp.rescueMode.application.description"><![CDATA[Bitte passen Sie sowohl die Domain als auch den Pfad jeder aufgeführten Anwendung an die geänderten Einstellung an, die Angabe der Domain erfolgt ohne Protokoll („http://“ bzw. „https://“).]]></item>
+               <item name="wcf.acp.rescueMode.credentials"><![CDATA[Zugangsdaten]]></item>
+               <item name="wcf.acp.rescueMode.credentials.description"><![CDATA[Die Änderung der Konfiguration erfordert gültige Zugangsdaten für ein Administrator-Konto mit der Berechtigung die installierten Anwendungen zu verwalten.]]></item>
+               <item name="wcf.acp.rescueMode.description"><![CDATA[Die eingestellte Domains und/oder Pfade stimmen nicht mit der für den Aufruf verwendeten Adresse überein; Dies kann in Folge eines Umzugs auf eine andere Domain oder Veränderung der Verzeichnisstruktur auftreten. Mit Hilfe des unten stehenden Formulars können Sie die Angaben schnell und einfach anpassen.]]></item>
+               <item name="wcf.acp.rescueMode.username.notAuthorized"><![CDATA[Diese Benutzer ist nicht berechtigt die Konfiguration zu verändern.]]></item>
+       </category>
+       
        <category name="wcf.acp.search">
                <item name="wcf.acp.search.noResults"><![CDATA[Keine Treffer]]></item>
                <item name="wcf.acp.search.provider.com.woltlab.wcf.menuItem"><![CDATA[Seiten]]></item>
index 315e2071b7b08a6f39c15fc5b6bcbc4847fc38e1..1e795cf6a407815f97c8f93534b0cb5646ad799a 100644 (file)
@@ -1316,6 +1316,16 @@ GmbH=Gesellschaft mit beschränkter Haftung]]></item>
                <item name="wcf.acp.rebuildData.com.woltlab.wcf.statDaily.description"><![CDATA[Rebuilds the daily statistics]]></item>
        </category>
        
+       <category name="wcf.acp.rescueMode">
+               <item name="wcf.acp.rescueMode"><![CDATA[Rescue Mode]]></item>
+               <item name="wcf.acp.rescueMode.application"><![CDATA[Installed Applications]]></item>
+               <item name="wcf.acp.rescueMode.application.description"><![CDATA[Please adjust both domain and path for each application listed below to match the changed settings. The domain must be provided without an explicit protocol such as “http://” or “https://”.]]></item>
+               <item name="wcf.acp.rescueMode.credentials"><![CDATA[Credentials]]></item>
+               <item name="wcf.acp.rescueMode.credentials.description"><![CDATA[Changes to the configuration require valid credentials of an administrator with the permissions to manage installed applications.]]></item>
+               <item name="wcf.acp.rescueMode.description"><![CDATA[The configured domains and/or paths do not match the address used to access this page. This can happen when moving to a new domain or changing the directory structure. Please use the form below to provide the new values.]]></item>
+               <item name="wcf.acp.rescueMode.username.notAuthorized"><![CDATA[This user is not authorized to manage installed applications.]]></item>
+       </category>
+       
        <category name="wcf.acp.search">
                <item name="wcf.acp.search.noResults"><![CDATA[No results]]></item>
                <item name="wcf.acp.search.provider.com.woltlab.wcf.menuItem"><![CDATA[ACP Menu]]></item>