Blame view

sources/apps/files_external/lib/swift.php 11.2 KB
03e52840d   Kload   Init
1
  <?php
31b7f2792   Kload   Upgrade to ownclo...
2

03e52840d   Kload   Init
3
  /**
31b7f2792   Kload   Upgrade to ownclo...
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   Kload   Init
21
22
23
   */
  
  namespace OC\Files\Storage;
31b7f2792   Kload   Upgrade to ownclo...
24
25
26
  set_include_path(get_include_path() . PATH_SEPARATOR .
          \OC_App::getAppPath('files_external') . '/3rdparty/php-opencloud/lib');
  require_once 'openstack.php';
03e52840d   Kload   Init
27

31b7f2792   Kload   Upgrade to ownclo...
28
29
  use \OpenCloud;
  use \OpenCloud\Common\Exceptions;
03e52840d   Kload   Init
30

31b7f2792   Kload   Upgrade to ownclo...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  class Swift extends \OC\Files\Storage\Common {
  
          /**
           * @var \OpenCloud\ObjectStore
           */
  	private $connection;
          /**
           * @var \OpenCloud\ObjectStore\Container
           */
  	private $container;
          /**
           * @var \OpenCloud\OpenStack
           */
  	private $anchor;
          /**
           * @var string
           */
  	private $bucket;
          /**
           * @var array
           */
  	private static $tmpFiles = array();
  
  	private function normalizePath($path) {
  		$path = trim($path, '/');
  
  		if (!$path) {
  			$path = '.';
03e52840d   Kload   Init
59
  		}
31b7f2792   Kload   Upgrade to ownclo...
60
61
  
  		return $path;
03e52840d   Kload   Init
62
  	}
31b7f2792   Kload   Upgrade to ownclo...
63
64
65
66
67
68
69
70
71
72
  	private function doesObjectExist($path) {
  		try {
  			$object = $this->container->DataObject($path);
  			return true;
  		} catch (Exceptions\ObjFetchError $e) {
  			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
  			return false;
  		} catch (Exceptions\HttpError $e) {
  			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
  			return false;
03e52840d   Kload   Init
73
74
  		}
  	}
31b7f2792   Kload   Upgrade to ownclo...
75
76
77
78
79
  	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   Kload   Init
80
  		}
03e52840d   Kload   Init
81

31b7f2792   Kload   Upgrade to ownclo...
82
83
  		$this->id = 'swift::' . $params['user'] . md5($params['bucket']);
  		$this->bucket = $params['bucket'];
03e52840d   Kload   Init
84

31b7f2792   Kload   Upgrade to ownclo...
85
86
87
  		if (!isset($params['url'])) {
  			$params['url'] = 'https://identity.api.rackspacecloud.com/v2.0/';
  		}
03e52840d   Kload   Init
88

31b7f2792   Kload   Upgrade to ownclo...
89
90
91
  		if (!isset($params['service_name'])) {
  			$params['service_name'] = 'cloudFiles';
  		}
03e52840d   Kload   Init
92

31b7f2792   Kload   Upgrade to ownclo...
93
94
95
96
97
98
99
100
101
  		$settings = array(
  			'username' => $params['user'],
  			
  		);
  
  		if (isset($params['password'])) {
  			$settings['password'] = $params['password'];
  		} else if (isset($params['key'])) {
  			$settings['apiKey'] = $params['key'];
03e52840d   Kload   Init
102
  		}
31b7f2792   Kload   Upgrade to ownclo...
103
104
105
  
  		if (isset($params['tenant'])) {
  			$settings['tenantName'] = $params['tenant'];
03e52840d   Kload   Init
106
  		}
03e52840d   Kload   Init
107

31b7f2792   Kload   Upgrade to ownclo...
108
109
110
111
  		$this->anchor = new \OpenCloud\OpenStack($params['url'], $settings);
  
  		if (isset($params['timeout'])) {
  			$this->anchor->setHttpTimeout($params['timeout']);
03e52840d   Kload   Init
112
  		}
31b7f2792   Kload   Upgrade to ownclo...
113
114
  
  		$this->connection = $this->anchor->ObjectStore($params['service_name'], $params['region'], 'publicURL');
03e52840d   Kload   Init
115
  		try {
31b7f2792   Kload   Upgrade to ownclo...
116
117
118
119
  			$this->container = $this->connection->Container($this->bucket);
  		} catch (Exceptions\ContainerNotFoundError $e) {
  			$this->container = $this->connection->Container();
  			$this->container->Create(array('name' => $this->bucket));
03e52840d   Kload   Init
120
  		}
31b7f2792   Kload   Upgrade to ownclo...
121
122
123
  		if (!$this->file_exists('.')) {
  			$this->mkdir('.');
  		}
