Completed
Pull Request — stable9 (#203)
by
unknown
10:16
created

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @author Bernhard Posselt <[email protected]>
4
 * @author Christopher Schäpers <[email protected]>
5
 * @author Jakob Sack <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Jörn Friedrich Dreyer <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Oliver Kohl D.Sc. <[email protected]>
10
 * @author Phil Davis <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Steffen Lindner <[email protected]>
13
 * @author Thomas Müller <[email protected]>
14
 * @author Vincent Petry <[email protected]>
15
 *
16
 * @copyright Copyright (c) 2016, ownCloud, Inc.
17
 * @license AGPL-3.0
18
 *
19
 * This code is free software: you can redistribute it and/or modify
20
 * it under the terms of the GNU Affero General Public License, version 3,
21
 * as published by the Free Software Foundation.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
 * GNU Affero General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU Affero General Public License, version 3,
29
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
30
 *
31
 */
32
33
try {
34
35
	require_once 'lib/base.php';
36
37
	if (\OCP\Util::needUpgrade()) {
38
		\OCP\Util::writeLog('cron', 'Update required, skipping cron', \OCP\Util::DEBUG);
39
		exit;
40
	}
41
	if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
42
		\OCP\Util::writeLog('cron', 'We are in maintenance mode, skipping cron', \OCP\Util::DEBUG);
43
		exit;
44
	}
45
46
	if (\OC::$server->getSystemConfig()->getValue('singleuser', false)) {
47
		\OCP\Util::writeLog('cron', 'We are in admin only mode, skipping cron', \OCP\Util::DEBUG);
48
		exit;
49
	}
50
51
	// load all apps to get all api routes properly setup
52
	OC_App::loadApps();
53
54
	\OC::$server->getSession()->close();
55
56
	// initialize a dummy memory session
57
	$session = new \OC\Session\Memory('');
58
	$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
59
	$session = $cryptoWrapper->wrapSession($session);
60
	\OC::$server->setSession($session);
61
62
	$logger = \OC::$server->getLogger();
63
	$config = \OC::$server->getConfig();
64
65
	// Don't do anything if ownCloud has not been installed
66
	if (!$config->getSystemValue('installed', false)) {
67
		exit(0);
68
	}
69
70
	\OC::$server->getTempManager()->cleanOld();
71
72
	// Exit if background jobs are disabled!
73
	$appMode = \OCP\BackgroundJob::getExecutionType();
74
	if ($appMode == 'none') {
75
		if (OC::$CLI) {
76
			echo 'Background Jobs are disabled!' . PHP_EOL;
77
		} else {
78
			OC_JSON::error(array('data' => array('message' => 'Background jobs disabled!')));
0 ignored issues
show
Deprecated Code introduced by
The method OC_JSON::error() has been deprecated with message: Use a AppFramework JSONResponse instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
79
		}
80
		exit(1);
81
	}
82
83
	if (OC::$CLI) {
84
		// set to run indefinitely if needed
85
		set_time_limit(0);
86
87
		// the cron job must be executed with the right user
88
		if (!OC_Util::runningOnWindows())  {
89
			if (!function_exists('posix_getuid')) {
90
				echo "The posix extensions are required - see http://php.net/manual/en/book.posix.php" . PHP_EOL;
91
				exit(0);
92
			}
93
			$user = posix_getpwuid(posix_getuid());
94
			$configUser = posix_getpwuid(fileowner(OC::$SERVERROOT . '/config/config.php'));
95
			if ($user['name'] !== $configUser['name']) {
96
				echo "Console has to be executed with the same user as the web server is operated" . PHP_EOL;
97
				echo "Current user: " . $user['name'] . PHP_EOL;
98
				echo "Web server user: " . $configUser['name'] . PHP_EOL;
99
				exit(0);
100
			}
101
		}
102
103
		$instanceId = $config->getSystemValue('instanceid');
104
		$lockFileName = 'owncloud-server-' . $instanceId . '-cron.lock';
105
		$lockDirectory = $config->getSystemValue('cron.lockfile.location', sys_get_temp_dir());
106
		$lockDirectory = rtrim($lockDirectory, '\\/');
107
		$lockFile = $lockDirectory . '/' . $lockFileName;
108
109
		if (!file_exists($lockFile)) {
110
			touch($lockFile);
111
		}
112
113
		// We call ownCloud from the CLI (aka cron)
114
		if ($appMode != 'cron') {
115
			\OCP\BackgroundJob::setExecutionType('cron');
116
		}
117
118
		// open the file and try to lock it. If it is not locked, the background
119
		// job can be executed, otherwise another instance is already running
120
		$fp = fopen($lockFile, 'w');
121
		$isLocked = flock($fp, LOCK_EX|LOCK_NB, $wouldBlock);
122
123
		// check if backgroundjobs is still running. The wouldBlock check is
124
		// needed on systems with advisory locking, see
125
		// http://php.net/manual/en/function.flock.php#45464
126
		if (!$isLocked || $wouldBlock) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $wouldBlock of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
127
			echo "Another instance of cron.php is still running!" . PHP_EOL;
128
			exit(1);
129
		}
130
131
		// Work
132
		$jobList = \OC::$server->getJobList();
133
134
		// We only ask for jobs for 14 minutes, because after 15 minutes the next
135
		// system cron task should spawn.
136
		$endTime = time() + 14 * 60;
137
138
		$executedJobs = [];
139
		while ($job = $jobList->getNext()) {
140
			if (isset($executedJobs[$job->getId()])) {
141
				break;
142
			}
143
144
			$logger->debug('Run job with ID ' . $job->getId(), ['app' => 'cron']);
145
			$job->execute($jobList, $logger);
146
			$logger->debug('Finished job with ID ' . $job->getId(), ['app' => 'cron']);
147
148
			$jobList->setLastJob($job);
149
			$executedJobs[$job->getId()] = true;
150
			unset($job);
151
152
			if (time() > $endTime) {
153
				break;
154
			}
155
		}
156
157
		// unlock the file
158
		flock($fp, LOCK_UN);
159
		fclose($fp);
160
161
	} else {
162
		// We call cron.php from some website
163
		if ($appMode == 'cron') {
164
			// Cron is cron :-P
165
			OC_JSON::error(array('data' => array('message' => 'Backgroundjobs are using system cron!')));
0 ignored issues
show
Deprecated Code introduced by
The method OC_JSON::error() has been deprecated with message: Use a AppFramework JSONResponse instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
166
		} else {
167
			// Work and success :-)
168
			$jobList = \OC::$server->getJobList();
169
			$job = $jobList->getNext();
170
			if ($job != null) {
171
				$job->execute($jobList, $logger);
172
				$jobList->setLastJob($job);
173
			}
174
			OC_JSON::success();
0 ignored issues
show
Deprecated Code introduced by
The method OC_JSON::success() has been deprecated with message: Use a AppFramework JSONResponse instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
175
		}
176
	}
177
178
	// Log the successful cron execution
179
	if (\OC::$server->getConfig()->getSystemValue('cron_log', true)) {
180
		\OC::$server->getConfig()->setAppValue('core', 'lastcron', time());
181
	}
182
	exit();
183
184
} catch (Exception $ex) {
185
	\OCP\Util::writeLog('cron', $ex->getMessage(), \OCP\Util::FATAL);
186
}
187