Passed
Push — master ( ad6eb8...bba3a1 )
by Julius
14:09 queued 18s
created

File::set()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 3
nop 3
dl 0
loc 20
rs 9.8666
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Christoph Wurst <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Lukas Reschke <[email protected]>
9
 * @author Robin Appelman <[email protected]>
10
 * @author Roeland Jago Douma <[email protected]>
11
 * @author Sebastian Wessalowski <[email protected]>
12
 * @author Thomas Müller <[email protected]>
13
 * @author Vincent Petry <[email protected]>
14
 *
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program. If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
namespace OC\Cache;
31
32
use OC\Files\Filesystem;
33
use OC\Files\View;
34
use OCP\ICache;
35
use OCP\Security\ISecureRandom;
36
use Psr\Log\LoggerInterface;
37
38
/**
39
 * @deprecated 26.0.0
40
 */
41
class File implements ICache {
42
	/** @var View */
43
	protected $storage;
44
45
	/**
46
	 * Set the cache storage for a user
47
	 */
48
	public function setUpStorage(string $userId) {
49
		Filesystem::initMountPoints($userId);
50
		$rootView = new View();
51
		if (!$rootView->file_exists('/' . $userId . '/cache')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $rootView->file_exists('/' . $userId . '/cache') of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
52
			$rootView->mkdir('/' . $userId . '/cache');
53
		}
54
		$this->storage = new View('/' . $userId . '/cache');
55
		return $this->storage;
56
	}
57
58
	/**
59
	 * Returns the cache storage for the logged in user
60
	 *
61
	 * @return \OC\Files\View cache storage
62
	 * @throws \OC\ForbiddenException
63
	 * @throws \OC\User\NoUserException
64
	 */
65
	protected function getStorage() {
66
		if ($this->storage !== null) {
67
			return $this->storage;
68
		}
69
		if (\OC::$server->getUserSession()->isLoggedIn()) {
70
			$user = \OC::$server->getUserSession()->getUser();
71
			return $this->setUpStorage($user->getUID());
72
		} else {
73
			\OC::$server->get(LoggerInterface::class)->error('Can\'t get cache storage, user not logged in', ['app' => 'core']);
74
			throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in');
75
		}
76
	}
77
78
	/**
79
	 * @param string $key
80
	 * @return mixed|null
81
	 * @throws \OC\ForbiddenException
82
	 */
83
	public function get($key) {
84
		$result = null;
85
		if ($this->hasKey($key)) {
86
			$storage = $this->getStorage();
87
			$result = $storage->file_get_contents($key);
88
		}
89
		return $result;
90
	}
91
92
	/**
93
	 * Returns the size of the stored/cached data
94
	 *
95
	 * @param string $key
96
	 * @return int
97
	 */
98
	public function size($key) {
99
		$result = 0;
100
		if ($this->hasKey($key)) {
101
			$storage = $this->getStorage();
102
			$result = $storage->filesize($key);
103
		}
104
		return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
105
	}
106
107
	/**
108
	 * @param string $key
109
	 * @param mixed $value
110
	 * @param int $ttl
111
	 * @return bool|mixed
112
	 * @throws \OC\ForbiddenException
113
	 */
114
	public function set($key, $value, $ttl = 0) {
115
		$storage = $this->getStorage();
116
		$result = false;
117
		// unique id to avoid chunk collision, just in case
118
		$uniqueId = \OC::$server->getSecureRandom()->generate(
119
			16,
120
			ISecureRandom::CHAR_ALPHANUMERIC
121
		);
122
123
		// use part file to prevent hasKey() to find the key
124
		// while it is being written
125
		$keyPart = $key . '.' . $uniqueId . '.part';
126
		if ($storage and $storage->file_put_contents($keyPart, $value)) {
127
			if ($ttl === 0) {
128
				$ttl = 86400; // 60*60*24
129
			}
130
			$result = $storage->touch($keyPart, time() + $ttl);
131
			$result &= $storage->rename($keyPart, $key);
132
		}
133
		return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type integer which is incompatible with the return type mandated by OCP\ICache::set() of boolean.
Loading history...
134
	}
135
136
	/**
137
	 * @param string $key
138
	 * @return bool
139
	 * @throws \OC\ForbiddenException
140
	 */
141
	public function hasKey($key) {
142
		$storage = $this->getStorage();
143
		if ($storage && $storage->is_file($key) && $storage->isReadable($key)) {
144
			return true;
145
		}
146
		return false;
147
	}
148
149
	/**
150
	 * @param string $key
151
	 * @return bool|mixed
152
	 * @throws \OC\ForbiddenException
153
	 */
154
	public function remove($key) {
155
		$storage = $this->getStorage();
156
		if (!$storage) {
0 ignored issues
show
introduced by
$storage is of type OC\Files\View, thus it always evaluated to true.
Loading history...
157
			return false;
158
		}
159
		return $storage->unlink($key);
160
	}
161
162
	/**
163
	 * @param string $prefix
164
	 * @return bool
165
	 * @throws \OC\ForbiddenException
166
	 */
167
	public function clear($prefix = '') {
168
		$storage = $this->getStorage();
169
		if ($storage and $storage->is_dir('/')) {
170
			$dh = $storage->opendir('/');
171
			if (is_resource($dh)) {
172
				while (($file = readdir($dh)) !== false) {
173
					if ($file != '.' and $file != '..' and ($prefix === '' || strpos($file, $prefix) === 0)) {
174
						$storage->unlink('/' . $file);
175
					}
176
				}
177
			}
178
		}
179
		return true;
180
	}
181
182
	/**
183
	 * Runs GC
184
	 * @throws \OC\ForbiddenException
185
	 */
186
	public function gc() {
187
		$storage = $this->getStorage();
188
		if ($storage) {
0 ignored issues
show
introduced by
$storage is of type OC\Files\View, thus it always evaluated to true.
Loading history...
189
			// extra hour safety, in case of stray part chunks that take longer to write,
190
			// because touch() is only called after the chunk was finished
191
			$now = time() - 3600;
192
			$dh = $storage->opendir('/');
193
			if (!is_resource($dh)) {
194
				return null;
195
			}
196
			while (($file = readdir($dh)) !== false) {
197
				if ($file != '.' and $file != '..') {
198
					try {
199
						$mtime = $storage->filemtime('/' . $file);
200
						if ($mtime < $now) {
201
							$storage->unlink('/' . $file);
202
						}
203
					} catch (\OCP\Lock\LockedException $e) {
204
						// ignore locked chunks
205
						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
206
					} catch (\OCP\Files\ForbiddenException $e) {
207
						\OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "' . $file . '"', ['app' => 'core']);
208
					} catch (\OCP\Files\LockNotAcquiredException $e) {
209
						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
210
					}
211
				}
212
			}
213
		}
214
	}
215
216
	public static function isAvailable(): bool {
217
		return true;
218
	}
219
}
220