03e52840d   Kload   Init
124
  	}
31b7f2792   Kload   Upgrade to ownclo...
125
126
127
128
  	public function mkdir($path) {
  		$path = $this->normalizePath($path);
  
  		if ($this->is_dir($path)) {
03e52840d   Kload   Init
129
130
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
131
132
133
  
  		if($path !== '.') {
  			$path .= '/';
03e52840d   Kload   Init
134
  		}
31b7f2792   Kload   Upgrade to ownclo...
135
136
137
138
139
140
141
142
143
  
  		try {
  			$object = $this->container->DataObject();
  			$object->Create(array(
  				'name' => $path,
  				'content_type' => 'httpd/unix-directory'
  			));
  		} catch (Exceptions\CreateUpdateError $e) {
  			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
03e52840d   Kload   Init
144
  			return false;
03e52840d   Kload   Init
145
  		}
03e52840d   Kload   Init
146
147
  		return true;
  	}
31b7f2792   Kload   Upgrade to ownclo...
148
149
  	public function file_exists($path) {
  		$path = $this->normalizePath($path);
03e52840d   Kload   Init
150

31b7f2792   Kload   Upgrade to ownclo...
151
152
  		if ($path !== '.' && $this->is_dir($path)) {
  			$path .= '/';
03e52840d   Kload   Init
153
  		}
31b7f2792   Kload   Upgrade to ownclo...
154
  		return $this->doesObjectExist($path);
03e52840d   Kload   Init
155
  	}
31b7f2792   Kload   Upgrade to ownclo...
156
157
158
159
160
  	public function rmdir($path) {
  		$path = $this->normalizePath($path);
  
  		if (!$this->is_dir($path)) {
  			return false;
03e52840d   Kload   Init
161
  		}
03e52840d   Kload   Init
162

31b7f2792   Kload   Upgrade to ownclo...
163
164
165
166
167
  		$dh = $this->opendir($path);
  		while ($file = readdir($dh)) {
  			if ($file === '.' || $file === '..') {
  				continue;
  			}
03e52840d   Kload   Init
168

31b7f2792   Kload   Upgrade to ownclo...
169
170
171
172
173
174
  			if ($this->is_dir($path . '/' . $file)) {
  				$this->rmdir($path . '/' . $file);
  			} else {
  				$this->unlink($path . '/' . $file);
  			}
  		}
03e52840d   Kload   Init
175

31b7f2792   Kload   Upgrade to ownclo...
176
177
178
179
180
181
  		try {
  			$object = $this->container->DataObject($path . '/');
  			$object->Delete();
  		} catch (Exceptions\DeleteError $e) {
  			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
  			return false;
03e52840d   Kload   Init
182
  		}
03e52840d   Kload   Init
183

31b7f2792   Kload   Upgrade to ownclo...
184
  		return true;
03e52840d   Kload   Init
185
  	}
31b7f2792   Kload   Upgrade to ownclo...
186
187
  	public function opendir($path) {
  		$path = $this->normalizePath($path);
03e52840d   Kload   Init
188

31b7f2792   Kload   Upgrade to ownclo...
189
190
  		if ($path === '.') {
  			$path = '';
03e52840d   Kload   Init
191
  		} else {
31b7f2792   Kload   Upgrade to ownclo...
192
  			$path .= '/';
03e52840d   Kload   Init
193
  		}
03e52840d   Kload   Init
194

31b7f2792   Kload   Upgrade to ownclo...
195
196
197
198
199
200
201
202
203
204
205
206
  		try {
  			$files = array();
  			$objects = $this->container->ObjectList(array(
  				'prefix' => $path,
  				'delimiter' => '/'
  			));
  
  			while ($object = $objects->Next()) {
  				$file = basename($object->Name());
  				if ($file !== basename($path)) {
  					$files[] = $file;
  				}
03e52840d   Kload   Init
207
  			}
31b7f2792   Kload   Upgrade to ownclo...
208
209
210
211
212
  			\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   Kload   Init
213
  		}
31b7f2792   Kload   Upgrade to ownclo...
214

03e52840d   Kload   Init
215
  	}
31b7f2792   Kload   Upgrade to ownclo...
216
217
  	public function stat($path) {
  		$path = $this->normalizePath($path);
03e52840d   Kload   Init
218

31b7f2792   Kload   Upgrade to ownclo...
219
220
  		if ($this->is_dir($path) && $path != '.') {
  			$path .= '/';
03e52840d   Kload   Init
221
  		}
03e52840d   Kload   Init
222

31b7f2792   Kload   Upgrade to ownclo...
223
224
225
226
227
228
  		try {
  			$object = $this->container->DataObject($path);
  		} catch (Exceptions\ObjFetchError $e) {
  			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
  			return false;
  		}
03e52840d   Kload   Init
229

31b7f2792   Kload   Upgrade to ownclo...
230
231
232
  		$mtime = $object->extra_headers['X-Timestamp'];
  		if (isset($object->extra_headers['X-Object-Meta-Timestamp'])) {
  			$mtime = $object->extra_headers['X-Object-Meta-Timestamp'];
03e52840d   Kload   Init
233
  		}
03e52840d   Kload   Init
234

837968727   Kload   [enh] Upgrade to ...
235
236
237
  		if (!empty($mtime)) {
  			$mtime = floor($mtime);
  		}
31b7f2792   Kload   Upgrade to ownclo...
238
239
240
241
242
  		$stat = array();
  		$stat['size'] = $object->content_length;
  		$stat['mtime'] = $mtime;
  		$stat['atime'] = time();
  		return $stat;
03e52840d   Kload   Init
243
  	}
31b7f2792   Kload   Upgrade to ownclo...
244
245
  	public function filetype($path) {
  		$path = $this->normalizePath($path);
03e52840d   Kload   Init
246

31b7f2792   Kload   Upgrade to ownclo...
247
248
  		if ($path !== '.' && $this->doesObjectExist($path)) {
  			return 'file';
03e52840d   Kload   Init
249
  		}
03e52840d   Kload   Init
250

31b7f2792   Kload   Upgrade to ownclo...
251
252
  		if ($path !== '.') {
  			$path .= '/';
03e52840d   Kload   Init
253
  		}
03e52840d   Kload   Init
254

31b7f2792   Kload   Upgrade to ownclo...
255
256
  		if ($this->doesObjectExist($path)) {
  			return 'dir';
03e52840d   Kload   Init
257
  		}
03e52840d   Kload   Init
258
259
260
  	}
  
  	public function unlink($path) {
31b7f2792   Kload   Upgrade to ownclo...
261
262
263
264
265
266
267
268
269
270
  		$path = $this->normalizePath($path);
  
  		try {
  			$object = $this->container->DataObject($path);
  			$object->Delete();
  		} catch (Exceptions\DeleteError $e) {
  			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
  			return false;
  		} catch (Exceptions\ObjFetchError $e) {
  			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
03e52840d   Kload   Init
271
272
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
273
274
  
  		return true;
03e52840d   Kload   Init
275
276
277
  	}
  
  	public function fopen($path, $mode) {
31b7f2792   Kload   Upgrade to ownclo...
278
279
280
  		$path = $this->normalizePath($path);
  
  		switch ($mode) {
03e52840d   Kload   Init
281
282
  			case 'r':
  			case 'rb':
31b7f2792   Kload   Upgrade to ownclo...
283
284
285
286
287
288
  				$tmpFile = \OC_Helper::tmpFile();
  				self::$tmpFiles[$tmpFile] = $path;
  				try {
  					$object = $this->container->DataObject($path);
  				} catch (Exceptions\ObjFetchError $e) {
  					\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
03e52840d   Kload   Init
289
290
  					return false;
  				}
31b7f2792   Kload   Upgrade to ownclo...
291
292
293
294
295
296
297
  				try {
  					$object->SaveToFilename($tmpFile);
  				} catch (Exceptions\IOError $e) {
  					\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
  					return false;
  				}
  				return fopen($tmpFile, 'r');
03e52840d   Kload   Init
298
299
300
301
302
303
304
305
306
307
308
309
  			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   Kload   Upgrade to ownclo...
310
311
312
313
314
315
  				if (strrpos($path, '.') !== false) {
  					$ext = substr($path, strrpos($path, '.'));
  				} else {
  					$ext = '';
  				}
  				$tmpFile = \OC_Helper::tmpFile($ext);
03e52840d   Kload   Init
316
  				\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
31b7f2792   Kload   Upgrade to ownclo...
317
318
319
320
321
322
323
  				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   Kload   Init
324
325
  		}
  	}
31b7f2792   Kload   Upgrade to ownclo...
326
327
328
329
330
331
332
333
  	public function getMimeType($path) {
  		$path = $this->normalizePath($path);
  
  		if ($this->is_dir($path)) {
  			return 'httpd/unix-directory';
  		} else if ($this->file_exists($path)) {
  			$object = $this->container->DataObject($path);
  			return $object->extra_headers["Content-Type"];
03e52840d   Kload   Init
334
  		}
31b7f2792   Kload   Upgrade to ownclo...
335
  		return false;
03e52840d   Kload   Init
336
  	}
31b7f2792   Kload   Upgrade to ownclo...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  	public function touch($path, $mtime = null) {
  		$path = $this->normalizePath($path);
  		if ($this->file_exists($path)) {
  			if ($this->is_dir($path) && $path != '.') {
  				$path .= '/';
  			}
  
  			$object = $this->container->DataObject($path);
  			if( is_null($mtime)) {
  				$mtime = time();
  			}
  			$settings = array(
  				'name' => $path,
  				'extra_headers' => array(
  					'X-Object-Meta-Timestamp' => $mtime
  				)
  			);
837968727   Kload   [enh] Upgrade to ...
354
  			return $object->UpdateMetadata($settings);
31b7f2792   Kload   Upgrade to ownclo...
355
356
357
358
359
360
361
362
363
364
365
366
367
  		} else {
  			$object = $this->container->DataObject();
  			if (is_null($mtime)) {
  				$mtime = time();
  			}
  			$settings = array(
  				'name' => $path,
  				'content_type' => 'text/plain',
  				'extra_headers' => array(
  					'X-Object-Meta-Timestamp' => $mtime
  				)
  			);
  			return $object->Create($settings);
03e52840d   Kload   Init
368
  		}
31b7f2792   Kload   Upgrade to ownclo...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  	}
  
  	public function copy($path1, $path2) {
  		$path1 = $this->normalizePath($path1);
  		$path2 = $this->normalizePath($path2);
  
  		if ($this->is_file($path1)) {
  			try {
  				$source = $this->container->DataObject($path1);
  				$target = $this->container->DataObject();
  				$target->Create(array(
  					'name' => $path2,
  				));
  				$source->Copy($target);
  			} catch (Exceptions\ObjectCopyError $e) {
  				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
  				return false;
  			}
  		} else {
  			if ($this->file_exists($path2)) {
  				return false;
  			}
  
  			try {
  				$source = $this->container->DataObject($path1 . '/');
  				$target = $this->container->DataObject();
  				$target->Create(array(
  					'name' => $path2 . '/',
  				));
  				$source->Copy($target);
  			} catch (Exceptions\ObjectCopyError $e) {
  				\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);
  			}
03e52840d   Kload   Init
414
  		}
31b7f2792   Kload   Upgrade to ownclo...
415
  		return true;
03e52840d   Kload   Init
416
417
418
  	}
  
  	public function rename($path1, $path2) {
31b7f2792   Kload   Upgrade to ownclo...
419
420
  		$path1 = $this->normalizePath($path1);
  		$path2 = $this->normalizePath($path2);
03e52840d   Kload   Init
421

31b7f2792   Kload   Upgrade to ownclo...
422
423
424
425
  		if ($this->is_file($path1)) {
  			if ($this->copy($path1, $path2) === false) {
  				return false;
  			}
03e52840d   Kload   Init
426

31b7f2792   Kload   Upgrade to ownclo...
427
428
429
430
431
432
433
434
  			if ($this->unlink($path1) === false) {
  				$this->unlink($path2);
  				return false;
  			}
  		} else {
  			if ($this->file_exists($path2)) {
  				return false;
  			}
03e52840d   Kload   Init
435

31b7f2792   Kload   Upgrade to ownclo...
436
437
438
  			if ($this->copy($path1, $path2) === false) {
  				return false;
  			}
03e52840d   Kload   Init
439

31b7f2792   Kload   Upgrade to ownclo...
440
441
442
443
  			if ($this->rmdir($path1) === false) {
  				$this->rmdir($path2);
  				return false;
  			}
03e52840d   Kload   Init
444
  		}
31b7f2792   Kload   Upgrade to ownclo...
445
  		return true;
03e52840d   Kload   Init
446
  	}
31b7f2792   Kload   Upgrade to ownclo...
447
448
  	public function getId() {
  		return $this->id;
03e52840d   Kload   Init
449
  	}
31b7f2792   Kload   Upgrade to ownclo...
450
451
  	public function getConnection() {
  		return $this->connection;
03e52840d   Kload   Init
452
  	}
31b7f2792   Kload   Upgrade to ownclo...
453
454
455
  	public function writeBack($tmpFile) {
  		if (!isset(self::$tmpFiles[$tmpFile])) {
  			return false;
03e52840d   Kload   Init
456
  		}
31b7f2792   Kload   Upgrade to ownclo...
457
458
459
460
461
462
463
  
  		$object = $this->container->DataObject();
  		$object->Create(array(
  			'name' => self::$tmpFiles[$tmpFile],
  			'content_type' => \OC_Helper::getMimeType($tmpFile)
  		), $tmpFile);
  		unlink($tmpFile);
03e52840d   Kload   Init
464
465
  	}
  }