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

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

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

31b7f2792   Kload   Upgrade to ownclo...
248
249
  		if ($path !== '.') {
  			$path .= '/';
03e52840d   Kload   Init
250
  		}
03e52840d   Kload   Init
251

31b7f2792   Kload   Upgrade to ownclo...
252
253
  		if ($this->doesObjectExist($path)) {
  			return 'dir';
03e52840d   Kload   Init
254
  		}
03e52840d   Kload   Init
255
256
257
  	}
  
  	public function unlink($path) {
31b7f2792   Kload   Upgrade to ownclo...
258
259
260
261
262
263
264
265
266
267
  		$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
268
269
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
270
271
  
  		return true;
03e52840d   Kload   Init
272
273
274
  	}
  
  	public function fopen($path, $mode) {
31b7f2792   Kload   Upgrade to ownclo...
275
276
277
  		$path = $this->normalizePath($path);
  
  		switch ($mode) {
03e52840d   Kload   Init
278
279
  			case 'r':
  			case 'rb':
31b7f2792   Kload   Upgrade to ownclo...
280
281
282
283
284
285
  				$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
286
287
  					return false;
  				}
31b7f2792   Kload   Upgrade to ownclo...
288
289
290
291
292
293
294
  				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
295
296
297
298
299
300
301
302
303
304
305
306
  			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...
307
308
309
310
311
312
  				if (strrpos($path, '.') !== false) {
  					$ext = substr($path, strrpos($path, '.'));
  				} else {
  					$ext = '';
  				}
  				$tmpFile = \OC_Helper::tmpFile($ext);
03e52840d   Kload   Init
313
  				\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
31b7f2792   Kload   Upgrade to ownclo...
314
315
316
317
318
319
320
  				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
321
322
  		}
  	}
31b7f2792   Kload   Upgrade to ownclo...
323
324
325
326
327
328
329
330
  	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
331
  		}
31b7f2792   Kload   Upgrade to ownclo...
332
  		return false;
03e52840d   Kload   Init
333
  	}
31b7f2792   Kload   Upgrade to ownclo...
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
  	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
  				)
  			);
  			return $object->Update($settings);
  		} 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
365
  		}
31b7f2792   Kload   Upgrade to ownclo...
366
367
368
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
  	}
  
  	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
411
  		}
31b7f2792   Kload   Upgrade to ownclo...
412
  		return true;
03e52840d   Kload   Init
413
414
415
  	}
  
  	public function rename($path1, $path2) {
31b7f2792   Kload   Upgrade to ownclo...
416
417
  		$path1 = $this->normalizePath($path1);
  		$path2 = $this->normalizePath($path2);
03e52840d   Kload   Init
418

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

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

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

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