Completed
Push — master ( 4ea7db...188b96 )
by Morris
59:10 queued 33:45
created

File::clear()   B

Complexity

Conditions 9
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 9
nc 3
nop 1
dl 0
loc 14
rs 7.756
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 * @author Sebastian Wessalowski <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 * @author Vincent Petry <[email protected]>
11
 *
12
 * @license AGPL-3.0
13
 *
14
 * This code is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License, version 3,
16
 * as published by the Free Software Foundation.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License, version 3,
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
25
 *
26
 */
27
28
namespace OC\Cache;
29
30
use OC\Files\Filesystem;
31
use OC\Files\View;
32
use OCP\ICache;
33
use OCP\ILogger;
34
use OCP\Security\ISecureRandom;
35
36
class File implements ICache {
37
38
	/** @var View */
39
	protected $storage;
40
41
	/**
42
	 * Returns the cache storage for the logged in user
43
	 *
44
	 * @return \OC\Files\View cache storage
45
	 * @throws \OC\ForbiddenException
46
	 * @throws \OC\User\NoUserException
47
	 */
48
	protected function getStorage() {
49
		if (isset($this->storage)) {
50
			return $this->storage;
51
		}
52
		if (\OC::$server->getUserSession()->isLoggedIn()) {
53
			$rootView = new View();
54
			$user = \OC::$server->getUserSession()->getUser();
55
			Filesystem::initMountPoints($user->getUID());
56 View Code Duplication
			if (!$rootView->file_exists('/' . $user->getUID() . '/cache')) {
57
				$rootView->mkdir('/' . $user->getUID() . '/cache');
58
			}
59
			$this->storage = new View('/' . $user->getUID() . '/cache');
60
			return $this->storage;
61
		} else {
62
			\OCP\Util::writeLog('core', 'Can\'t get cache storage, user not logged in', ILogger::ERROR);
63
			throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in');
64
		}
65
	}
66
67
	/**
68
	 * @param string $key
69
	 * @return mixed|null
70
	 * @throws \OC\ForbiddenException
71
	 */
72 View Code Duplication
	public function get($key) {
73
		$result = null;
74
		if ($this->hasKey($key)) {
75
			$storage = $this->getStorage();
76
			$result = $storage->file_get_contents($key);
77
		}
78
		return $result;
79
	}
80
81
	/**
82
	 * Returns the size of the stored/cached data
83
	 *
84
	 * @param string $key
85
	 * @return int
86
	 */
87 View Code Duplication
	public function size($key) {
88
		$result = 0;
89
		if ($this->hasKey($key)) {
90
			$storage = $this->getStorage();
91
			$result = $storage->filesize($key);
92
		}
93
		return $result;
94
	}
95
96
	/**
97
	 * @param string $key
98
	 * @param mixed $value
99
	 * @param int $ttl
100
	 * @return bool|mixed
101
	 * @throws \OC\ForbiddenException
102
	 */
103
	public function set($key, $value, $ttl = 0) {
104
		$storage = $this->getStorage();
105
		$result = false;
106
		// unique id to avoid chunk collision, just in case
107
		$uniqueId = \OC::$server->getSecureRandom()->generate(
108
			16,
109
			ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER
110
		);
111
112
		// use part file to prevent hasKey() to find the key
113
		// while it is being written
114
		$keyPart = $key . '.' . $uniqueId . '.part';
115
		if ($storage and $storage->file_put_contents($keyPart, $value)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
116
			if ($ttl === 0) {
117
				$ttl = 86400; // 60*60*24
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
118
			}
119
			$result = $storage->touch($keyPart, time() + $ttl);
120
			$result &= $storage->rename($keyPart, $key);
121
		}
122
		return $result;
123
	}
124
125
	/**
126
	 * @param string $key
127
	 * @return bool
128
	 * @throws \OC\ForbiddenException
129
	 */
130
	public function hasKey($key) {
131
		$storage = $this->getStorage();
132
		if ($storage && $storage->is_file($key) && $storage->isReadable($key)) {
133
			return true;
134
		}
135
		return false;
136
	}
137
138
	/**
139
	 * @param string $key
140
	 * @return bool|mixed
141
	 * @throws \OC\ForbiddenException
142
	 */
143
	public function remove($key) {
144
		$storage = $this->getStorage();
145
		if (!$storage) {
146
			return false;
147
		}
148
		return $storage->unlink($key);
149
	}
150
151
	/**
152
	 * @param string $prefix
153
	 * @return bool
154
	 * @throws \OC\ForbiddenException
155
	 */
156
	public function clear($prefix = '') {
157
		$storage = $this->getStorage();
158
		if ($storage and $storage->is_dir('/')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
159
			$dh = $storage->opendir('/');
160
			if (is_resource($dh)) {
161
				while (($file = readdir($dh)) !== false) {
162
					if ($file != '.' and $file != '..' and ($prefix === '' || strpos($file, $prefix) === 0)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
163
						$storage->unlink('/' . $file);
164
					}
165
				}
166
			}
167
		}
168
		return true;
169
	}
170
171
	/**
172
	 * Runs GC
173
	 * @throws \OC\ForbiddenException
174
	 */
175
	public function gc() {
176
		$storage = $this->getStorage();
177
		if ($storage) {
178
			// extra hour safety, in case of stray part chunks that take longer to write,
179
			// because touch() is only called after the chunk was finished
180
			$now = time() - 3600;
181
			$dh = $storage->opendir('/');
182
			if (!is_resource($dh)) {
183
				return null;
184
			}
185
			while (($file = readdir($dh)) !== false) {
186
				if ($file != '.' and $file != '..') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
187
					try {
188
						$mtime = $storage->filemtime('/' . $file);
189
						if ($mtime < $now) {
190
							$storage->unlink('/' . $file);
191
						}
192
					} catch (\OCP\Lock\LockedException $e) {
193
						// ignore locked chunks
194
						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', array('app' => 'core'));
195
					} catch (\OCP\Files\ForbiddenException $e) {
196
						\OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "' . $file . '"', array('app' => 'core'));
197
					} catch (\OCP\Files\LockNotAcquiredException $e) {
198
						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', array('app' => 'core'));
199
					}
200
				}
201
			}
202
		}
203
	}
204
}
205