UtilTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <?php
  2. /**
  3. * Copyright (c) 2012 Lukas Reschke <lukas@statuscode.ch>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test;
  9. use OC_Util;
  10. use OCP\App\IAppManager;
  11. /**
  12. * Class UtilTest
  13. *
  14. * @package Test
  15. * @group DB
  16. */
  17. class UtilTest extends \Test\TestCase {
  18. public function testGetVersion() {
  19. $version = \OCP\Util::getVersion();
  20. $this->assertTrue(is_array($version));
  21. foreach ($version as $num) {
  22. $this->assertTrue(is_int($num));
  23. }
  24. }
  25. public function testGetVersionString() {
  26. $version = \OC_Util::getVersionString();
  27. $this->assertTrue(is_string($version));
  28. }
  29. public function testGetEditionString() {
  30. $edition = \OC_Util::getEditionString();
  31. $this->assertTrue(is_string($edition));
  32. }
  33. public function testSanitizeHTML() {
  34. $badArray = [
  35. 'While it is unusual to pass an array',
  36. 'this function actually <blink>supports</blink> it.',
  37. 'And therefore there needs to be a <script>alert("Unit"+\'test\')</script> for it!',
  38. [
  39. 'And It Even May <strong>Nest</strong>',
  40. ],
  41. ];
  42. $goodArray = [
  43. 'While it is unusual to pass an array',
  44. 'this function actually &lt;blink&gt;supports&lt;/blink&gt; it.',
  45. 'And therefore there needs to be a &lt;script&gt;alert(&quot;Unit&quot;+&#039;test&#039;)&lt;/script&gt; for it!',
  46. [
  47. 'And It Even May &lt;strong&gt;Nest&lt;/strong&gt;'
  48. ],
  49. ];
  50. $result = OC_Util::sanitizeHTML($badArray);
  51. $this->assertEquals($goodArray, $result);
  52. $badString = '<img onload="alert(1)" />';
  53. $result = OC_Util::sanitizeHTML($badString);
  54. $this->assertEquals('&lt;img onload=&quot;alert(1)&quot; /&gt;', $result);
  55. $badString = "<script>alert('Hacked!');</script>";
  56. $result = OC_Util::sanitizeHTML($badString);
  57. $this->assertEquals('&lt;script&gt;alert(&#039;Hacked!&#039;);&lt;/script&gt;', $result);
  58. $goodString = 'This is a good string without HTML.';
  59. $result = OC_Util::sanitizeHTML($goodString);
  60. $this->assertEquals('This is a good string without HTML.', $result);
  61. }
  62. public function testEncodePath() {
  63. $component = '/§#@test%&^ä/-child';
  64. $result = OC_Util::encodePath($component);
  65. $this->assertEquals("/%C2%A7%23%40test%25%26%5E%C3%A4/-child", $result);
  66. }
  67. public function testFileInfoLoaded() {
  68. $expected = function_exists('finfo_open');
  69. $this->assertEquals($expected, \OC_Util::fileInfoLoaded());
  70. }
  71. public function testGetDefaultEmailAddress() {
  72. $email = \OCP\Util::getDefaultEmailAddress("no-reply");
  73. $this->assertEquals('no-reply@localhost', $email);
  74. }
  75. public function testGetDefaultEmailAddressFromConfig() {
  76. $config = \OC::$server->getConfig();
  77. $config->setSystemValue('mail_domain', 'example.com');
  78. $email = \OCP\Util::getDefaultEmailAddress("no-reply");
  79. $this->assertEquals('no-reply@example.com', $email);
  80. $config->deleteSystemValue('mail_domain');
  81. }
  82. public function testGetConfiguredEmailAddressFromConfig() {
  83. $config = \OC::$server->getConfig();
  84. $config->setSystemValue('mail_domain', 'example.com');
  85. $config->setSystemValue('mail_from_address', 'owncloud');
  86. $email = \OCP\Util::getDefaultEmailAddress("no-reply");
  87. $this->assertEquals('owncloud@example.com', $email);
  88. $config->deleteSystemValue('mail_domain');
  89. $config->deleteSystemValue('mail_from_address');
  90. }
  91. public function testGetInstanceIdGeneratesValidId() {
  92. \OC::$server->getConfig()->deleteSystemValue('instanceid');
  93. $instanceId = OC_Util::getInstanceId();
  94. $this->assertStringStartsWith('oc', $instanceId);
  95. $matchesRegex = preg_match('/^[a-z0-9]+$/', $instanceId);
  96. $this->assertSame(1, $matchesRegex);
  97. }
  98. /**
  99. * @dataProvider filenameValidationProvider
  100. */
  101. public function testFilenameValidation($file, $valid) {
  102. // private API
  103. $this->assertEquals($valid, \OC_Util::isValidFileName($file));
  104. // public API
  105. $this->assertEquals($valid, \OCP\Util::isValidFileName($file));
  106. }
  107. public function filenameValidationProvider() {
  108. return [
  109. // valid names
  110. ['boringname', true],
  111. ['something.with.extension', true],
  112. ['now with spaces', true],
  113. ['.a', true],
  114. ['..a', true],
  115. ['.dotfile', true],
  116. ['single\'quote', true],
  117. [' spaces before', true],
  118. ['spaces after ', true],
  119. ['allowed chars including the crazy ones $%&_-^@!,()[]{}=;#', true],
  120. ['汉字也能用', true],
  121. ['und Ümläüte sind auch willkommen', true],
  122. // disallowed names
  123. ['', false],
  124. [' ', false],
  125. ['.', false],
  126. ['..', false],
  127. ['back\\slash', false],
  128. ['sl/ash', false],
  129. ['lt<lt', true],
  130. ['gt>gt', true],
  131. ['col:on', true],
  132. ['double"quote', true],
  133. ['pi|pe', true],
  134. ['dont?ask?questions?', true],
  135. ['super*star', true],
  136. ['new\nline', false],
  137. // better disallow these to avoid unexpected trimming to have side effects
  138. [' ..', false],
  139. ['.. ', false],
  140. ['. ', false],
  141. [' .', false],
  142. // part files not allowed
  143. ['.part', false],
  144. ['notallowed.part', false],
  145. ['neither.filepart', false],
  146. // part in the middle is ok
  147. ['super movie part one.mkv', true],
  148. ['super.movie.part.mkv', true],
  149. ];
  150. }
  151. /**
  152. * Test default apps
  153. *
  154. * @dataProvider defaultAppsProvider
  155. * @group DB
  156. */
  157. public function testDefaultApps($defaultAppConfig, $expectedPath, $enabledApps) {
  158. $oldDefaultApps = \OC::$server->getConfig()->getSystemValue('defaultapp', '');
  159. // CLI is doing messy stuff with the webroot, so need to work it around
  160. $oldWebRoot = \OC::$WEBROOT;
  161. \OC::$WEBROOT = '';
  162. $appManager = $this->createMock(IAppManager::class);
  163. $appManager->expects($this->any())
  164. ->method('isEnabledForUser')
  165. ->willReturnCallback(function ($appId) use ($enabledApps) {
  166. return in_array($appId, $enabledApps);
  167. });
  168. Dummy_OC_Util::$appManager = $appManager;
  169. // need to set a user id to make sure enabled apps are read from cache
  170. \OC_User::setUserId($this->getUniqueID());
  171. \OC::$server->getConfig()->setSystemValue('defaultapp', $defaultAppConfig);
  172. $this->assertEquals('http://localhost/' . $expectedPath, Dummy_OC_Util::getDefaultPageUrl());
  173. // restore old state
  174. \OC::$WEBROOT = $oldWebRoot;
  175. \OC::$server->getConfig()->setSystemValue('defaultapp', $oldDefaultApps);
  176. \OC_User::setUserId(null);
  177. }
  178. public function defaultAppsProvider() {
  179. return [
  180. // none specified, default to files
  181. [
  182. '',
  183. 'index.php/apps/files/',
  184. ['files'],
  185. ],
  186. // unexisting or inaccessible app specified, default to files
  187. [
  188. 'unexist',
  189. 'index.php/apps/files/',
  190. ['files'],
  191. ],
  192. // non-standard app
  193. [
  194. 'calendar',
  195. 'index.php/apps/calendar/',
  196. ['files', 'calendar'],
  197. ],
  198. // non-standard app with fallback
  199. [
  200. 'contacts,calendar',
  201. 'index.php/apps/calendar/',
  202. ['files', 'calendar'],
  203. ],
  204. ];
  205. }
  206. public function testGetDefaultPageUrlWithRedirectUrlWithoutFrontController() {
  207. putenv('front_controller_active=false');
  208. \OC::$server->getConfig()->deleteSystemValue('htaccess.IgnoreFrontController');
  209. $_REQUEST['redirect_url'] = 'myRedirectUrl.com';
  210. $this->assertSame('http://localhost'.\OC::$WEBROOT.'/myRedirectUrl.com', OC_Util::getDefaultPageUrl());
  211. }
  212. public function testGetDefaultPageUrlWithRedirectUrlRedirectBypassWithoutFrontController() {
  213. putenv('front_controller_active=false');
  214. \OC::$server->getConfig()->deleteSystemValue('htaccess.IgnoreFrontController');
  215. $_REQUEST['redirect_url'] = 'myRedirectUrl.com@foo.com:a';
  216. $this->assertSame('http://localhost'.\OC::$WEBROOT.'/index.php/apps/files/', OC_Util::getDefaultPageUrl());
  217. }
  218. public function testGetDefaultPageUrlWithRedirectUrlRedirectBypassWithFrontController() {
  219. putenv('front_controller_active=true');
  220. $_REQUEST['redirect_url'] = 'myRedirectUrl.com@foo.com:a';
  221. $this->assertSame('http://localhost'.\OC::$WEBROOT.'/apps/files/', OC_Util::getDefaultPageUrl());
  222. }
  223. public function testGetDefaultPageUrlWithRedirectUrlWithIgnoreFrontController() {
  224. putenv('front_controller_active=false');
  225. \OC::$server->getConfig()->setSystemValue('htaccess.IgnoreFrontController', true);
  226. $_REQUEST['redirect_url'] = 'myRedirectUrl.com@foo.com:a';
  227. $this->assertSame('http://localhost'.\OC::$WEBROOT.'/apps/files/', OC_Util::getDefaultPageUrl());
  228. }
  229. /**
  230. * Test needUpgrade() when the core version is increased
  231. */
  232. public function testNeedUpgradeCore() {
  233. $config = \OC::$server->getConfig();
  234. $oldConfigVersion = $config->getSystemValue('version', '0.0.0');
  235. $oldSessionVersion = \OC::$server->getSession()->get('OC_Version');
  236. $this->assertFalse(\OCP\Util::needUpgrade());
  237. $config->setSystemValue('version', '7.0.0.0');
  238. \OC::$server->getSession()->set('OC_Version', [7, 0, 0, 1]);
  239. self::invokePrivate(new \OCP\Util, 'needUpgradeCache', [null]);
  240. $this->assertTrue(\OCP\Util::needUpgrade());
  241. $config->setSystemValue('version', $oldConfigVersion);
  242. \OC::$server->getSession()->set('OC_Version', $oldSessionVersion);
  243. self::invokePrivate(new \OCP\Util, 'needUpgradeCache', [null]);
  244. $this->assertFalse(\OCP\Util::needUpgrade());
  245. }
  246. public function testCheckDataDirectoryValidity() {
  247. $dataDir = \OC::$server->getTempManager()->getTemporaryFolder();
  248. touch($dataDir . '/.ocdata');
  249. $errors = \OC_Util::checkDataDirectoryValidity($dataDir);
  250. $this->assertEmpty($errors);
  251. \OCP\Files::rmdirr($dataDir);
  252. $dataDir = \OC::$server->getTempManager()->getTemporaryFolder();
  253. // no touch
  254. $errors = \OC_Util::checkDataDirectoryValidity($dataDir);
  255. $this->assertNotEmpty($errors);
  256. \OCP\Files::rmdirr($dataDir);
  257. $errors = \OC_Util::checkDataDirectoryValidity('relative/path');
  258. $this->assertNotEmpty($errors);
  259. }
  260. protected function setUp(): void {
  261. parent::setUp();
  262. \OC_Util::$scripts = [];
  263. \OC_Util::$styles = [];
  264. }
  265. protected function tearDown(): void {
  266. parent::tearDown();
  267. \OC_Util::$scripts = [];
  268. \OC_Util::$styles = [];
  269. }
  270. public function testAddScript() {
  271. \OC_Util::addScript('core', 'myFancyJSFile1');
  272. \OC_Util::addScript('myApp', 'myFancyJSFile2');
  273. \OC_Util::addScript('core', 'myFancyJSFile0', true);
  274. \OC_Util::addScript('core', 'myFancyJSFile10', true);
  275. // add duplicate
  276. \OC_Util::addScript('core', 'myFancyJSFile1');
  277. $this->assertEquals([
  278. 'core/js/myFancyJSFile10',
  279. 'core/js/myFancyJSFile0',
  280. 'core/js/myFancyJSFile1',
  281. 'myApp/l10n/en',
  282. 'myApp/js/myFancyJSFile2',
  283. ], \OC_Util::$scripts);
  284. $this->assertEquals([], \OC_Util::$styles);
  285. }
  286. public function testAddVendorScript() {
  287. \OC_Util::addVendorScript('core', 'myFancyJSFile1');
  288. \OC_Util::addVendorScript('myApp', 'myFancyJSFile2');
  289. \OC_Util::addVendorScript('core', 'myFancyJSFile0', true);
  290. \OC_Util::addVendorScript('core', 'myFancyJSFile10', true);
  291. // add duplicate
  292. \OC_Util::addVendorScript('core', 'myFancyJSFile1');
  293. $this->assertEquals([
  294. 'core/vendor/myFancyJSFile10',
  295. 'core/vendor/myFancyJSFile0',
  296. 'core/vendor/myFancyJSFile1',
  297. 'myApp/vendor/myFancyJSFile2',
  298. ], \OC_Util::$scripts);
  299. $this->assertEquals([], \OC_Util::$styles);
  300. }
  301. public function testAddTranslations() {
  302. \OC_Util::addTranslations('appId', 'de');
  303. $this->assertEquals([
  304. 'appId/l10n/de'
  305. ], \OC_Util::$scripts);
  306. $this->assertEquals([], \OC_Util::$styles);
  307. }
  308. public function testAddStyle() {
  309. \OC_Util::addStyle('core', 'myFancyCSSFile1');
  310. \OC_Util::addStyle('myApp', 'myFancyCSSFile2');
  311. \OC_Util::addStyle('core', 'myFancyCSSFile0', true);
  312. \OC_Util::addStyle('core', 'myFancyCSSFile10', true);
  313. // add duplicate
  314. \OC_Util::addStyle('core', 'myFancyCSSFile1');
  315. $this->assertEquals([], \OC_Util::$scripts);
  316. $this->assertEquals([
  317. 'core/css/myFancyCSSFile10',
  318. 'core/css/myFancyCSSFile0',
  319. 'core/css/myFancyCSSFile1',
  320. 'myApp/css/myFancyCSSFile2',
  321. ], \OC_Util::$styles);
  322. }
  323. public function testAddVendorStyle() {
  324. \OC_Util::addVendorStyle('core', 'myFancyCSSFile1');
  325. \OC_Util::addVendorStyle('myApp', 'myFancyCSSFile2');
  326. \OC_Util::addVendorStyle('core', 'myFancyCSSFile0', true);
  327. \OC_Util::addVendorStyle('core', 'myFancyCSSFile10', true);
  328. // add duplicate
  329. \OC_Util::addVendorStyle('core', 'myFancyCSSFile1');
  330. $this->assertEquals([], \OC_Util::$scripts);
  331. $this->assertEquals([
  332. 'core/vendor/myFancyCSSFile10',
  333. 'core/vendor/myFancyCSSFile0',
  334. 'core/vendor/myFancyCSSFile1',
  335. 'myApp/vendor/myFancyCSSFile2',
  336. ], \OC_Util::$styles);
  337. }
  338. }
  339. /**
  340. * Dummy OC Util class to make it possible to override the app manager
  341. */
  342. class Dummy_OC_Util extends OC_Util {
  343. /**
  344. * @var \OCP\App\IAppManager
  345. */
  346. public static $appManager;
  347. protected static function getAppManager() {
  348. return self::$appManager;
  349. }
  350. }