You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

base.php 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. <?php
  2. /**
  3. * ownCloud
  4. *
  5. * @author Frank Karlitschek
  6. * @copyright 2012 Frank Karlitschek frank@owncloud.org
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  10. * License as published by the Free Software Foundation; either
  11. * version 3 of the License, or any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public
  19. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. require_once 'public/constants.php';
  23. /**
  24. * Class that is a namespace for all global OC variables
  25. * No, we can not put this class in its own file because it is used by
  26. * OC_autoload!
  27. */
  28. class OC {
  29. /**
  30. * Associative array for autoloading. classname => filename
  31. */
  32. public static $CLASSPATH = array();
  33. /**
  34. * The installation path for owncloud on the server (e.g. /srv/http/owncloud)
  35. */
  36. public static $SERVERROOT = '';
  37. /**
  38. * the current request path relative to the owncloud root (e.g. files/index.php)
  39. */
  40. private static $SUBURI = '';
  41. /**
  42. * the owncloud root path for http requests (e.g. owncloud/)
  43. */
  44. public static $WEBROOT = '';
  45. /**
  46. * The installation path of the 3rdparty folder on the server (e.g. /srv/http/owncloud/3rdparty)
  47. */
  48. public static $THIRDPARTYROOT = '';
  49. /**
  50. * the root path of the 3rdparty folder for http requests (e.g. owncloud/3rdparty)
  51. */
  52. public static $THIRDPARTYWEBROOT = '';
  53. /**
  54. * The installation path array of the apps folder on the server (e.g. /srv/http/owncloud) 'path' and
  55. * web path in 'url'
  56. */
  57. public static $APPSROOTS = array();
  58. /*
  59. * requested app
  60. */
  61. public static $REQUESTEDAPP = '';
  62. /*
  63. * requested file of app
  64. */
  65. public static $REQUESTEDFILE = '';
  66. /**
  67. * check if owncloud runs in cli mode
  68. */
  69. public static $CLI = false;
  70. /*
  71. * OC router
  72. */
  73. protected static $router = null;
  74. /**
  75. * SPL autoload
  76. */
  77. public static function autoload($className) {
  78. $className = trim($className, '\\');
  79. if (array_key_exists($className, OC::$CLASSPATH)) {
  80. $path = OC::$CLASSPATH[$className];
  81. /** @TODO: Remove this when necessary
  82. Remove "apps/" from inclusion path for smooth migration to mutli app dir
  83. */
  84. if (strpos($path, 'apps/') === 0) {
  85. OC_Log::write('core', 'include path for class "' . $className . '" starts with "apps/"', OC_Log::DEBUG);
  86. $path = str_replace('apps/', '', $path);
  87. }
  88. } elseif (strpos($className, 'OC_') === 0) {
  89. $path = strtolower(str_replace('_', '/', substr($className, 3)) . '.php');
  90. } elseif (strpos($className, 'OC\\') === 0) {
  91. $path = strtolower(str_replace('\\', '/', substr($className, 3)) . '.php');
  92. } elseif (strpos($className, 'OCP\\') === 0) {
  93. $path = 'public/' . strtolower(str_replace('\\', '/', substr($className, 3)) . '.php');
  94. } elseif (strpos($className, 'OCA\\') === 0) {
  95. foreach (self::$APPSROOTS as $appDir) {
  96. $path = $appDir['path'] . '/' . strtolower(str_replace('\\', '/', substr($className, 3)) . '.php');
  97. $fullPath = stream_resolve_include_path($path);
  98. if (file_exists($fullPath)) {
  99. require_once $fullPath;
  100. return false;
  101. }
  102. }
  103. } elseif (strpos($className, 'Sabre_') === 0) {
  104. $path = str_replace('_', '/', $className) . '.php';
  105. } elseif (strpos($className, 'Symfony\\Component\\Routing\\') === 0) {
  106. $path = 'symfony/routing/' . str_replace('\\', '/', $className) . '.php';
  107. } elseif (strpos($className, 'Sabre\\VObject') === 0) {
  108. $path = str_replace('\\', '/', $className) . '.php';
  109. } elseif (strpos($className, 'Test_') === 0) {
  110. $path = 'tests/lib/' . strtolower(str_replace('_', '/', substr($className, 5)) . '.php');
  111. } elseif (strpos($className, 'Test\\') === 0) {
  112. $path = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($className, 5)) . '.php');
  113. } else {
  114. return false;
  115. }
  116. if ($fullPath = stream_resolve_include_path($path)) {
  117. require_once $fullPath;
  118. }
  119. return false;
  120. }
  121. public static function initPaths() {
  122. // calculate the root directories
  123. OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
  124. // ensure we can find OC_Config
  125. set_include_path(
  126. OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
  127. get_include_path()
  128. );
  129. OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
  130. $scriptName = OC_Request::scriptName();
  131. if (substr($scriptName, -1) == '/') {
  132. $scriptName .= 'index.php';
  133. //make sure suburi follows the same rules as scriptName
  134. if (substr(OC::$SUBURI, -9) != 'index.php') {
  135. if (substr(OC::$SUBURI, -1) != '/') {
  136. OC::$SUBURI = OC::$SUBURI . '/';
  137. }
  138. OC::$SUBURI = OC::$SUBURI . 'index.php';
  139. }
  140. }
  141. OC::$WEBROOT = substr($scriptName, 0, strlen($scriptName) - strlen(OC::$SUBURI));
  142. if (OC::$WEBROOT != '' and OC::$WEBROOT[0] !== '/') {
  143. OC::$WEBROOT = '/' . OC::$WEBROOT;
  144. }
  145. // search the 3rdparty folder
  146. if (OC_Config::getValue('3rdpartyroot', '') <> '' and OC_Config::getValue('3rdpartyurl', '') <> '') {
  147. OC::$THIRDPARTYROOT = OC_Config::getValue('3rdpartyroot', '');
  148. OC::$THIRDPARTYWEBROOT = OC_Config::getValue('3rdpartyurl', '');
  149. } elseif (file_exists(OC::$SERVERROOT . '/3rdparty')) {
  150. OC::$THIRDPARTYROOT = OC::$SERVERROOT;
  151. OC::$THIRDPARTYWEBROOT = OC::$WEBROOT;
  152. } elseif (file_exists(OC::$SERVERROOT . '/../3rdparty')) {
  153. OC::$THIRDPARTYWEBROOT = rtrim(dirname(OC::$WEBROOT), '/');
  154. OC::$THIRDPARTYROOT = rtrim(dirname(OC::$SERVERROOT), '/');
  155. } else {
  156. echo('3rdparty directory not found! Please put the ownCloud 3rdparty'
  157. .' folder in the ownCloud folder or the folder above.'
  158. .' You can also configure the location in the config.php file.');
  159. exit;
  160. }
  161. // search the apps folder
  162. $config_paths = OC_Config::getValue('apps_paths', array());
  163. if (!empty($config_paths)) {
  164. foreach ($config_paths as $paths) {
  165. if (isset($paths['url']) && isset($paths['path'])) {
  166. $paths['url'] = rtrim($paths['url'], '/');
  167. $paths['path'] = rtrim($paths['path'], '/');
  168. OC::$APPSROOTS[] = $paths;
  169. }
  170. }
  171. } elseif (file_exists(OC::$SERVERROOT . '/apps')) {
  172. OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
  173. } elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
  174. OC::$APPSROOTS[] = array(
  175. 'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
  176. 'url' => '/apps',
  177. 'writable' => true
  178. );
  179. }
  180. if (empty(OC::$APPSROOTS)) {
  181. echo('apps directory not found! Please put the ownCloud apps folder in the ownCloud folder'
  182. .' or the folder above. You can also configure the location in the config.php file.');
  183. exit;
  184. }
  185. $paths = array();
  186. foreach (OC::$APPSROOTS as $path) {
  187. $paths[] = $path['path'];
  188. }
  189. // set the right include path
  190. set_include_path(
  191. OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
  192. OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
  193. OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
  194. implode($paths, PATH_SEPARATOR) . PATH_SEPARATOR .
  195. get_include_path() . PATH_SEPARATOR .
  196. OC::$SERVERROOT
  197. );
  198. }
  199. public static function checkConfig() {
  200. if (file_exists(OC::$SERVERROOT . "/config/config.php")
  201. and !is_writable(OC::$SERVERROOT . "/config/config.php")) {
  202. $tmpl = new OC_Template('', 'error', 'guest');
  203. $tmpl->assign('errors', array(1 => array(
  204. 'error' => "Can't write into config directory 'config'",
  205. 'hint' => 'You can usually fix this by giving the webserver user write access'
  206. .' to the config directory in owncloud'
  207. )));
  208. $tmpl->printPage();
  209. exit();
  210. }
  211. }
  212. public static function checkInstalled() {
  213. // Redirect to installer if not installed
  214. if (!OC_Config::getValue('installed', false) && OC::$SUBURI != '/index.php') {
  215. if (!OC::$CLI) {
  216. $url = 'http://' . $_SERVER['SERVER_NAME'] . OC::$WEBROOT . '/index.php';
  217. header("Location: $url");
  218. }
  219. exit();
  220. }
  221. }
  222. public static function checkSSL() {
  223. // redirect to https site if configured
  224. if (OC_Config::getValue("forcessl", false)) {
  225. header('Strict-Transport-Security: max-age=31536000');
  226. ini_set("session.cookie_secure", "on");
  227. if (OC_Request::serverProtocol() <> 'https' and !OC::$CLI) {
  228. $url = "https://" . OC_Request::serverHost() . OC_Request::requestUri();
  229. header("Location: $url");
  230. exit();
  231. }
  232. } else {
  233. // Invalidate HSTS headers
  234. if (OC_Request::serverProtocol() === 'https') {
  235. header('Strict-Transport-Security: max-age=0');
  236. }
  237. }
  238. }
  239. public static function checkMaintenanceMode() {
  240. // Allow ajax update script to execute without being stopped
  241. if (OC_Config::getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
  242. // send http status 503
  243. header('HTTP/1.1 503 Service Temporarily Unavailable');
  244. header('Status: 503 Service Temporarily Unavailable');
  245. header('Retry-After: 120');
  246. // render error page
  247. $tmpl = new OC_Template('', 'error', 'guest');
  248. $tmpl->assign('errors', array(1 => array('error' => 'ownCloud is in maintenance mode')));
  249. $tmpl->printPage();
  250. exit();
  251. }
  252. }
  253. public static function checkUpgrade($showTemplate = true) {
  254. if (OC_Config::getValue('installed', false)) {
  255. $installedVersion = OC_Config::getValue('version', '0.0.0');
  256. $currentVersion = implode('.', OC_Util::getVersion());
  257. if (version_compare($currentVersion, $installedVersion, '>')) {
  258. if ($showTemplate && !OC_Config::getValue('maintenance', false)) {
  259. OC_Config::setValue('maintenance', true);
  260. OC_Log::write('core',
  261. 'starting upgrade from ' . $installedVersion . ' to ' . $currentVersion,
  262. OC_Log::WARN);
  263. $minimizerCSS = new OC_Minimizer_CSS();
  264. $minimizerCSS->clearCache();
  265. $minimizerJS = new OC_Minimizer_JS();
  266. $minimizerJS->clearCache();
  267. OC_Util::addscript('update');
  268. $tmpl = new OC_Template('', 'update', 'guest');
  269. $tmpl->assign('version', OC_Util::getVersionString());
  270. $tmpl->printPage();
  271. exit();
  272. } else {
  273. return true;
  274. }
  275. }
  276. return false;
  277. }
  278. }
  279. public static function initTemplateEngine() {
  280. // Add the stuff we need always
  281. OC_Util::addScript("jquery-1.7.2.min");
  282. OC_Util::addScript("jquery-ui-1.10.0.custom");
  283. OC_Util::addScript("jquery-showpassword");
  284. OC_Util::addScript("jquery.infieldlabel");
  285. OC_Util::addScript("jquery-tipsy");
  286. OC_Util::addScript("compatibility");
  287. OC_Util::addScript("oc-dialogs");
  288. OC_Util::addScript("js");
  289. OC_Util::addScript("eventsource");
  290. OC_Util::addScript("config");
  291. //OC_Util::addScript( "multiselect" );
  292. OC_Util::addScript('search', 'result');
  293. OC_Util::addScript('router');
  294. OC_Util::addStyle("styles");
  295. OC_Util::addStyle("multiselect");
  296. OC_Util::addStyle("jquery-ui-1.10.0.custom");
  297. OC_Util::addStyle("jquery-tipsy");
  298. OC_Util::addScript("oc-requesttoken");
  299. }
  300. public static function initSession() {
  301. // prevents javascript from accessing php session cookies
  302. ini_set('session.cookie_httponly', '1;');
  303. // set the cookie path to the ownCloud directory
  304. $cookie_path = OC::$WEBROOT ?: '/';
  305. ini_set('session.cookie_path', $cookie_path);
  306. // set the session name to the instance id - which is unique
  307. session_name(OC_Util::getInstanceId());
  308. // if session cant be started break with http 500 error
  309. if (session_start() === false){
  310. OC_Log::write('core', 'Session could not be initialized',
  311. OC_Log::ERROR);
  312. header('HTTP/1.1 500 Internal Server Error');
  313. OC_Util::addStyle("styles");
  314. $error = 'Session could not be initialized. Please contact your ';
  315. $error .= 'system administrator';
  316. $tmpl = new OC_Template('', 'error', 'guest');
  317. $tmpl->assign('errors', array(1 => array('error' => $error)));
  318. $tmpl->printPage();
  319. exit();
  320. }
  321. // regenerate session id periodically to avoid session fixation
  322. if (!isset($_SESSION['SID_CREATED'])) {
  323. $_SESSION['SID_CREATED'] = time();
  324. } else if (time() - $_SESSION['SID_CREATED'] > 60*60*12) {
  325. session_regenerate_id(true);
  326. $_SESSION['SID_CREATED'] = time();
  327. }
  328. // session timeout
  329. if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 60*60*24)) {
  330. if (isset($_COOKIE[session_name()])) {
  331. setcookie(session_name(), '', time() - 42000, $cookie_path);
  332. }
  333. session_unset();
  334. session_destroy();
  335. session_start();
  336. }
  337. $_SESSION['LAST_ACTIVITY'] = time();
  338. }
  339. public static function getRouter() {
  340. if (!isset(OC::$router)) {
  341. OC::$router = new OC_Router();
  342. OC::$router->loadRoutes();
  343. }
  344. return OC::$router;
  345. }
  346. public static function loadAppClassPaths() {
  347. foreach (OC_APP::getEnabledApps() as $app) {
  348. $file = OC_App::getAppPath($app) . '/appinfo/classpath.php';
  349. if (file_exists($file)) {
  350. require_once $file;
  351. }
  352. }
  353. }
  354. public static function init() {
  355. // register autoloader
  356. spl_autoload_register(array('OC', 'autoload'));
  357. OC_Util::issetlocaleworking();
  358. // set some stuff
  359. //ob_start();
  360. error_reporting(E_ALL | E_STRICT);
  361. if (defined('DEBUG') && DEBUG) {
  362. ini_set('display_errors', 1);
  363. }
  364. self::$CLI = (php_sapi_name() == 'cli');
  365. date_default_timezone_set('UTC');
  366. ini_set('arg_separator.output', '&amp;');
  367. // try to switch magic quotes off.
  368. if (get_magic_quotes_gpc()==1) {
  369. ini_set('magic_quotes_runtime', 0);
  370. }
  371. //try to configure php to enable big file uploads.
  372. //this doesn´t work always depending on the webserver and php configuration.
  373. //Let´s try to overwrite some defaults anyways
  374. //try to set the maximum execution time to 60min
  375. @set_time_limit(3600);
  376. @ini_set('max_execution_time', 3600);
  377. @ini_set('max_input_time', 3600);
  378. //try to set the maximum filesize to 10G
  379. @ini_set('upload_max_filesize', '10G');
  380. @ini_set('post_max_size', '10G');
  381. @ini_set('file_uploads', '50');
  382. //try to set the session lifetime to 60min
  383. @ini_set('gc_maxlifetime', '3600');
  384. //copy http auth headers for apache+php-fcgid work around
  385. if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
  386. $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
  387. }
  388. //set http auth headers for apache+php-cgi work around
  389. if (isset($_SERVER['HTTP_AUTHORIZATION'])
  390. && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
  391. list($name, $password) = explode(':', base64_decode($matches[1]), 2);
  392. $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
  393. $_SERVER['PHP_AUTH_PW'] = strip_tags($password);
  394. }
  395. //set http auth headers for apache+php-cgi work around if variable gets renamed by apache
  396. if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])
  397. && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) {
  398. list($name, $password) = explode(':', base64_decode($matches[1]), 2);
  399. $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
  400. $_SERVER['PHP_AUTH_PW'] = strip_tags($password);
  401. }
  402. self::initPaths();
  403. // set debug mode if an xdebug session is active
  404. if (!defined('DEBUG') || !DEBUG) {
  405. if (isset($_COOKIE['XDEBUG_SESSION'])) {
  406. define('DEBUG', true);
  407. }
  408. }
  409. if (!defined('PHPUNIT_RUN') and !(defined('DEBUG') and DEBUG)) {
  410. register_shutdown_function(array('OC_Log', 'onShutdown'));
  411. set_error_handler(array('OC_Log', 'onError'));
  412. set_exception_handler(array('OC_Log', 'onException'));
  413. }
  414. // register the stream wrappers
  415. stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
  416. stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
  417. stream_wrapper_register('close', 'OC\Files\Stream\Close');
  418. stream_wrapper_register('oc', 'OC\Files\Stream\OC');
  419. self::checkConfig();
  420. self::checkInstalled();
  421. self::checkSSL();
  422. self::initSession();
  423. self::initTemplateEngine();
  424. $errors = OC_Util::checkServer();
  425. if (count($errors) > 0) {
  426. OC_Template::printGuestPage('', 'error', array('errors' => $errors));
  427. exit;
  428. }
  429. // User and Groups
  430. if (!OC_Config::getValue("installed", false)) {
  431. $_SESSION['user_id'] = '';
  432. }
  433. OC_User::useBackend(new OC_User_Database());
  434. OC_Group::useBackend(new OC_Group_Database());
  435. if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SESSION['user_id'])
  436. && $_SERVER['PHP_AUTH_USER'] != $_SESSION['user_id']) {
  437. OC_User::logout();
  438. }
  439. // Load Apps
  440. // This includes plugins for users and filesystems as well
  441. global $RUNTIME_NOAPPS;
  442. global $RUNTIME_APPTYPES;
  443. if (!$RUNTIME_NOAPPS) {
  444. if ($RUNTIME_APPTYPES) {
  445. OC_App::loadApps($RUNTIME_APPTYPES);
  446. } else {
  447. OC_App::loadApps();
  448. }
  449. }
  450. //setup extra user backends
  451. OC_User::setupBackends();
  452. self::registerCacheHooks();
  453. self::registerFilesystemHooks();
  454. self::registerShareHooks();
  455. //make sure temporary files are cleaned up
  456. register_shutdown_function(array('OC_Helper', 'cleanTmp'));
  457. //parse the given parameters
  458. self::$REQUESTEDAPP = (isset($_GET['app']) && trim($_GET['app']) != '' && !is_null($_GET['app']) ? OC_App::cleanAppId(strip_tags($_GET['app'])) : OC_Config::getValue('defaultapp', 'files'));
  459. if (substr_count(self::$REQUESTEDAPP, '?') != 0) {
  460. $app = substr(self::$REQUESTEDAPP, 0, strpos(self::$REQUESTEDAPP, '?'));
  461. $param = substr($_GET['app'], strpos($_GET['app'], '?') + 1);
  462. parse_str($param, $get);
  463. $_GET = array_merge($_GET, $get);
  464. self::$REQUESTEDAPP = $app;
  465. $_GET['app'] = $app;
  466. }
  467. self::$REQUESTEDFILE = (isset($_GET['getfile']) ? $_GET['getfile'] : null);
  468. if (substr_count(self::$REQUESTEDFILE, '?') != 0) {
  469. $file = substr(self::$REQUESTEDFILE, 0, strpos(self::$REQUESTEDFILE, '?'));
  470. $param = substr(self::$REQUESTEDFILE, strpos(self::$REQUESTEDFILE, '?') + 1);
  471. parse_str($param, $get);
  472. $_GET = array_merge($_GET, $get);
  473. self::$REQUESTEDFILE = $file;
  474. $_GET['getfile'] = $file;
  475. }
  476. if (!is_null(self::$REQUESTEDFILE)) {
  477. $subdir = OC_App::getAppPath(OC::$REQUESTEDAPP) . '/' . self::$REQUESTEDFILE;
  478. $parent = OC_App::getAppPath(OC::$REQUESTEDAPP);
  479. if (!OC_Helper::issubdirectory($subdir, $parent)) {
  480. self::$REQUESTEDFILE = null;
  481. header('HTTP/1.0 404 Not Found');
  482. exit;
  483. }
  484. }
  485. // write error into log if locale can't be set
  486. if (OC_Util::issetlocaleworking() == false) {
  487. OC_Log::write('core',
  488. 'setting locale to en_US.UTF-8/en_US.UTF8 failed. Support is probably not installed on your system',
  489. OC_Log::ERROR);
  490. }
  491. if (OC_Config::getValue('installed', false) && !self::checkUpgrade(false)) {
  492. if (OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
  493. OC_Util::addScript('backgroundjobs');
  494. }
  495. }
  496. }
  497. /**
  498. * register hooks for the cache
  499. */
  500. public static function registerCacheHooks() {
  501. // register cache cleanup jobs
  502. OC_BackgroundJob_RegularTask::register('OC_Cache_FileGlobal', 'gc');
  503. OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener');
  504. }
  505. /**
  506. * register hooks for the filesystem
  507. */
  508. public static function registerFilesystemHooks() {
  509. // Check for blacklisted files
  510. OC_Hook::connect('OC_Filesystem', 'write', 'OC_Filesystem', 'isBlacklisted');
  511. OC_Hook::connect('OC_Filesystem', 'rename', 'OC_Filesystem', 'isBlacklisted');
  512. }
  513. /**
  514. * register hooks for sharing
  515. */
  516. public static function registerShareHooks() {
  517. OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser');
  518. OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup');
  519. OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup');
  520. OC_Hook::connect('OC_User', 'post_deleteGroup', 'OCP\Share', 'post_deleteGroup');
  521. }
  522. /**
  523. * @brief Handle the request
  524. */
  525. public static function handleRequest() {
  526. // load all the classpaths from the enabled apps so they are available
  527. // in the routing files of each app
  528. OC::loadAppClassPaths();
  529. // Check if ownCloud is installed or in maintenance (update) mode
  530. if (!OC_Config::getValue('installed', false)) {
  531. require_once 'core/setup.php';
  532. exit();
  533. }
  534. $request = OC_Request::getPathInfo();
  535. if(substr($request, -3) !== '.js') {// we need these files during the upgrade
  536. self::checkMaintenanceMode();
  537. self::checkUpgrade();
  538. }
  539. if (!self::$CLI) {
  540. try {
  541. if (!OC_Config::getValue('maintenance', false)) {
  542. OC_App::loadApps();
  543. }
  544. OC::getRouter()->match(OC_Request::getRawPathInfo());
  545. return;
  546. } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
  547. //header('HTTP/1.0 404 Not Found');
  548. } catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
  549. OC_Response::setStatus(405);
  550. return;
  551. }
  552. }
  553. $app = OC::$REQUESTEDAPP;
  554. $file = OC::$REQUESTEDFILE;
  555. $param = array('app' => $app, 'file' => $file);
  556. // Handle app css files
  557. if (substr($file, -3) == 'css') {
  558. self::loadCSSFile($param);
  559. return;
  560. }
  561. // Handle redirect URL for logged in users
  562. if (isset($_REQUEST['redirect_url']) && OC_User::isLoggedIn()) {
  563. $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url']));
  564. header('Location: ' . $location);
  565. return;
  566. }
  567. // Handle WebDAV
  568. if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
  569. header('location: ' . OC_Helper::linkToRemote('webdav'));
  570. return;
  571. }
  572. // Someone is logged in :
  573. if (OC_User::isLoggedIn()) {
  574. OC_App::loadApps();
  575. OC_User::setupBackends();
  576. if (isset($_GET["logout"]) and ($_GET["logout"])) {
  577. if (isset($_COOKIE['oc_token'])) {
  578. OC_Preferences::deleteKey(OC_User::getUser(), 'login_token', $_COOKIE['oc_token']);
  579. }
  580. OC_User::logout();
  581. header("Location: " . OC::$WEBROOT . '/');
  582. } else {
  583. if (is_null($file)) {
  584. $param['file'] = 'index.php';
  585. }
  586. $file_ext = substr($param['file'], -3);
  587. if ($file_ext != 'php'
  588. || !self::loadAppScriptFile($param)
  589. ) {
  590. header('HTTP/1.0 404 Not Found');
  591. }
  592. }
  593. return;
  594. }
  595. // Not handled and not logged in
  596. self::handleLogin();
  597. }
  598. public static function loadAppScriptFile($param) {
  599. OC_App::loadApps();
  600. $app = $param['app'];
  601. $file = $param['file'];
  602. $app_path = OC_App::getAppPath($app);
  603. $file = $app_path . '/' . $file;
  604. unset($app, $app_path);
  605. if (file_exists($file)) {
  606. require_once $file;
  607. return true;
  608. }
  609. return false;
  610. }
  611. public static function loadCSSFile($param) {
  612. $app = $param['app'];
  613. $file = $param['file'];
  614. $app_path = OC_App::getAppPath($app);
  615. if (file_exists($app_path . '/' . $file)) {
  616. $app_web_path = OC_App::getAppWebPath($app);
  617. $filepath = $app_web_path . '/' . $file;
  618. $minimizer = new OC_Minimizer_CSS();
  619. $info = array($app_path, $app_web_path, $file);
  620. $minimizer->output(array($info), $filepath);
  621. }
  622. }
  623. protected static function handleLogin() {
  624. OC_App::loadApps(array('prelogin'));
  625. $error = array();
  626. // remember was checked after last login
  627. if (OC::tryRememberLogin()) {
  628. $error[] = 'invalidcookie';
  629. // Someone wants to log in :
  630. } elseif (OC::tryFormLogin()) {
  631. $error[] = 'invalidpassword';
  632. // The user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP
  633. } elseif (OC::tryBasicAuthLogin()) {
  634. $error[] = 'invalidpassword';
  635. }
  636. OC_Util::displayLoginPage(array_unique($error));
  637. }
  638. protected static function cleanupLoginTokens($user) {
  639. $cutoff = time() - OC_Config::getValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
  640. $tokens = OC_Preferences::getKeys($user, 'login_token');
  641. foreach ($tokens as $token) {
  642. $time = OC_Preferences::getValue($user, 'login_token', $token);
  643. if ($time < $cutoff) {
  644. OC_Preferences::deleteKey($user, 'login_token', $token);
  645. }
  646. }
  647. }
  648. protected static function tryRememberLogin() {
  649. if (!isset($_COOKIE["oc_remember_login"])
  650. || !isset($_COOKIE["oc_token"])
  651. || !isset($_COOKIE["oc_username"])
  652. || !$_COOKIE["oc_remember_login"]
  653. ) {
  654. return false;
  655. }
  656. OC_App::loadApps(array('authentication'));
  657. if (defined("DEBUG") && DEBUG) {
  658. OC_Log::write('core', 'Trying to login from cookie', OC_Log::DEBUG);
  659. }
  660. // confirm credentials in cookie
  661. if (isset($_COOKIE['oc_token']) && OC_User::userExists($_COOKIE['oc_username'])) {
  662. // delete outdated cookies
  663. self::cleanupLoginTokens($_COOKIE['oc_username']);
  664. // get stored tokens
  665. $tokens = OC_Preferences::getKeys($_COOKIE['oc_username'], 'login_token');
  666. // test cookies token against stored tokens
  667. if (in_array($_COOKIE['oc_token'], $tokens, true)) {
  668. // replace successfully used token with a new one
  669. OC_Preferences::deleteKey($_COOKIE['oc_username'], 'login_token', $_COOKIE['oc_token']);
  670. $token = OC_Util::generate_random_bytes(32);
  671. OC_Preferences::setValue($_COOKIE['oc_username'], 'login_token', $token, time());
  672. OC_User::setMagicInCookie($_COOKIE['oc_username'], $token);
  673. // login
  674. OC_User::setUserId($_COOKIE['oc_username']);
  675. OC_Util::redirectToDefaultPage();
  676. // doesn't return
  677. }
  678. // if you reach this point you have changed your password
  679. // or you are an attacker
  680. // we can not delete tokens here because users may reach
  681. // this point multiple times after a password change
  682. OC_Log::write('core', 'Authentication cookie rejected for user ' . $_COOKIE['oc_username'], OC_Log::WARN);
  683. }
  684. OC_User::unsetMagicInCookie();
  685. return true;
  686. }
  687. protected static function tryFormLogin() {
  688. if (!isset($_POST["user"]) || !isset($_POST['password'])) {
  689. return false;
  690. }
  691. OC_App::loadApps();
  692. //setup extra user backends
  693. OC_User::setupBackends();
  694. if (OC_User::login($_POST["user"], $_POST["password"])) {
  695. // setting up the time zone
  696. if (isset($_POST['timezone-offset'])) {
  697. $_SESSION['timezone'] = $_POST['timezone-offset'];
  698. }
  699. self::cleanupLoginTokens($_POST['user']);
  700. if (!empty($_POST["remember_login"])) {
  701. if (defined("DEBUG") && DEBUG) {
  702. OC_Log::write('core', 'Setting remember login to cookie', OC_Log::DEBUG);
  703. }
  704. $token = OC_Util::generate_random_bytes(32);
  705. OC_Preferences::setValue($_POST['user'], 'login_token', $token, time());
  706. OC_User::setMagicInCookie($_POST["user"], $token);
  707. } else {
  708. OC_User::unsetMagicInCookie();
  709. }
  710. OC_Util::redirectToDefaultPage();
  711. exit();
  712. }
  713. return true;
  714. }
  715. protected static function tryBasicAuthLogin() {
  716. if (!isset($_SERVER["PHP_AUTH_USER"])
  717. || !isset($_SERVER["PHP_AUTH_PW"])
  718. ) {
  719. return false;
  720. }
  721. OC_App::loadApps(array('authentication'));
  722. if (OC_User::login($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"])) {
  723. //OC_Log::write('core',"Logged in with HTTP Authentication", OC_Log::DEBUG);
  724. OC_User::unsetMagicInCookie();
  725. $_REQUEST['redirect_url'] = OC_Request::requestUri();
  726. OC_Util::redirectToDefaultPage();
  727. }
  728. return true;
  729. }
  730. }
  731. // define runtime variables - unless this already has been done
  732. if (!isset($RUNTIME_NOAPPS)) {
  733. $RUNTIME_NOAPPS = false;
  734. }
  735. if (!function_exists('get_temp_dir')) {
  736. function get_temp_dir() {
  737. if ($temp = ini_get('upload_tmp_dir')) return $temp;
  738. if ($temp = getenv('TMP')) return $temp;
  739. if ($temp = getenv('TEMP')) return $temp;
  740. if ($temp = getenv('TMPDIR')) return $temp;
  741. $temp = tempnam(__FILE__, '');
  742. if (file_exists($temp)) {
  743. unlink($temp);
  744. return dirname($temp);
  745. }
  746. if ($temp = sys_get_temp_dir()) return $temp;
  747. return null;
  748. }
  749. }
  750. OC::init();