util.php 27 KB

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