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 28KB

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