2 /***************************************************************
5 * (c) 2010 Helmut Hummel <helmut@typo3.org>
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
26 require_once t3lib_extMgm
::extPath('felogin', 'pi1/class.tx_felogin_pi1.php');
29 * Testcase for URL validation in class tx_felogin_pi1
31 * @author Helmut Hummel <helmut@typo3.org>
33 * @subpackage tests/typo3/sysext/felogin
35 class tx_feloginTest
extends tx_phpunit_testcase
{
40 private $backupGlobalVariables;
50 private $testHostName;
55 private $testSitePath;
60 private $testTableName;
62 public function setUp() {
63 $this->backupGlobalVariables
= array(
64 '_SERVER' => $_SERVER,
65 'TYPO3_DB' => $GLOBALS['TYPO3_DB'],
66 'TSFE' => $GLOBALS['TSFE'],
69 $this->testTableName
= 'sys_domain';
70 $this->testHostName
= 'hostname.tld';
71 $this->testSitePath
= '/';
73 // we need to subclass because the method we want to test is protected
74 $className = uniqid('FeLogin_');
76 class ' . $className. ' extends tx_felogin_pi1 {
77 public function validateRedirectUrl($url) {
78 return parent::validateRedirectUrl($url);
83 $this->txFelogin
= new $className();
84 $this->txFelogin
->cObj
= $this->getMock('tslib_cObj');
87 $this->setUpFakeSitePathAndHost();
90 private function setUpTSFE() {
91 $GLOBALS['TSFE'] = $this->getMock('tslib_fe', array(), array(), '', FALSE);
94 private function setUpFakeSitePathAndHost() {
95 $_SERVER['ORIG_PATH_INFO'] =
96 $_SERVER['PATH_INFO'] =
97 $_SERVER['ORIG_SCRIPT_NAME'] =
98 $_SERVER['SCRIPT_NAME'] = $this->testSitePath
. TYPO3_mainDir
;
99 $_SERVER['HTTP_HOST'] = $this->testHostName
;
102 private function setUpDatabaseMock() {
103 $GLOBALS['TYPO3_DB'] = $this->getMock('t3lib_DB', array('exec_SELECTgetRows'));
104 $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetRows')->will(
105 $this->returnCallback(array($this, 'getDomainRecordsCallback'))
110 * Callback method for pageIdCanBeDetermined test cases.
111 * Simulates TYPO3_DB->exec_SELECTgetRows().
113 * @param string $fields
114 * @param string $table
115 * @param string $where
117 * @see setUpDatabaseMock
119 public function getDomainRecordsCallback($fields, $table, $where) {
121 if ($table !== $this->testTableName
) {
126 array('domainName' => 'domainhostname.tld'),
127 array('domainName' => 'otherhostname.tld/path'),
128 array('domainName' => 'sub.domainhostname.tld/path/')
132 public function tearDown() {
133 $this->txFelogin
= null;
135 foreach ($this->backupGlobalVariables
as $key => $data) {
136 $GLOBALS[$key] = $data;
139 $this->backupGlobalVariables
= null;
146 public function typo3SitePathEqualsStubSitePath() {
147 $this->assertEquals(t3lib_div
::getIndpEnv('TYPO3_SITE_PATH'), $this->testSitePath
);
153 public function typo3SiteUrlEqualsStubSiteUrl() {
154 $this->assertEquals(t3lib_div
::getIndpEnv('TYPO3_SITE_URL'), 'http://' . $this->testHostName
. $this->testSitePath
);
160 public function typo3SitePathEqualsStubSitePathAfterChangingInTest() {
161 $this->testHostName
= 'somenewhostname.com';
162 $this->testSitePath
= '/somenewpath/';
163 $this->setUpFakeSitePathAndHost();
165 $this->assertEquals(t3lib_div
::getIndpEnv('TYPO3_SITE_PATH'), $this->testSitePath
);
171 public function typo3SiteUrlEqualsStubSiteUrlAfterChangingInTest() {
172 $this->testHostName
= 'somenewhostname.com';
173 $this->testSitePath
= '/somenewpath/';
174 $this->setUpFakeSitePathAndHost();
176 $this->assertEquals(t3lib_div
::getIndpEnv('TYPO3_SITE_URL'), 'http://' . $this->testHostName
. $this->testSitePath
);
180 * Data provider for malicousUrlsWillBeCleared
182 * @see malicousUrlsWillBeCleared
184 public function variousUrlsDataProviderForMalicousUrlsWillBeCleared() {
186 'absolute URL, hostname not in sys_domain, trailing slash' => array('http://badhost.tld/'),
187 'absolute URL, hostname not in sys_domain, no trailing slash' => array('http://badhost.tld'),
188 'absolute URL, subdomain in sys_domain, but main domain not, trailing slash' => array('http://domainhostname.tld.badhost.tld/'),
189 'absolute URL, subdomain in sys_domain, but main domain not, no trailing slash' => array('http://domainhostname.tld.badhost.tld'),
190 'non http absolute URL 1' => array('its://domainhostname.tld/itunes/'),
191 'non http absolute URL 2' => array('ftp://domainhostname.tld/download/'),
193 'XSS attempt 1' => array('javascript:alert(123)'),
194 'XSS attempt 2' => array('" onmouseover="alert(123)"'),
195 'invalid URL, HTML break out attempt' => array('" >blabuubb'),
196 'invalid URL, UNC path' => array('\\\\foo\\bar\\'),
197 'invalid URL, backslashes in path' => array('http://domainhostname.tld\\bla\\blupp'),
198 'invalid URL, linefeed in path' => array("http://domainhostname.tld/bla/blupp\n"),
199 'invalid URL, only one slash after scheme' => array("http:/domainhostname.tld/bla/blupp"),
200 'invalid URL, illegal chars' => array("http://(<>domainhostname).tld/bla/blupp"),
207 * @dataProvider variousUrlsDataProviderForMalicousUrlsWillBeCleared
209 public function malicousUrlsWillBeCleared($url) {
210 $this->setUpDatabaseMock();
211 $this->assertEquals('', $this->txFelogin
->validateRedirectUrl($url));
215 * Data provider for cleanUrlsAreKept
217 * @see cleanUrlsAreKept
219 public function variousUrlsDataProviderForCleanUrlsAreKept() {
221 'sane absolute URL' => array('http://domainhostname.tld/'),
222 'sane absolute URL with script' => array('http://domainhostname.tld/index.php?id=1'),
223 'sane absolute URL with realurl' => array('http://domainhostname.tld/foo/bar/foo.html'),
224 'sane absolute URL with homedir' => array('http://domainhostname.tld/~user/'),
225 'sane absolute URL with some strange chars encoded' => array('http://domainhostname.tld/~user/a%cc%88o%cc%88%c3%9fa%cc%82/foo.html'),
227 'sane absolute URL (domain record with path)' => array('http://otherhostname.tld/path/'),
228 'sane absolute URL with script (domain record with path)' => array('http://otherhostname.tld/path/index.php?id=1'),
229 'sane absolute URL with realurl (domain record with path)' => array('http://otherhostname.tld/path/foo/bar/foo.html'),
231 'sane absolute URL (domain record with path and slash)' => array('http://sub.domainhostname.tld/path/'),
232 'sane absolute URL with script (domain record with path slash)' => array('http://sub.domainhostname.tld/path/index.php?id=1'),
233 'sane absolute URL with realurl (domain record with path slash)' => array('http://sub.domainhostname.tld/path/foo/bar/foo.html'),
235 'relative URL, no leading slash 1' => array('index.php?id=1'),
236 'relative URL, no leading slash 2' => array('foo/bar/index.php?id=2'),
237 'relative URL, leading slash, no realurl' => array('/index.php?id=1'),
238 'relative URL, leading slash, realurl' => array('/de/service/imprint.html'),
244 * @dataProvider variousUrlsDataProviderForCleanUrlsAreKept
246 public function cleanUrlsAreKept($url) {
247 $this->setUpDatabaseMock();
248 $this->assertEquals($url, $this->txFelogin
->validateRedirectUrl($url));
252 * Data provider for malicousUrlsWillBeClearedTypo3InSubdirectory
254 * @see malicousUrlsWillBeClearedTypo3InSubdirectory
256 public function variousUrlsDataProviderForMalicousUrlsWillBeClearedTypo3InSubdirectory() {
258 'absolute URL, missing subdirectory' => array('http://hostname.tld/'),
259 'absolute URL, wrong subdirectory' => array('http://hostname.tld/hacker/index.php'),
260 'absolute URL, correct subdirectory, no trailing slash' => array('http://hostname.tld/subdir'),
261 'absolute URL, correct subdirectory of sys_domain record, no trailing slash' => array('http://otherhostname.tld/path'),
262 'absolute URL, correct subdirectory of sys_domain record, no trailing slash' => array('http://sub.domainhostname.tld/path'),
264 'relative URL, leading slash, no path' => array('/index.php?id=1'),
265 'relative URL, leading slash, wrong path' => array('/de/sub/site.html'),
266 'relative URL, leading slash, slash only' => array('/'),
272 * @dataProvider variousUrlsDataProviderForMalicousUrlsWillBeClearedTypo3InSubdirectory
274 public function malicousUrlsWillBeClearedTypo3InSubdirectory($url) {
275 $this->testSitePath
= '/subdir/';
276 $this->setUpFakeSitePathAndHost();
278 $this->setUpDatabaseMock();
279 $this->assertEquals('', $this->txFelogin
->validateRedirectUrl($url));
283 * Data provider for cleanUrlsAreKeptTypo3InSubdirectory
285 * @see cleanUrlsAreKeptTypo3InSubdirectory
287 public function variousUrlsDataProviderForCleanUrlsAreKeptTypo3InSubdirectory() {
289 'absolute URL, correct subdirectory' => array('http://hostname.tld/subdir/'),
290 'absolute URL, correct subdirectory, realurl' => array('http://hostname.tld/subdir/de/imprint.html'),
291 'absolute URL, correct subdirectory, no realurl' => array('http://hostname.tld/subdir/index.php?id=10'),
293 'absolute URL, correct subdirectory of sys_domain record' => array('http://otherhostname.tld/path/'),
294 'absolute URL, correct subdirectory of sys_domain record' => array('http://sub.domainhostname.tld/path/'),
296 'relative URL, no leading slash, realurl' => array('de/service/imprint.html'),
297 'relative URL, no leading slash, no realurl' => array('index.php?id=1'),
298 'relative URL, no leading slash, no realurl' => array('foo/bar/index.php?id=2'),
304 * @dataProvider variousUrlsDataProviderForCleanUrlsAreKeptTypo3InSubdirectory
306 public function cleanUrlsAreKeptTypo3InSubdirectory($url) {
307 $this->testSitePath
= '/subdir/';
308 $this->setUpFakeSitePathAndHost();
310 $this->setUpDatabaseMock();
311 $this->assertEquals($url, $this->txFelogin
->validateRedirectUrl($url));