Skip to content

Commit 47599e6

Browse files
committed
metadata implemented
1 parent b1c4a70 commit 47599e6

File tree

7 files changed

+100
-16
lines changed

7 files changed

+100
-16
lines changed

.idea/files_external_ipfs.iml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/php.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/phpunit.xml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ This app allows you to use IPFS as an external storage for Nextcloud.
66

77
_Place this app in **nextcloud/apps/**_
88

9-
## Important Notes
10-
- unless you create a private IPFS swarm all files will be public *[How to](https://github.com/ahester57/ipfs-private-swarm)*
11-
129
## Documentation
1310
- **[Getting Started](docs/README.md)**
1411
- [Changelog](CHANGELOG.md)
1512

13+
## Notes
14+
- unless you create a private IPFS swarm all files will be public *[How to](https://github.com/ahester57/ipfs-private-swarm)*
15+
- `js-ipfs` <= `v0.40` and `go-ipfs` dont have write support

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
{
2-
"name": "Files IPFS",
2+
"name": "IPFS for Nextcloud",
33
"description": "IPFS Backend for file storage",
44
"type": "project",
55
"license": "AGPL",
66
"authors": [
77
{
8-
"name": "Carlo Meier"
8+
"name": "V31L"
99
}
1010
],
1111
"require": {
12+
"ext-curl": "*"
1213
},
1314
"require-dev": {
14-
"phpunit/phpunit": "^5.4"
15+
"phpunit/phpunit": "^5.7"
1516
}
1617
}

lib/Storage/Adapter.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,19 @@ public function __construct(string $host, string $root) {
4646
* @param array $data POST data
4747
* @return bool|string false or the body of the response
4848
*/
49-
private function callAPI(string $url, array $params = [], array $data = []) {
49+
private function callAPI(string $url, array $params = [], MultipartData $data = null) {
5050
$curl = curl_init();
5151

5252
curl_setopt($curl, CURLOPT_POST, 1);
53-
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
53+
54+
if (!empty($data)) $data->apply($curl);
5455

5556
if (!empty($params)) $url = sprintf("%s?%s", $url, http_build_query($params));
5657

5758
curl_setopt($curl, CURLOPT_URL, "{$this->host}{$url}");
5859
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
5960

6061
$result = curl_exec($curl);
61-
6262
curl_close($curl);
6363

6464
return $result;
@@ -88,6 +88,7 @@ private function normalizeFile(array $entry, $root = false) {
8888
'path' => $root ? ltrim("{$root}/{$entry['Name']}", '/') : $entry['Name'],
8989
'timestamp' => isset($entry['Mtime']) ? $entry['Mtime'] : time(),
9090
'size' => $entry['Size'],
91+
'visibility' => isset($entry['Mode']) && substr($entry['Mode'], 2) != '00' ? 'public' : 'private',
9192
];
9293
}
9394

@@ -101,17 +102,16 @@ private function normalizeFile(array $entry, $root = false) {
101102
* @return array|bool metadata of false if the operation failed
102103
*/
103104
private function upload(string $path, string $contents, Config $config ,$append = false) {
104-
$args = ['arg' => "/{$path}", 'create' => true, 'mode' => $this->permissions['file']['public']];
105+
$args = ['arg' => "/{$path}", 'create' => 'true'];
105106

106107
if ($append) {
107108
$meta = $this->getMetadata($path);
108109
$args['offset'] = $meta['size'];
109-
} else $args['truncate'] = true;
110+
} else $args['truncate'] = 'true';
110111

111-
if (in_array($config->get('visibility'), ['public', 'private']))
112-
$args['mode'] = $this->permissions['file'][$config->get('visibility')];
112+
$mode = in_array($config->get('visibility'), ['public', 'private']) ? $this->permissions['file'][$config->get('visibility')] : $this->permissions['file']['public'];
113113

114-
$response = $this->callAPI('/files/write', $args, ['data' => $contents]);
114+
$response = $this->callAPI('/files/write', $args, new MultipartData($contents, $path, $mode));
115115

116116
if ($response != '') return false; // On error return false
117117

@@ -190,7 +190,7 @@ public function getTimestamp($path) {
190190
}
191191

192192
public function getVisibility($path) {
193-
//TODO
193+
return $this->getMetadata($path);
194194
}
195195

196196
/**
@@ -263,6 +263,6 @@ public function createDir($dirname, Config $config) {
263263

264264
public function setVisibility($path, $visibility) {
265265
$mode = $this->permissions[$this->getMetadata($path)['type']][$visibility];
266-
$this->callAPI('/files/chmod', ['arg' => $path, 'mode' => $mode]);
266+
$this->callAPI('/files/chmod', ['arg' => $path, 'mode' => sprintf('%o', $mode)]);
267267
}
268268
}

lib/Storage/MultipartData.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace OCA\Files_External_IPFS\Storage;
4+
5+
/**
6+
* Class MultipartData
7+
* @package OCA\Files_External_IPFS\Storage
8+
* @author V31L <[email protected]>
9+
*/
10+
class MultipartData {
11+
private $content, $path, $mode, $mtime, $mime, $delimiter, $data, $fields;
12+
13+
public function __construct($content, string $path, int $mode, int $mtime = null, string $mime = 'application/octet-stream') {
14+
$this->content = $content;
15+
$this->mode = sprintf('0%o', $mode);
16+
$this->mtime = empty($mtime) ? time() : $mtime;
17+
$this->path = $path;
18+
$this->mime = $mime;
19+
$this->delimiter = '-------------' . uniqid();
20+
}
21+
22+
/**
23+
* @param array $fields
24+
*/
25+
public function setFields(array $fields) {
26+
$this->fields = $fields;
27+
}
28+
29+
/**
30+
* @param $curl
31+
*/
32+
public function apply($curl) {
33+
$this->data = '';
34+
35+
// populate normal fields
36+
foreach ($this->fields as $name => $content) {
37+
$this->data .= "--{$this->delimiter}\r\n";
38+
$this->data .= "Content-Disposition: form-data; name=\"{$name}\"\r\n{$content}\r\n\r\n";
39+
}
40+
41+
// populate file field
42+
$this->data .= "--" . $this->delimiter . "\r\n";
43+
$this->data .= "Content-Disposition: form-data; name=\"file\"; filename=\"{$this->path}\"\r\n";
44+
$this->data .= "Content-Type: {$this->mime}\r\n";
45+
$this->data .= "mode: {$this->mode}\r\n";
46+
$this->data .= "mtime: {$this->mtime}\r\n";
47+
$this->data .= $this->content . "\r\n";
48+
49+
// last delimiter
50+
$this->data .= "--" . $this->delimiter . "--\r\n";
51+
52+
// Add data to curl request
53+
curl_setopt($curl, CURLOPT_HTTPHEADER, $this->getHeaders());
54+
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
55+
}
56+
57+
/**
58+
* @return string[]
59+
*/
60+
private function getHeaders() {
61+
return [
62+
"Content-Type: multipart/form-data; boundary={$this->delimiter}",
63+
'Content-Length: ' . strlen($this->data)
64+
];
65+
}
66+
}

0 commit comments

Comments
 (0)