Blame view
sources/apps/files_external/lib/swift.php
11.9 KB
|
03e52840d
|
1 |
<?php |
|
31b7f2792
|
2 |
|
|
03e52840d
|
3 |
/** |
|
31b7f2792
|
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
* ownCloud * * @author Christian Berendt * @copyright 2013 Christian Berendt berendt@b1-systems.de * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE * License as published by the Free Software Foundation; either * version 3 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU AFFERO GENERAL PUBLIC LICENSE for more details. * * You should have received a copy of the GNU Affero General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
|
03e52840d
|
21 22 23 |
*/ namespace OC\Files\Storage; |
|
6d9380f96
|
24 25 26 27 28 29 |
use Guzzle\Http\Exception\ClientErrorResponseException; use OpenCloud; use OpenCloud\Common\Exceptions; use OpenCloud\OpenStack; use OpenCloud\ObjectStore\Resource\DataObject; use OpenCloud\ObjectStore\Exception; |
|
03e52840d
|
30 |
|
|
31b7f2792
|
31 |
class Swift extends \OC\Files\Storage\Common {
|
|
6d9380f96
|
32 33 34 |
/** * @var \OpenCloud\ObjectStore\Service */ |
|
31b7f2792
|
35 |
private $connection; |
|
6d9380f96
|
36 37 38 |
/** * @var \OpenCloud\ObjectStore\Resource\Container */ |
|
31b7f2792
|
39 |
private $container; |
|
6d9380f96
|
40 41 42 |
/** * @var \OpenCloud\OpenStack */ |
|
31b7f2792
|
43 |
private $anchor; |
|
6d9380f96
|
44 45 46 |
/** * @var string */ |
|
31b7f2792
|
47 |
private $bucket; |
|
6d9380f96
|
48 49 50 |
/** * @var array */ |
|
31b7f2792
|
51 |
private static $tmpFiles = array(); |
|
6d9380f96
|
52 53 54 |
/** * @param string $path */ |
|
31b7f2792
|
55 56 57 58 59 |
private function normalizePath($path) {
$path = trim($path, '/');
if (!$path) {
$path = '.';
|
|
03e52840d
|
60 |
} |
|
31b7f2792
|
61 |
|
|
6d9380f96
|
62 |
$path = str_replace('#', '%23', $path);
|
|
31b7f2792
|
63 |
return $path; |
|
03e52840d
|
64 |
} |
|
6d9380f96
|
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
const SUBCONTAINER_FILE='.subcontainers';
/**
* translate directory path to container name
* @param string $path
* @return string
*/
private function getContainerName($path) {
$path=trim(trim($this->root, '/') . "/".$path, '/.');
return str_replace('/', '\\', $path);
}
/**
* @param string $path
*/
|
|
31b7f2792
|
80 81 |
private function doesObjectExist($path) {
try {
|
|
6d9380f96
|
82 |
$this->container->getPartialObject($path); |
|
31b7f2792
|
83 |
return true; |
|
6d9380f96
|
84 |
} catch (ClientErrorResponseException $e) {
|
|
31b7f2792
|
85 86 |
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
|
|
03e52840d
|
87 88 |
} } |
|
31b7f2792
|
89 90 91 92 93 |
public function __construct($params) {
if ((!isset($params['key']) and !isset($params['password']))
or !isset($params['user']) or !isset($params['bucket'])
or !isset($params['region'])) {
throw new \Exception("API Key or password, Username, Bucket and Region have to be configured.");
|
|
03e52840d
|
94 |
} |
|
03e52840d
|
95 |
|
|
31b7f2792
|
96 97 |
$this->id = 'swift::' . $params['user'] . md5($params['bucket']); $this->bucket = $params['bucket']; |
|
03e52840d
|
98 |
|
|
31b7f2792
|
99 100 101 |
if (!isset($params['url'])) {
$params['url'] = 'https://identity.api.rackspacecloud.com/v2.0/';
}
|
|
03e52840d
|
102 |
|
|
31b7f2792
|
103 104 105 |
if (!isset($params['service_name'])) {
$params['service_name'] = 'cloudFiles';
}
|
|
03e52840d
|
106 |
|
|
31b7f2792
|
107 108 |
$settings = array( 'username' => $params['user'], |
|
31b7f2792
|
109 110 111 112 113 114 |
);
if (isset($params['password'])) {
$settings['password'] = $params['password'];
} else if (isset($params['key'])) {
$settings['apiKey'] = $params['key'];
|
|
03e52840d
|
115 |
} |
|
31b7f2792
|
116 117 118 |
if (isset($params['tenant'])) {
$settings['tenantName'] = $params['tenant'];
|
|
03e52840d
|
119 |
} |
|
03e52840d
|
120 |
|
|
31b7f2792
|
121 |
if (isset($params['timeout'])) {
|
|
6d9380f96
|
122 |
$settings['timeout'] = $params['timeout']; |
|
03e52840d
|
123 |
} |
|
31b7f2792
|
124 |
|
|
6d9380f96
|
125 126 127 |
$this->anchor = new OpenStack($params['url'], $settings); $this->connection = $this->anchor->objectStoreService($params['service_name'], $params['region']); |
|
31b7f2792
|
128 |
|
|
03e52840d
|
129 |
try {
|
|
6d9380f96
|
130 131 132 |
$this->container = $this->connection->getContainer($this->bucket);
} catch (ClientErrorResponseException $e) {
$this->container = $this->connection->createContainer($this->bucket);
|
|
03e52840d
|
133 |
} |
|
31b7f2792
|
134 135 136 |
if (!$this->file_exists('.')) {
$this->mkdir('.');
}
|
|
03e52840d
|
137 |
} |
|
31b7f2792
|
138 139 140 141 |
public function mkdir($path) {
$path = $this->normalizePath($path);
if ($this->is_dir($path)) {
|
|
03e52840d
|
142 143 |
return false; } |
|
31b7f2792
|
144 145 146 |
if($path !== '.') {
$path .= '/';
|
|
03e52840d
|
147 |
} |
|
31b7f2792
|
148 149 |
try {
|
|
6d9380f96
|
150 151 152 153 |
$customHeaders = array('content-type' => 'httpd/unix-directory');
$metadataHeaders = DataObject::stockHeaders(array());
$allHeaders = $customHeaders + $metadataHeaders;
$this->container->uploadObject($path, '', $allHeaders);
|
|
31b7f2792
|
154 155 |
} catch (Exceptions\CreateUpdateError $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
|
|
03e52840d
|
156 |
return false; |
|
03e52840d
|
157 |
} |
|
03e52840d
|
158 159 |
return true; } |
|
31b7f2792
|
160 161 |
public function file_exists($path) {
$path = $this->normalizePath($path);
|
|
03e52840d
|
162 |
|
|
31b7f2792
|
163 164 |
if ($path !== '.' && $this->is_dir($path)) {
$path .= '/';
|
|
03e52840d
|
165 |
} |
|
31b7f2792
|
166 |
return $this->doesObjectExist($path); |
|
03e52840d
|
167 |
} |
|
31b7f2792
|
168 169 170 171 172 |
public function rmdir($path) {
$path = $this->normalizePath($path);
if (!$this->is_dir($path)) {
return false;
|
|
03e52840d
|
173 |
} |
|
03e52840d
|
174 |
|
|
31b7f2792
|
175 176 177 178 179 |
$dh = $this->opendir($path);
while ($file = readdir($dh)) {
if ($file === '.' || $file === '..') {
continue;
}
|
|
03e52840d
|
180 |
|
|
31b7f2792
|
181 182 183 184 185 186 |
if ($this->is_dir($path . '/' . $file)) {
$this->rmdir($path . '/' . $file);
} else {
$this->unlink($path . '/' . $file);
}
}
|
|
03e52840d
|
187 |
|
|
31b7f2792
|
188 |
try {
|
|
6d9380f96
|
189 |
$this->container->dataObject()->setName($path . '/')->delete(); |
|
31b7f2792
|
190 191 192 |
} catch (Exceptions\DeleteError $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
|
|
03e52840d
|
193 |
} |
|
03e52840d
|
194 |
|
|
31b7f2792
|
195 |
return true; |
|
03e52840d
|
196 |
} |
|
31b7f2792
|
197 198 |
public function opendir($path) {
$path = $this->normalizePath($path);
|
|
03e52840d
|
199 |
|
|
31b7f2792
|
200 201 |
if ($path === '.') {
$path = '';
|
|
03e52840d
|
202 |
} else {
|
|
31b7f2792
|
203 |
$path .= '/'; |
|
03e52840d
|
204 |
} |
|
03e52840d
|
205 |
|
|
6d9380f96
|
206 |
$path = str_replace('%23', '#', $path); // the prefix is sent as a query param, so revert the encoding of #
|
|
31b7f2792
|
207 208 |
try {
$files = array();
|
|
6d9380f96
|
209 210 |
/** @var OpenCloud\Common\Collection $objects */ $objects = $this->container->objectList(array( |
|
31b7f2792
|
211 212 213 |
'prefix' => $path, 'delimiter' => '/' )); |
|
6d9380f96
|
214 215 216 |
/** @var OpenCloud\ObjectStore\Resource\DataObject $object */
foreach ($objects as $object) {
$file = basename($object->getName());
|
|
31b7f2792
|
217 218 219 |
if ($file !== basename($path)) {
$files[] = $file;
}
|
|
03e52840d
|
220 |
} |
|
31b7f2792
|
221 222 223 224 225 |
\OC\Files\Stream\Dir::register('swift' . $path, $files);
return opendir('fakedir://swift' . $path);
} catch (Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
|
|
03e52840d
|
226 |
} |
|
31b7f2792
|
227 |
|
|
03e52840d
|
228 |
} |
|
31b7f2792
|
229 230 |
public function stat($path) {
$path = $this->normalizePath($path);
|
|
03e52840d
|
231 |
|
|
31b7f2792
|
232 233 |
if ($this->is_dir($path) && $path != '.') {
$path .= '/';
|
|
03e52840d
|
234 |
} |
|
03e52840d
|
235 |
|
|
31b7f2792
|
236 |
try {
|
|
6d9380f96
|
237 238 |
$object = $this->container->getPartialObject($path);
} catch (ClientErrorResponseException $e) {
|
|
31b7f2792
|
239 240 241 |
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
}
|
|
03e52840d
|
242 |
|
|
6d9380f96
|
243 244 245 246 247 248 249 250 251 252 |
$dateTime = \DateTime::createFromFormat(\DateTime::RFC1123, $object->getLastModified());
if ($dateTime !== false) {
$mtime = $dateTime->getTimestamp();
} else {
$mtime = null;
}
$objectMetadata = $object->getMetadata();
$metaTimestamp = $objectMetadata->getProperty('timestamp');
if (isset($metaTimestamp)) {
$mtime = $metaTimestamp;
|
|
03e52840d
|
253 |
} |
|
03e52840d
|
254 |
|
|
837968727
|
255 256 257 |
if (!empty($mtime)) {
$mtime = floor($mtime);
}
|
|
31b7f2792
|
258 |
$stat = array(); |
|
6d9380f96
|
259 |
$stat['size'] = (int) $object->getContentLength(); |
|
31b7f2792
|
260 261 262 |
$stat['mtime'] = $mtime; $stat['atime'] = time(); return $stat; |
|
03e52840d
|
263 |
} |
|
31b7f2792
|
264 265 |
public function filetype($path) {
$path = $this->normalizePath($path);
|
|
03e52840d
|
266 |
|
|
31b7f2792
|
267 268 |
if ($path !== '.' && $this->doesObjectExist($path)) {
return 'file';
|
|
03e52840d
|
269 |
} |
|
03e52840d
|
270 |
|
|
31b7f2792
|
271 272 |
if ($path !== '.') {
$path .= '/';
|
|
03e52840d
|
273 |
} |
|
03e52840d
|
274 |
|
|
31b7f2792
|
275 276 |
if ($this->doesObjectExist($path)) {
return 'dir';
|
|
03e52840d
|
277 |
} |
|
03e52840d
|
278 279 280 |
}
public function unlink($path) {
|
|
31b7f2792
|
281 |
$path = $this->normalizePath($path); |
|
6d9380f96
|
282 283 284 |
if ($this->is_dir($path)) {
return $this->rmdir($path);
}
|
|
31b7f2792
|
285 |
try {
|
|
6d9380f96
|
286 287 |
$this->container->dataObject()->setName($path)->delete();
} catch (ClientErrorResponseException $e) {
|
|
31b7f2792
|
288 |
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
|
|
03e52840d
|
289 290 |
return false; } |
|
31b7f2792
|
291 292 |
return true; |
|
03e52840d
|
293 294 295 |
}
public function fopen($path, $mode) {
|
|
31b7f2792
|
296 297 298 |
$path = $this->normalizePath($path);
switch ($mode) {
|
|
03e52840d
|
299 300 |
case 'r': case 'rb': |
|
31b7f2792
|
301 302 303 |
$tmpFile = \OC_Helper::tmpFile();
self::$tmpFiles[$tmpFile] = $path;
try {
|
|
6d9380f96
|
304 305 306 307 308 |
$object = $this->container->getObject($path);
} catch (ClientErrorResponseException $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
} catch (Exception\ObjectNotFoundException $e) {
|
|
31b7f2792
|
309 |
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
|
|
03e52840d
|
310 311 |
return false; } |
|
31b7f2792
|
312 |
try {
|
|
6d9380f96
|
313 314 315 316 |
$objectContent = $object->getContent(); $objectContent->rewind(); $stream = $objectContent->getStream(); file_put_contents($tmpFile, $stream); |
|
31b7f2792
|
317 318 319 320 321 |
} catch (Exceptions\IOError $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
}
return fopen($tmpFile, 'r');
|
|
03e52840d
|
322 323 324 325 326 327 328 329 330 331 332 333 |
case 'w': case 'wb': case 'a': case 'ab': case 'r+': case 'w+': case 'wb+': case 'a+': case 'x': case 'x+': case 'c': case 'c+': |
|
31b7f2792
|
334 335 336 337 338 339 |
if (strrpos($path, '.') !== false) {
$ext = substr($path, strrpos($path, '.'));
} else {
$ext = '';
}
$tmpFile = \OC_Helper::tmpFile($ext);
|
|
03e52840d
|
340 |
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); |
|
31b7f2792
|
341 342 343 344 345 346 347 |
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
file_put_contents($tmpFile, $source);
}
self::$tmpFiles[$tmpFile] = $path;
return fopen('close://' . $tmpFile, $mode);
|
|
03e52840d
|
348 349 |
} } |
|
31b7f2792
|
350 351 352 353 354 355 |
public function getMimeType($path) {
$path = $this->normalizePath($path);
if ($this->is_dir($path)) {
return 'httpd/unix-directory';
} else if ($this->file_exists($path)) {
|
|
6d9380f96
|
356 357 |
$object = $this->container->getPartialObject($path); return $object->getContentType(); |
|
03e52840d
|
358 |
} |
|
31b7f2792
|
359 |
return false; |
|
03e52840d
|
360 |
} |
|
31b7f2792
|
361 362 |
public function touch($path, $mtime = null) {
$path = $this->normalizePath($path);
|
|
6d9380f96
|
363 364 365 366 |
if (is_null($mtime)) {
$mtime = time();
}
$metadata = array('timestamp' => $mtime);
|
|
31b7f2792
|
367 368 369 370 |
if ($this->file_exists($path)) {
if ($this->is_dir($path) && $path != '.') {
$path .= '/';
}
|
|
6d9380f96
|
371 372 373 |
$object = $this->container->getPartialObject($path); $object->saveMetadata($metadata); return true; |
|
31b7f2792
|
374 |
} else {
|
|
6d9380f96
|
375 376 377 378 379 |
$customHeaders = array('content-type' => 'text/plain');
$metadataHeaders = DataObject::stockHeaders($metadata);
$allHeaders = $customHeaders + $metadataHeaders;
$this->container->uploadObject($path, '', $allHeaders);
return true;
|
|
03e52840d
|
380 |
} |
|
31b7f2792
|
381 382 383 384 385 |
}
public function copy($path1, $path2) {
$path1 = $this->normalizePath($path1);
$path2 = $this->normalizePath($path2);
|
|
6d9380f96
|
386 387 388 389 390 |
$fileType = $this->filetype($path1);
if ($fileType === 'file') {
// make way
$this->unlink($path2);
|
|
31b7f2792
|
391 |
try {
|
|
6d9380f96
|
392 393 394 |
$source = $this->container->getPartialObject($path1);
$source->copy($this->bucket.'/'.$path2);
} catch (ClientErrorResponseException $e) {
|
|
31b7f2792
|
395 396 397 |
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
}
|
|
6d9380f96
|
398 399 400 401 402 |
} else if ($fileType === 'dir') {
// make way
$this->unlink($path2);
|
|
31b7f2792
|
403 404 |
try {
|
|
6d9380f96
|
405 406 407 |
$source = $this->container->getPartialObject($path1 . '/');
$source->copy($this->bucket.'/'.$path2 . '/');
} catch (ClientErrorResponseException $e) {
|
|
31b7f2792
|
408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
}
$dh = $this->opendir($path1);
while ($file = readdir($dh)) {
if ($file === '.' || $file === '..') {
continue;
}
$source = $path1 . '/' . $file;
$target = $path2 . '/' . $file;
$this->copy($source, $target);
}
|
|
6d9380f96
|
422 423 424 425 |
} else {
//file does not exist
return false;
|
|
03e52840d
|
426 |
} |
|
31b7f2792
|
427 |
return true; |
|
03e52840d
|
428 429 430 |
}
public function rename($path1, $path2) {
|
|
31b7f2792
|
431 432 |
$path1 = $this->normalizePath($path1); $path2 = $this->normalizePath($path2); |
|
03e52840d
|
433 |
|
|
6d9380f96
|
434 435 436 437 438 439 440 441 |
$fileType = $this->filetype($path1);
if ($fileType === 'dir' || $fileType === 'file') {
// make way
$this->unlink($path2);
// copy
|
|
31b7f2792
|
442 443 444 |
if ($this->copy($path1, $path2) === false) {
return false;
}
|
|
03e52840d
|
445 |
|
|
6d9380f96
|
446 |
// cleanup |
|
31b7f2792
|
447 448 449 450 |
if ($this->unlink($path1) === false) {
$this->unlink($path2);
return false;
}
|
|
03e52840d
|
451 |
|
|
6d9380f96
|
452 |
return true; |
|
03e52840d
|
453 |
} |
|
6d9380f96
|
454 |
return false; |
|
03e52840d
|
455 |
} |
|
31b7f2792
|
456 457 |
public function getId() {
return $this->id;
|
|
03e52840d
|
458 |
} |
|
31b7f2792
|
459 460 |
public function getConnection() {
return $this->connection;
|
|
03e52840d
|
461 |
} |
|
31b7f2792
|
462 463 464 |
public function writeBack($tmpFile) {
if (!isset(self::$tmpFiles[$tmpFile])) {
return false;
|
|
03e52840d
|
465 |
} |
|
6d9380f96
|
466 467 |
$fileData = fopen($tmpFile, 'r'); $this->container->uploadObject(self::$tmpFiles[$tmpFile], $fileData); |
|
31b7f2792
|
468 |
unlink($tmpFile); |
|
03e52840d
|
469 |
} |
|
6d9380f96
|
470 471 472 473 474 475 476 477 478 479 480 |
/**
* check if curl is installed
*/
public static function checkDependencies() {
if (function_exists('curl_init')) {
return true;
} else {
return array('curl');
}
}
|
|
03e52840d
|
481 |
} |