PageRenderTime 60ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/util.php

https://github.com/sezuan/core
PHP | 895 lines | 558 code | 101 blank | 236 comment | 117 complexity | 716de19c7bf491238cfcbabd60af6c01 MD5 | raw file
Possible License(s): AGPL-3.0, AGPL-1.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. require_once 'Patchwork/PHP/Shim/Normalizer.php';
  3. /**
  4. * Class for utility functions
  5. *
  6. */
  7. class OC_Util {
  8. public static $scripts=array();
  9. public static $styles=array();
  10. public static $headers=array();
  11. private static $rootMounted=false;
  12. private static $fsSetup=false;
  13. public static $core_styles=array();
  14. public static $core_scripts=array();
  15. // Can be set up
  16. public static function setupFS( $user = '' ) {// configure the initial filesystem based on the configuration
  17. if(self::$fsSetup) {//setting up the filesystem twice can only lead to trouble
  18. return false;
  19. }
  20. // If we are not forced to load a specific user we load the one that is logged in
  21. if( $user == "" && OC_User::isLoggedIn()) {
  22. $user = OC_User::getUser();
  23. }
  24. // load all filesystem apps before, so no setup-hook gets lost
  25. if(!isset($RUNTIME_NOAPPS) || !$RUNTIME_NOAPPS) {
  26. OC_App::loadApps(array('filesystem'));
  27. }
  28. // the filesystem will finish when $user is not empty,
  29. // mark fs setup here to avoid doing the setup from loading
  30. // OC_Filesystem
  31. if ($user != '') {
  32. self::$fsSetup=true;
  33. }
  34. $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
  35. //first set up the local "root" storage
  36. \OC\Files\Filesystem::initMounts();
  37. if(!self::$rootMounted) {
  38. \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir'=>$CONFIG_DATADIRECTORY), '/');
  39. self::$rootMounted=true;
  40. }
  41. if( $user != "" ) { //if we aren't logged in, there is no use to set up the filesystem
  42. $user_dir = '/'.$user.'/files';
  43. $user_root = OC_User::getHome($user);
  44. $userdirectory = $user_root . '/files';
  45. if( !is_dir( $userdirectory )) {
  46. mkdir( $userdirectory, 0755, true );
  47. }
  48. //jail the user into his "home" directory
  49. \OC\Files\Filesystem::init($user, $user_dir);
  50. $quotaProxy=new OC_FileProxy_Quota();
  51. $fileOperationProxy = new OC_FileProxy_FileOperations();
  52. OC_FileProxy::register($quotaProxy);
  53. OC_FileProxy::register($fileOperationProxy);
  54. OC_Hook::emit('OC_Filesystem', 'setup', array('user' => $user, 'user_dir' => $user_dir));
  55. }
  56. return true;
  57. }
  58. public static function tearDownFS() {
  59. \OC\Files\Filesystem::tearDown();
  60. self::$fsSetup=false;
  61. self::$rootMounted=false;
  62. }
  63. /**
  64. * get the current installed version of ownCloud
  65. * @return array
  66. */
  67. public static function getVersion() {
  68. // hint: We only can count up. Reset minor/patchlevel when
  69. // updating major/minor version number.
  70. return array(5, 80, 05);
  71. }
  72. /**
  73. * get the current installed version string of ownCloud
  74. * @return string
  75. */
  76. public static function getVersionString() {
  77. return '6.0 pre alpha';
  78. }
  79. /**
  80. * get the current installed edition of ownCloud. There is the community
  81. * edition that just returns an empty string and the enterprise edition
  82. * that returns "Enterprise".
  83. * @return string
  84. */
  85. public static function getEditionString() {
  86. return '';
  87. }
  88. /**
  89. * add a javascript file
  90. *
  91. * @param appid $application
  92. * @param filename $file
  93. */
  94. public static function addScript( $application, $file = null ) {
  95. if( is_null( $file )) {
  96. $file = $application;
  97. $application = "";
  98. }
  99. if( !empty( $application )) {
  100. self::$scripts[] = "$application/js/$file";
  101. }else{
  102. self::$scripts[] = "js/$file";
  103. }
  104. }
  105. /**
  106. * add a css file
  107. *
  108. * @param appid $application
  109. * @param filename $file
  110. */
  111. public static function addStyle( $application, $file = null ) {
  112. if( is_null( $file )) {
  113. $file = $application;
  114. $application = "";
  115. }
  116. if( !empty( $application )) {
  117. self::$styles[] = "$application/css/$file";
  118. }else{
  119. self::$styles[] = "css/$file";
  120. }
  121. }
  122. /**
  123. * @brief Add a custom element to the header
  124. * @param string tag tag name of the element
  125. * @param array $attributes array of attributes for the element
  126. * @param string $text the text content for the element
  127. */
  128. public static function addHeader( $tag, $attributes, $text='') {
  129. self::$headers[] = array('tag'=>$tag, 'attributes'=>$attributes, 'text'=>$text);
  130. }
  131. /**
  132. * formats a timestamp in the "right" way
  133. *
  134. * @param int timestamp $timestamp
  135. * @param bool dateOnly option to omit time from the result
  136. */
  137. public static function formatDate( $timestamp, $dateOnly=false) {
  138. if(\OC::$session->exists('timezone')) {//adjust to clients timezone if we know it
  139. $systemTimeZone = intval(date('O'));
  140. $systemTimeZone=(round($systemTimeZone/100, 0)*60)+($systemTimeZone%100);
  141. $clientTimeZone=\OC::$session->get('timezone')*60;
  142. $offset=$clientTimeZone-$systemTimeZone;
  143. $timestamp=$timestamp+$offset*60;
  144. }
  145. $l=OC_L10N::get('lib');
  146. return $l->l($dateOnly ? 'date' : 'datetime', $timestamp);
  147. }
  148. /**
  149. * check if the current server configuration is suitable for ownCloud
  150. * @return array arrays with error messages and hints
  151. */
  152. public static function checkServer() {
  153. $errors=array();
  154. $defaults = new \OC_Defaults();
  155. $web_server_restart= false;
  156. //check for database drivers
  157. if(!(is_callable('sqlite_open') or class_exists('SQLite3'))
  158. and !is_callable('mysql_connect')
  159. and !is_callable('pg_connect')
  160. and !is_callable('oci_connect')) {
  161. $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.',
  162. 'hint'=>'');//TODO: sane hint
  163. $web_server_restart= true;
  164. }
  165. //common hint for all file permissons error messages
  166. $permissionsHint = 'Permissions can usually be fixed by '
  167. .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the root directory</a>.';
  168. // Check if config folder is writable.
  169. if(!is_writable(OC::$SERVERROOT."/config/") or !is_readable(OC::$SERVERROOT."/config/")) {
  170. $errors[] = array(
  171. 'error' => "Can't write into config directory",
  172. 'hint' => 'This can usually be fixed by '
  173. .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the config directory</a>.'
  174. );
  175. }
  176. // Check if there is a writable install folder.
  177. if(OC_Config::getValue('appstoreenabled', true)) {
  178. if( OC_App::getInstallPath() === null
  179. || !is_writable(OC_App::getInstallPath())
  180. || !is_readable(OC_App::getInstallPath()) ) {
  181. $errors[] = array(
  182. 'error' => "Can't write into apps directory",
  183. 'hint' => 'This can usually be fixed by '
  184. .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the apps directory</a> '
  185. .'or disabling the appstore in the config file.'
  186. );
  187. }
  188. }
  189. $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
  190. // Create root dir.
  191. if(!is_dir($CONFIG_DATADIRECTORY)) {
  192. $success=@mkdir($CONFIG_DATADIRECTORY);
  193. if ($success) {
  194. $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
  195. } else {
  196. $errors[] = array(
  197. 'error' => "Can't create data directory (".$CONFIG_DATADIRECTORY.")",
  198. 'hint' => 'This can usually be fixed by '
  199. .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the root directory</a>.'
  200. );
  201. }
  202. } else if(!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) {
  203. $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') not writable by ownCloud',
  204. 'hint'=>$permissionsHint);
  205. } else {
  206. $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
  207. }
  208. // check if all required php modules are present
  209. if(!class_exists('ZipArchive')) {
  210. $errors[]=array('error'=>'PHP module zip not installed.',
  211. 'hint'=>'Please ask your server administrator to install the module.');
  212. $web_server_restart=true;
  213. }
  214. if(!class_exists('DOMDocument')) {
  215. $errors[] = array('error' => 'PHP module dom not installed.',
  216. 'hint' => 'Please ask your server administrator to install the module.');
  217. $web_server_restart =true;
  218. }
  219. if(!function_exists('xml_parser_create')) {
  220. $errors[] = array('error' => 'PHP module libxml not installed.',
  221. 'hint' => 'Please ask your server administrator to install the module.');
  222. $web_server_restart =true;
  223. }
  224. if(!function_exists('mb_detect_encoding')) {
  225. $errors[]=array('error'=>'PHP module mb multibyte not installed.',
  226. 'hint'=>'Please ask your server administrator to install the module.');
  227. $web_server_restart=true;
  228. }
  229. if(!function_exists('ctype_digit')) {
  230. $errors[]=array('error'=>'PHP module ctype is not installed.',
  231. 'hint'=>'Please ask your server administrator to install the module.');
  232. $web_server_restart=true;
  233. }
  234. if(!function_exists('json_encode')) {
  235. $errors[]=array('error'=>'PHP module JSON is not installed.',
  236. 'hint'=>'Please ask your server administrator to install the module.');
  237. $web_server_restart=true;
  238. }
  239. if(!extension_loaded('gd') || !function_exists('gd_info')) {
  240. $errors[]=array('error'=>'PHP module GD is not installed.',
  241. 'hint'=>'Please ask your server administrator to install the module.');
  242. $web_server_restart=true;
  243. }
  244. if(!function_exists('gzencode')) {
  245. $errors[]=array('error'=>'PHP module zlib is not installed.',
  246. 'hint'=>'Please ask your server administrator to install the module.');
  247. $web_server_restart=true;
  248. }
  249. if(!function_exists('iconv')) {
  250. $errors[]=array('error'=>'PHP module iconv is not installed.',
  251. 'hint'=>'Please ask your server administrator to install the module.');
  252. $web_server_restart=true;
  253. }
  254. if(!function_exists('simplexml_load_string')) {
  255. $errors[]=array('error'=>'PHP module SimpleXML is not installed.',
  256. 'hint'=>'Please ask your server administrator to install the module.');
  257. $web_server_restart=true;
  258. }
  259. if(floatval(phpversion())<5.3) {
  260. $errors[]=array('error'=>'PHP 5.3 is required.',
  261. 'hint'=>'Please ask your server administrator to update PHP to version 5.3 or higher.'
  262. .' PHP 5.2 is no longer supported by ownCloud and the PHP community.');
  263. $web_server_restart=true;
  264. }
  265. if(!defined('PDO::ATTR_DRIVER_NAME')) {
  266. $errors[]=array('error'=>'PHP PDO module is not installed.',
  267. 'hint'=>'Please ask your server administrator to install the module.');
  268. $web_server_restart=true;
  269. }
  270. if (((strtolower(@ini_get('safe_mode')) == 'on')
  271. || (strtolower(@ini_get('safe_mode')) == 'yes')
  272. || (strtolower(@ini_get('safe_mode')) == 'true')
  273. || (ini_get("safe_mode") == 1 ))) {
  274. $errors[]=array('error'=>'PHP Safe Mode is enabled. ownCloud requires that it is disabled to work properly.',
  275. 'hint'=>'PHP Safe Mode is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.');
  276. $web_server_restart=true;
  277. }
  278. if (get_magic_quotes_gpc() == 1 ) {
  279. $errors[]=array('error'=>'Magic Quotes is enabled. ownCloud requires that it is disabled to work properly.',
  280. 'hint'=>'Magic Quotes is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.');
  281. $web_server_restart=true;
  282. }
  283. if($web_server_restart) {
  284. $errors[]=array('error'=>'PHP modules have been installed, but they are still listed as missing?',
  285. 'hint'=>'Please ask your server administrator to restart the web server.');
  286. }
  287. return $errors;
  288. }
  289. /**
  290. * Check for correct file permissions of data directory
  291. * @return array arrays with error messages and hints
  292. */
  293. public static function checkDataDirectoryPermissions($dataDirectory) {
  294. $errors = array();
  295. if (stristr(PHP_OS, 'WIN')) {
  296. //TODO: permissions checks for windows hosts
  297. } else {
  298. $permissionsModHint = 'Please change the permissions to 0770 so that the directory'
  299. .' cannot be listed by other users.';
  300. $prems = substr(decoct(@fileperms($dataDirectory)), -3);
  301. if (substr($prems, -1) != '0') {
  302. OC_Helper::chmodr($dataDirectory, 0770);
  303. clearstatcache();
  304. $prems = substr(decoct(@fileperms($dataDirectory)), -3);
  305. if (substr($prems, 2, 1) != '0') {
  306. $errors[] = array('error' => 'Data directory ('.$dataDirectory.') is readable for other users',
  307. 'hint' => $permissionsModHint);
  308. }
  309. }
  310. }
  311. return $errors;
  312. }
  313. public static function displayLoginPage($errors = array()) {
  314. $parameters = array();
  315. foreach( $errors as $key => $value ) {
  316. $parameters[$value] = true;
  317. }
  318. if (!empty($_POST['user'])) {
  319. $parameters["username"] = $_POST['user'];
  320. $parameters['user_autofocus'] = false;
  321. } else {
  322. $parameters["username"] = '';
  323. $parameters['user_autofocus'] = true;
  324. }
  325. if (isset($_REQUEST['redirect_url'])) {
  326. $redirect_url = $_REQUEST['redirect_url'];
  327. $parameters['redirect_url'] = urlencode($redirect_url);
  328. }
  329. $parameters['alt_login'] = OC_App::getAlternativeLogIns();
  330. OC_Template::printGuestPage("", "login", $parameters);
  331. }
  332. /**
  333. * Check if the app is enabled, redirects to home if not
  334. */
  335. public static function checkAppEnabled($app) {
  336. if( !OC_App::isEnabled($app)) {
  337. header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
  338. exit();
  339. }
  340. }
  341. /**
  342. * Check if the user is logged in, redirects to home if not. With
  343. * redirect URL parameter to the request URI.
  344. */
  345. public static function checkLoggedIn() {
  346. // Check if we are a user
  347. if( !OC_User::isLoggedIn()) {
  348. header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php',
  349. array('redirect_url' => OC_Request::requestUri())));
  350. exit();
  351. }
  352. }
  353. /**
  354. * Check if the user is a admin, redirects to home if not
  355. */
  356. public static function checkAdminUser() {
  357. if( !OC_User::isAdminUser(OC_User::getUser())) {
  358. header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
  359. exit();
  360. }
  361. }
  362. /**
  363. * Check if the user is a subadmin, redirects to home if not
  364. * @return array $groups where the current user is subadmin
  365. */
  366. public static function checkSubAdminUser() {
  367. if(!OC_SubAdmin::isSubAdmin(OC_User::getUser())) {
  368. header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
  369. exit();
  370. }
  371. return true;
  372. }
  373. /**
  374. * Redirect to the user default page
  375. */
  376. public static function redirectToDefaultPage() {
  377. if(isset($_REQUEST['redirect_url'])) {
  378. $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url']));
  379. }
  380. else if (isset(OC::$REQUESTEDAPP) && !empty(OC::$REQUESTEDAPP)) {
  381. $location = OC_Helper::linkToAbsolute( OC::$REQUESTEDAPP, 'index.php' );
  382. }
  383. else {
  384. $defaultpage = OC_Appconfig::getValue('core', 'defaultpage');
  385. if ($defaultpage) {
  386. $location = OC_Helper::makeURLAbsolute(OC::$WEBROOT.'/'.$defaultpage);
  387. }
  388. else {
  389. $location = OC_Helper::linkToAbsolute( 'files', 'index.php' );
  390. }
  391. }
  392. OC_Log::write('core', 'redirectToDefaultPage: '.$location, OC_Log::DEBUG);
  393. header( 'Location: '.$location );
  394. exit();
  395. }
  396. /**
  397. * get an id unique for this instance
  398. * @return string
  399. */
  400. public static function getInstanceId() {
  401. $id = OC_Config::getValue('instanceid', null);
  402. if(is_null($id)) {
  403. // We need to guarantee at least one letter in instanceid so it can be used as the session_name
  404. $id = 'oc' . OC_Util::generate_random_bytes(10);
  405. OC_Config::setValue('instanceid', $id);
  406. }
  407. return $id;
  408. }
  409. /**
  410. * @brief Static lifespan (in seconds) when a request token expires.
  411. * @see OC_Util::callRegister()
  412. * @see OC_Util::isCallRegistered()
  413. * @description
  414. * Also required for the client side to compute the piont in time when to
  415. * request a fresh token. The client will do so when nearly 97% of the
  416. * timespan coded here has expired.
  417. */
  418. public static $callLifespan = 3600; // 3600 secs = 1 hour
  419. /**
  420. * @brief Register an get/post call. Important to prevent CSRF attacks.
  421. * @todo Write howto: CSRF protection guide
  422. * @return $token Generated token.
  423. * @description
  424. * Creates a 'request token' (random) and stores it inside the session.
  425. * Ever subsequent (ajax) request must use such a valid token to succeed,
  426. * otherwise the request will be denied as a protection against CSRF.
  427. * The tokens expire after a fixed lifespan.
  428. * @see OC_Util::$callLifespan
  429. * @see OC_Util::isCallRegistered()
  430. */
  431. public static function callRegister() {
  432. // Check if a token exists
  433. if(!\OC::$session->exists('requesttoken')) {
  434. // No valid token found, generate a new one.
  435. $requestToken = self::generate_random_bytes(20);
  436. \OC::$session->set('requesttoken', $requestToken);
  437. } else {
  438. // Valid token already exists, send it
  439. $requestToken = \OC::$session->get('requesttoken');
  440. }
  441. return($requestToken);
  442. }
  443. /**
  444. * @brief Check an ajax get/post call if the request token is valid.
  445. * @return boolean False if request token is not set or is invalid.
  446. * @see OC_Util::$callLifespan
  447. * @see OC_Util::callRegister()
  448. */
  449. public static function isCallRegistered() {
  450. if(!\OC::$session->exists('requesttoken')) {
  451. return false;
  452. }
  453. if(isset($_GET['requesttoken'])) {
  454. $token=$_GET['requesttoken'];
  455. } elseif(isset($_POST['requesttoken'])) {
  456. $token=$_POST['requesttoken'];
  457. } elseif(isset($_SERVER['HTTP_REQUESTTOKEN'])) {
  458. $token=$_SERVER['HTTP_REQUESTTOKEN'];
  459. } else {
  460. //no token found.
  461. return false;
  462. }
  463. // Check if the token is valid
  464. if($token !== \OC::$session->get('requesttoken')) {
  465. // Not valid
  466. return false;
  467. } else {
  468. // Valid token
  469. return true;
  470. }
  471. }
  472. /**
  473. * @brief Check an ajax get/post call if the request token is valid. exit if not.
  474. * Todo: Write howto
  475. */
  476. public static function callCheck() {
  477. if(!OC_Util::isCallRegistered()) {
  478. exit;
  479. }
  480. }
  481. /**
  482. * @brief Public function to sanitize HTML
  483. *
  484. * This function is used to sanitize HTML and should be applied on any
  485. * string or array of strings before displaying it on a web page.
  486. *
  487. * @param string or array of strings
  488. * @return array with sanitized strings or a single sanitized string, depends on the input parameter.
  489. */
  490. public static function sanitizeHTML( &$value ) {
  491. if (is_array($value)) {
  492. array_walk_recursive($value, 'OC_Util::sanitizeHTML');
  493. } else {
  494. $value = htmlentities((string)$value, ENT_QUOTES, 'UTF-8'); //Specify encoding for PHP<5.4
  495. }
  496. return $value;
  497. }
  498. /**
  499. * @brief Public function to encode url parameters
  500. *
  501. * This function is used to encode path to file before output.
  502. * Encoding is done according to RFC 3986 with one exception:
  503. * Character '/' is preserved as is.
  504. *
  505. * @param string $component part of URI to encode
  506. * @return string
  507. */
  508. public static function encodePath($component) {
  509. $encoded = rawurlencode($component);
  510. $encoded = str_replace('%2F', '/', $encoded);
  511. return $encoded;
  512. }
  513. /**
  514. * Check if the htaccess file is working by creating a test file in the data directory and trying to access via http
  515. */
  516. public static function ishtaccessworking() {
  517. // testdata
  518. $filename='/htaccesstest.txt';
  519. $testcontent='testcontent';
  520. // creating a test file
  521. $testfile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$filename;
  522. if(file_exists($testfile)) {// already running this test, possible recursive call
  523. return false;
  524. }
  525. $fp = @fopen($testfile, 'w');
  526. @fwrite($fp, $testcontent);
  527. @fclose($fp);
  528. // accessing the file via http
  529. $url = OC_Helper::makeURLAbsolute(OC::$WEBROOT.'/data'.$filename);
  530. $fp = @fopen($url, 'r');
  531. $content=@fread($fp, 2048);
  532. @fclose($fp);
  533. // cleanup
  534. @unlink($testfile);
  535. // does it work ?
  536. if($content==$testcontent) {
  537. return(false);
  538. }else{
  539. return(true);
  540. }
  541. }
  542. /**
  543. * we test if webDAV is working properly
  544. *
  545. * The basic assumption is that if the server returns 401/Not Authenticated for an unauthenticated PROPFIND
  546. * the web server it self is setup properly.
  547. *
  548. * Why not an authenticated PROFIND and other verbs?
  549. * - We don't have the password available
  550. * - We have no idea about other auth methods implemented (e.g. OAuth with Bearer header)
  551. *
  552. */
  553. public static function isWebDAVWorking() {
  554. if (!function_exists('curl_init')) {
  555. return true;
  556. }
  557. $settings = array(
  558. 'baseUri' => OC_Helper::linkToRemote('webdav'),
  559. );
  560. // save the old timeout so that we can restore it later
  561. $old_timeout=ini_get("default_socket_timeout");
  562. // use a 5 sec timeout for the check. Should be enough for local requests.
  563. ini_set("default_socket_timeout", 5);
  564. $client = new \Sabre_DAV_Client($settings);
  565. // for this self test we don't care if the ssl certificate is self signed and the peer cannot be verified.
  566. $client->setVerifyPeer(false);
  567. $return = true;
  568. try {
  569. // test PROPFIND
  570. $client->propfind('', array('{DAV:}resourcetype'));
  571. } catch(\Sabre_DAV_Exception_NotAuthenticated $e) {
  572. $return = true;
  573. } catch(\Exception $e) {
  574. OC_Log::write('core', 'isWebDAVWorking: NO - Reason: '.$e->getMessage(). ' ('.get_class($e).')', OC_Log::WARN);
  575. $return = false;
  576. }
  577. // restore the original timeout
  578. ini_set("default_socket_timeout", $old_timeout);
  579. return $return;
  580. }
  581. /**
  582. * Check if the setlocal call doesn't work. This can happen if the right
  583. * local packages are not available on the server.
  584. */
  585. public static function issetlocaleworking() {
  586. // setlocale test is pointless on Windows
  587. if (OC_Util::runningOnWindows() ) {
  588. return true;
  589. }
  590. $result = setlocale(LC_ALL, 'en_US.UTF-8', 'en_US.UTF8');
  591. if($result == false) {
  592. return false;
  593. }
  594. return true;
  595. }
  596. /**
  597. * Check if the PHP module fileinfo is loaded.
  598. * @return bool
  599. */
  600. public static function fileInfoLoaded() {
  601. return function_exists('finfo_open');
  602. }
  603. /**
  604. * Check if the ownCloud server can connect to the internet
  605. */
  606. public static function isInternetConnectionWorking() {
  607. // in case there is no internet connection on purpose return false
  608. if (self::isInternetConnectionEnabled() === false) {
  609. return false;
  610. }
  611. // try to connect to owncloud.org to see if http connections to the internet are possible.
  612. $connected = @fsockopen("www.owncloud.org", 80);
  613. if ($connected) {
  614. fclose($connected);
  615. return true;
  616. }else{
  617. // second try in case one server is down
  618. $connected = @fsockopen("apps.owncloud.com", 80);
  619. if ($connected) {
  620. fclose($connected);
  621. return true;
  622. }else{
  623. return false;
  624. }
  625. }
  626. }
  627. /**
  628. * Check if the connection to the internet is disabled on purpose
  629. */
  630. public static function isInternetConnectionEnabled(){
  631. return \OC_Config::getValue("has_internet_connection", true);
  632. }
  633. /**
  634. * clear all levels of output buffering
  635. */
  636. public static function obEnd(){
  637. while (ob_get_level()) {
  638. ob_end_clean();
  639. }
  640. }
  641. /**
  642. * @brief Generates a cryptographical secure pseudorandom string
  643. * @param Int with the length of the random string
  644. * @return String
  645. * Please also update secureRNG_available if you change something here
  646. */
  647. public static function generate_random_bytes($length = 30) {
  648. // Try to use openssl_random_pseudo_bytes
  649. if(function_exists('openssl_random_pseudo_bytes')) {
  650. $pseudo_byte = bin2hex(openssl_random_pseudo_bytes($length, $strong));
  651. if($strong == true) {
  652. return substr($pseudo_byte, 0, $length); // Truncate it to match the length
  653. }
  654. }
  655. // Try to use /dev/urandom
  656. $fp = @file_get_contents('/dev/urandom', false, null, 0, $length);
  657. if ($fp !== false) {
  658. $string = substr(bin2hex($fp), 0, $length);
  659. return $string;
  660. }
  661. // Fallback to mt_rand()
  662. $characters = '0123456789';
  663. $characters .= 'abcdefghijklmnopqrstuvwxyz';
  664. $charactersLength = strlen($characters)-1;
  665. $pseudo_byte = "";
  666. // Select some random characters
  667. for ($i = 0; $i < $length; $i++) {
  668. $pseudo_byte .= $characters[mt_rand(0, $charactersLength)];
  669. }
  670. return $pseudo_byte;
  671. }
  672. /**
  673. * @brief Checks if a secure random number generator is available
  674. * @return bool
  675. */
  676. public static function secureRNG_available() {
  677. // Check openssl_random_pseudo_bytes
  678. if(function_exists('openssl_random_pseudo_bytes')) {
  679. openssl_random_pseudo_bytes(1, $strong);
  680. if($strong == true) {
  681. return true;
  682. }
  683. }
  684. // Check /dev/urandom
  685. $fp = @file_get_contents('/dev/urandom', false, null, 0, 1);
  686. if ($fp !== false) {
  687. return true;
  688. }
  689. return false;
  690. }
  691. /**
  692. * @Brief Get file content via curl.
  693. * @param string $url Url to get content
  694. * @return string of the response or false on error
  695. * This function get the content of a page via curl, if curl is enabled.
  696. * If not, file_get_element is used.
  697. */
  698. public static function getUrlContent($url){
  699. if (function_exists('curl_init')) {
  700. $curl = curl_init();
  701. curl_setopt($curl, CURLOPT_HEADER, 0);
  702. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  703. curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
  704. curl_setopt($curl, CURLOPT_URL, $url);
  705. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  706. curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
  707. curl_setopt($curl, CURLOPT_USERAGENT, "ownCloud Server Crawler");
  708. if(OC_Config::getValue('proxy', '')<>'') {
  709. curl_setopt($curl, CURLOPT_PROXY, OC_Config::getValue('proxy'));
  710. }
  711. if(OC_Config::getValue('proxyuserpwd', '')<>'') {
  712. curl_setopt($curl, CURLOPT_PROXYUSERPWD, OC_Config::getValue('proxyuserpwd'));
  713. }
  714. $data = curl_exec($curl);
  715. curl_close($curl);
  716. } else {
  717. $contextArray = null;
  718. if(OC_Config::getValue('proxy', '')<>'') {
  719. $contextArray = array(
  720. 'http' => array(
  721. 'timeout' => 10,
  722. 'proxy' => OC_Config::getValue('proxy')
  723. )
  724. );
  725. } else {
  726. $contextArray = array(
  727. 'http' => array(
  728. 'timeout' => 10
  729. )
  730. );
  731. }
  732. $ctx = stream_context_create(
  733. $contextArray
  734. );
  735. $data=@file_get_contents($url, 0, $ctx);
  736. }
  737. return $data;
  738. }
  739. /**
  740. * @return bool - well are we running on windows or not
  741. */
  742. public static function runningOnWindows() {
  743. return (substr(PHP_OS, 0, 3) === "WIN");
  744. }
  745. /**
  746. * Handles the case that there may not be a theme, then check if a "default"
  747. * theme exists and take that one
  748. * @return string the theme
  749. */
  750. public static function getTheme() {
  751. $theme = OC_Config::getValue("theme", '');
  752. if($theme === '') {
  753. if(is_dir(OC::$SERVERROOT . '/themes/default')) {
  754. $theme = 'default';
  755. }
  756. }
  757. return $theme;
  758. }
  759. /**
  760. * Clear the opcode cache if one exists
  761. * This is necessary for writing to the config file
  762. * in case the opcode cache doesn't revalidate files
  763. */
  764. public static function clearOpcodeCache() {
  765. // APC
  766. if (function_exists('apc_clear_cache')) {
  767. apc_clear_cache();
  768. }
  769. // Zend Opcache
  770. if (function_exists('accelerator_reset')) {
  771. accelerator_reset();
  772. }
  773. // XCache
  774. if (function_exists('xcache_clear_cache')) {
  775. xcache_clear_cache(XC_TYPE_VAR, 0);
  776. }
  777. }
  778. /**
  779. * Normalize a unicode string
  780. * @param string $value a not normalized string
  781. * @return bool|string
  782. */
  783. public static function normalizeUnicode($value) {
  784. if(class_exists('Patchwork\PHP\Shim\Normalizer')) {
  785. $normalizedValue = \Patchwork\PHP\Shim\Normalizer::normalize($value);
  786. if($normalizedValue === false) {
  787. \OC_Log::write( 'core', 'normalizing failed for "' . $value . '"', \OC_Log::WARN);
  788. } else {
  789. $value = $normalizedValue;
  790. }
  791. }
  792. return $value;
  793. }
  794. }