ruby-libstorj 0.0.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +14 -2
- data/ext/libstorj/.gitignore +1 -0
- data/ext/libstorj/CONTRIBUTING.md +66 -0
- data/ext/libstorj/Doxyfile +1 -1
- data/ext/libstorj/README.md +6 -1
- data/ext/libstorj/configure.ac +1 -1
- data/ext/libstorj/release.sh +61 -0
- data/ext/libstorj/src/Makefile.am +2 -2
- data/ext/libstorj/src/bip39.c +5 -0
- data/ext/libstorj/src/cli.c +542 -459
- data/ext/libstorj/src/cli_callback.c +1173 -0
- data/ext/libstorj/src/cli_callback.h +175 -0
- data/ext/libstorj/src/crypto.c +98 -4
- data/ext/libstorj/src/crypto.h +51 -0
- data/ext/libstorj/src/downloader.c +2 -3
- data/ext/libstorj/src/storj.c +371 -123
- data/ext/libstorj/src/storj.h +96 -4
- data/ext/libstorj/src/uploader.c +46 -50
- data/ext/libstorj/src/utils.c +48 -0
- data/ext/libstorj/src/utils.h +12 -0
- data/ext/libstorj/test/mockbridge.c +11 -1
- data/ext/libstorj/test/mockbridge.json +3 -0
- data/ext/libstorj/test/tests.c +132 -20
- data/ruby-libstorj.gemspec +1 -1
- data/spec/helpers/{options.yml.example → options.example.yml} +6 -3
- metadata +7 -3
@@ -0,0 +1,175 @@
|
|
1
|
+
/**
|
2
|
+
* @file storjapi_callback.h
|
3
|
+
* @brief Storj callback library.
|
4
|
+
*
|
5
|
+
* Implements callback functionality that can be customised for
|
6
|
+
* end user's application
|
7
|
+
*/
|
8
|
+
|
9
|
+
#ifndef CLI_CALLBACK_H
|
10
|
+
#define CLI_CALLBACK_H
|
11
|
+
|
12
|
+
#ifdef __cplusplus
|
13
|
+
extern "C" {
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#include "storj.h"
|
17
|
+
|
18
|
+
#define CLI_NO_SUCH_FILE_OR_DIR 0x00
|
19
|
+
#define CLI_VALID_REGULAR_FILE 0x01
|
20
|
+
#define CLI_VALID_DIR 0x02
|
21
|
+
#define CLI_UNKNOWN_FILE_ATTR 0x03
|
22
|
+
#define CLI_UPLOAD_FILE_LOG_ERR 0x04
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @brief A Structure for passing the User's Application info to
|
26
|
+
* Storj API.
|
27
|
+
*/
|
28
|
+
typedef struct cli_api {
|
29
|
+
storj_env_t *env;
|
30
|
+
char *bucket_name;
|
31
|
+
char bucket_id[256];
|
32
|
+
char *file_name;
|
33
|
+
char file_id[256];
|
34
|
+
char *file_path; /**< local upload files directory path */
|
35
|
+
FILE *src_fd;
|
36
|
+
char src_list[256]; /**< file list ready to upload */
|
37
|
+
char *src_file; /**< next file ready to upload */
|
38
|
+
FILE *dst_fd;
|
39
|
+
char *dst_file; /**< next file ready to upload */
|
40
|
+
int xfer_count; /**< # of files xferred (up/down) */
|
41
|
+
int total_files; /**< total files to upload */
|
42
|
+
char *last_cmd_req; /**< last command requested */
|
43
|
+
char *curr_cmd_req; /**< cli curr command requested */
|
44
|
+
char *next_cmd_req; /**< cli curr command requested */
|
45
|
+
char *final_cmd_req; /**< final command in the seq */
|
46
|
+
char *excp_cmd_resp; /**< expected cmd response */
|
47
|
+
char *rcvd_cmd_resp; /**< received cmd response */
|
48
|
+
int error_status; /**< command response/error status */
|
49
|
+
storj_log_levels_t *log;
|
50
|
+
void *handle;
|
51
|
+
} cli_api_t;
|
52
|
+
|
53
|
+
/**
|
54
|
+
* @brief Callback function listing bucket names & IDs
|
55
|
+
*/
|
56
|
+
void get_buckets_callback(uv_work_t *work_req, int status);
|
57
|
+
|
58
|
+
/**
|
59
|
+
* @brief Callback function returning the bucket id for a given
|
60
|
+
* bucket name
|
61
|
+
*/
|
62
|
+
void get_bucket_id_callback(uv_work_t *work_req, int status);
|
63
|
+
|
64
|
+
/**
|
65
|
+
* @brief Callback function returning the file id for a given
|
66
|
+
* file name
|
67
|
+
*/
|
68
|
+
void get_file_id_callback(uv_work_t *work_req, int status);
|
69
|
+
|
70
|
+
/**
|
71
|
+
* @brief Storj api state machine function
|
72
|
+
*/
|
73
|
+
void queue_next_cmd_req(cli_api_t *cli_api);
|
74
|
+
|
75
|
+
/**
|
76
|
+
* @brief Function lists the bucket names & IDs
|
77
|
+
*
|
78
|
+
* @param[in] cli_api_t structure that passes user's input
|
79
|
+
* info
|
80
|
+
* @return A non-zero error value on failure and 0 on success.
|
81
|
+
*/
|
82
|
+
int cli_list_buckets(cli_api_t *cli_api);
|
83
|
+
|
84
|
+
/**
|
85
|
+
* @brief Function returns the corresponding bucket's id for a
|
86
|
+
* given bucket name
|
87
|
+
*
|
88
|
+
* @param[in] cli_api_t structure that passes user's input
|
89
|
+
* info
|
90
|
+
* @return A non-zero error value on failure and 0 on success.
|
91
|
+
*/
|
92
|
+
int cli_get_bucket_id(cli_api_t *cli_api);
|
93
|
+
|
94
|
+
/**
|
95
|
+
* @brief Function to list files in a given bucket name
|
96
|
+
*
|
97
|
+
* @param[in] cli_api_t structure that passes user's input
|
98
|
+
* info
|
99
|
+
* @return A non-zero error value on failure and 0 on success.
|
100
|
+
*/
|
101
|
+
int cli_list_files(cli_api_t *cli_api);
|
102
|
+
|
103
|
+
/**
|
104
|
+
* @brief Function to remove a given bucket name
|
105
|
+
*
|
106
|
+
* @param[in] cli_api_t structure that passes user's input
|
107
|
+
* info
|
108
|
+
* @return A non-zero error value on failure and 0 on success.
|
109
|
+
*/
|
110
|
+
int cli_remove_bucket(cli_api_t *cli_api);
|
111
|
+
|
112
|
+
/**
|
113
|
+
* @brief Function to remove a file from a given bucket name
|
114
|
+
*
|
115
|
+
* @param[in] cli_api_t structure that passes user's input
|
116
|
+
* info
|
117
|
+
* @return A non-zero error value on failure and 0 on success.
|
118
|
+
*/
|
119
|
+
int cli_remove_file(cli_api_t *cli_api);
|
120
|
+
|
121
|
+
/**
|
122
|
+
* @brief Function to return the node IDs for a given file for a
|
123
|
+
* given bucket name
|
124
|
+
*
|
125
|
+
* @param[in] cli_api_t structure that passes user's input
|
126
|
+
* info
|
127
|
+
* @return A non-zero error value on failure and 0 on success.
|
128
|
+
*/
|
129
|
+
int cli_list_mirrors(cli_api_t *cli_api);
|
130
|
+
|
131
|
+
/**
|
132
|
+
* @brief Function to upload a local file into a given bucket
|
133
|
+
* name
|
134
|
+
*
|
135
|
+
* @param[in] cli_api_t structure that passes user's input
|
136
|
+
* info
|
137
|
+
* @return A non-zero error value on failure and 0 on success.
|
138
|
+
*/
|
139
|
+
int cli_upload_file(cli_api_t *cli_api);
|
140
|
+
|
141
|
+
/**
|
142
|
+
* @brief Function to upload local files into a given bucket
|
143
|
+
* name
|
144
|
+
*
|
145
|
+
* @param[in] cli_api_t structure that passes user's input
|
146
|
+
* info
|
147
|
+
* @return A non-zero error value on failure and 0 on success.
|
148
|
+
*/
|
149
|
+
int cli_upload_files(cli_api_t *cli_api);
|
150
|
+
|
151
|
+
/**
|
152
|
+
* @brief Function to download a file from a given bucket to a
|
153
|
+
* local folder
|
154
|
+
*
|
155
|
+
* @param[in] cli_api_t structure that passes user's input
|
156
|
+
* info
|
157
|
+
* @return A non-zero error value on failure and 0 on success.
|
158
|
+
*/
|
159
|
+
int cli_download_file(cli_api_t *cli_api);
|
160
|
+
|
161
|
+
/**
|
162
|
+
* @brief Function to download files from a given bucket to a
|
163
|
+
* local folder
|
164
|
+
*
|
165
|
+
* @param[in] cli_api_t structure that passes user's input
|
166
|
+
* info
|
167
|
+
* @return A non-zero error value on failure and 0 on success.
|
168
|
+
*/
|
169
|
+
int cli_download_files(cli_api_t *cli_api);
|
170
|
+
|
171
|
+
#ifdef __cplusplus
|
172
|
+
}
|
173
|
+
#endif
|
174
|
+
|
175
|
+
#endif /* CLI_CALLBACK_H */
|
data/ext/libstorj/src/crypto.c
CHANGED
@@ -141,6 +141,98 @@ cleanup:
|
|
141
141
|
return status;
|
142
142
|
}
|
143
143
|
|
144
|
+
int decrypt_bucket_name(const char *mnemonic, const char *encrypted_name, char **decrypted_name) {
|
145
|
+
return decrypt_file_name(mnemonic, BUCKET_NAME_MAGIC, encrypted_name, decrypted_name);
|
146
|
+
}
|
147
|
+
|
148
|
+
int decrypt_file_name(const char *mnemonic, const char* bucket_id,
|
149
|
+
const char *encrypted_name, char **decrypted_name) {
|
150
|
+
int status = 0;
|
151
|
+
|
152
|
+
// Derive a key based on the bucket id
|
153
|
+
char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
|
154
|
+
generate_bucket_key(mnemonic, bucket_id, &bucket_key_as_str);
|
155
|
+
|
156
|
+
uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
|
157
|
+
if (!bucket_key) {
|
158
|
+
status = 1;
|
159
|
+
goto cleanup;
|
160
|
+
}
|
161
|
+
|
162
|
+
// Get encryption key with first half of hmac w/ magic
|
163
|
+
struct hmac_sha512_ctx ctx1;
|
164
|
+
hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
|
165
|
+
hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
|
166
|
+
uint8_t key[SHA256_DIGEST_SIZE];
|
167
|
+
hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
|
168
|
+
|
169
|
+
status = decrypt_meta(encrypted_name, key, decrypted_name);
|
170
|
+
|
171
|
+
cleanup:
|
172
|
+
|
173
|
+
if (bucket_key) {
|
174
|
+
memset_zero(bucket_key, BASE16_DECODE_LENGTH(strlen(bucket_key_as_str)) + 1);
|
175
|
+
free(bucket_key);
|
176
|
+
}
|
177
|
+
if (bucket_key_as_str) {
|
178
|
+
memset_zero(bucket_key_as_str, DETERMINISTIC_KEY_SIZE + 1);
|
179
|
+
free(bucket_key_as_str);
|
180
|
+
}
|
181
|
+
|
182
|
+
return status;
|
183
|
+
}
|
184
|
+
|
185
|
+
int encrypt_bucket_name(const char *mnemonic, const char *bucket_name, char **encrypted_name) {
|
186
|
+
return encrypt_file_name(mnemonic, BUCKET_NAME_MAGIC, bucket_name, encrypted_name);
|
187
|
+
}
|
188
|
+
|
189
|
+
int encrypt_file_name(const char *mnemonic, const char* bucket_id,
|
190
|
+
const char *file_name, char **encrypted_name) {
|
191
|
+
int status = 0;
|
192
|
+
|
193
|
+
// Derive a key based on the bucket id
|
194
|
+
char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
|
195
|
+
generate_bucket_key(mnemonic, bucket_id, &bucket_key_as_str);
|
196
|
+
|
197
|
+
uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
|
198
|
+
if (!bucket_key) {
|
199
|
+
status = 1;
|
200
|
+
goto cleanup;
|
201
|
+
}
|
202
|
+
|
203
|
+
// Get encryption key with first half of hmac w/ magic
|
204
|
+
struct hmac_sha512_ctx ctx1;
|
205
|
+
hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
|
206
|
+
hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
|
207
|
+
uint8_t key[SHA256_DIGEST_SIZE];
|
208
|
+
hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
|
209
|
+
|
210
|
+
// Generate the synthetic iv with first half of hmac w/ bucket and filename
|
211
|
+
struct hmac_sha512_ctx ctx2;
|
212
|
+
hmac_sha512_set_key(&ctx2, SHA256_DIGEST_SIZE, bucket_key);
|
213
|
+
if (strcmp(bucket_id, BUCKET_NAME_MAGIC)) {
|
214
|
+
hmac_sha512_update(&ctx2, strlen(bucket_id), (uint8_t *) bucket_id);
|
215
|
+
}
|
216
|
+
hmac_sha512_update(&ctx2, strlen(file_name), (uint8_t *)file_name);
|
217
|
+
uint8_t iv[SHA256_DIGEST_SIZE];
|
218
|
+
hmac_sha512_digest(&ctx2, SHA256_DIGEST_SIZE, iv);
|
219
|
+
|
220
|
+
status = encrypt_meta(file_name, key, iv, encrypted_name);
|
221
|
+
|
222
|
+
cleanup:
|
223
|
+
|
224
|
+
if (bucket_key) {
|
225
|
+
memset_zero(bucket_key, BASE16_DECODE_LENGTH(strlen(bucket_key_as_str)) + 1);
|
226
|
+
free(bucket_key);
|
227
|
+
}
|
228
|
+
if (bucket_key_as_str) {
|
229
|
+
memset_zero(bucket_key_as_str, DETERMINISTIC_KEY_SIZE + 1);
|
230
|
+
free(bucket_key_as_str);
|
231
|
+
}
|
232
|
+
|
233
|
+
return status;
|
234
|
+
}
|
235
|
+
|
144
236
|
int get_deterministic_key(const char *key, int key_len,
|
145
237
|
const char *id, char **buffer)
|
146
238
|
{
|
@@ -462,18 +554,20 @@ int decrypt_meta(const char *buffer_base64,
|
|
462
554
|
if (!base64_decode_update(&ctx3, &decode_len, buffer,
|
463
555
|
strlen(buffer_base64), (uint8_t *)buffer_base64)) {
|
464
556
|
free(buffer);
|
465
|
-
|
557
|
+
//STORJ_META_DECRYPTION_ERROR
|
558
|
+
return 6001;
|
466
559
|
}
|
467
560
|
|
468
561
|
if (!base64_decode_final(&ctx3)) {
|
469
562
|
free(buffer);
|
470
|
-
|
563
|
+
//STORJ_META_DECRYPTION_ERROR
|
564
|
+
return 6001;
|
471
565
|
}
|
472
566
|
|
473
567
|
if (GCM_DIGEST_SIZE + SHA256_DIGEST_SIZE + 1 > decode_len) {
|
474
568
|
free(buffer);
|
475
569
|
//STORJ_META_DECRYPTION_ERROR
|
476
|
-
return
|
570
|
+
return 6001;
|
477
571
|
}
|
478
572
|
|
479
573
|
size_t length = decode_len - GCM_DIGEST_SIZE - SHA256_DIGEST_SIZE;
|
@@ -511,7 +605,7 @@ int decrypt_meta(const char *buffer_base64,
|
|
511
605
|
int digest_match = memcmp(actual_digest, digest, GCM_DIGEST_SIZE);
|
512
606
|
if (digest_match != 0) {
|
513
607
|
//STORJ_META_DECRYPTION_ERROR
|
514
|
-
return
|
608
|
+
return 6001;
|
515
609
|
}
|
516
610
|
|
517
611
|
*filemeta = calloc(length + 1, sizeof(char));
|
data/ext/libstorj/src/crypto.h
CHANGED
@@ -71,6 +71,57 @@ int generate_file_key(const char *mnemonic,
|
|
71
71
|
const char *index,
|
72
72
|
char **file_key);
|
73
73
|
|
74
|
+
/**
|
75
|
+
* @brief Decrypt a bucket name
|
76
|
+
*
|
77
|
+
* @param[in] mnemonic Character array of the mnemonic
|
78
|
+
* @param[in] encrypted_name Character array of the encrypted name
|
79
|
+
* @param[out] decrypted_name Character array of the decrypted name
|
80
|
+
* @return A non-zero error value on failure and 0 on success.
|
81
|
+
*/
|
82
|
+
int decrypt_bucket_name(const char *mnemonic,
|
83
|
+
const char *encrypted_name,
|
84
|
+
char **decrypted_name);
|
85
|
+
|
86
|
+
/**
|
87
|
+
* @brief Decrypt a file name
|
88
|
+
*
|
89
|
+
* @param[in] mnemonic Character array of the mnemonic
|
90
|
+
* @param[in] bucket_id Character array of bucket id
|
91
|
+
* @param[in] encrypted_name Character array of the encrypted name
|
92
|
+
* @param[out] decrypted_name Character array of the decrypted name
|
93
|
+
* @return A non-zero error value on failure and 0 on success.
|
94
|
+
*/
|
95
|
+
int decrypt_file_name(const char *mnemonic,
|
96
|
+
const char *bucket_id,
|
97
|
+
const char *encrypted_name,
|
98
|
+
char **decrypted_name);
|
99
|
+
/**
|
100
|
+
* @brief Encrypt a bucket name
|
101
|
+
*
|
102
|
+
* @param[in] mnemonic Character array of the mnemonic
|
103
|
+
* @param[in] bucket_name Character array of the bucket name
|
104
|
+
* @param[out] encrypted_name Character array of the encrypted name
|
105
|
+
* @return A non-zero error value on failure and 0 on success.
|
106
|
+
*/
|
107
|
+
int encrypt_bucket_name(const char *mnemonic,
|
108
|
+
const char *bucket_name,
|
109
|
+
char **encrypted_name);
|
110
|
+
|
111
|
+
/**
|
112
|
+
* @brief Encrypt a file name
|
113
|
+
*
|
114
|
+
* @param[in] mnemonic Character array of the mnemonic
|
115
|
+
* @param[in] bucket_id Character array of bucket id
|
116
|
+
* @param[in] file_name Character array of the file name
|
117
|
+
* @param[out] encrypted_name Character array of the encrypted name
|
118
|
+
* @return A non-zero error value on failure and 0 on success.
|
119
|
+
*/
|
120
|
+
int encrypt_file_name(const char *mnemonic,
|
121
|
+
const char *bucket_id,
|
122
|
+
const char *file_name,
|
123
|
+
char **encrypted_name);
|
124
|
+
|
74
125
|
/**
|
75
126
|
* @brief Calculate deterministic key by getting sha512 of key + id
|
76
127
|
*
|
@@ -1125,9 +1125,7 @@ static void determine_decryption_key_v0(storj_download_state_t *state)
|
|
1125
1125
|
|
1126
1126
|
static void determine_decryption_key(storj_download_state_t *state)
|
1127
1127
|
{
|
1128
|
-
if (!state->env->encrypt_options
|
1129
|
-
!state->env->encrypt_options->mnemonic) {
|
1130
|
-
|
1128
|
+
if (!state->env->encrypt_options) {
|
1131
1129
|
state->decrypt_key = NULL;
|
1132
1130
|
state->decrypt_ctr = NULL;
|
1133
1131
|
} else {
|
@@ -1240,6 +1238,7 @@ static void request_info(uv_work_t *work)
|
|
1240
1238
|
req->info->size = 0;
|
1241
1239
|
req->info->hmac = NULL;
|
1242
1240
|
req->info->id = NULL;
|
1241
|
+
req->info->bucket_id = NULL;
|
1243
1242
|
req->info->decrypted = false;
|
1244
1243
|
req->info->index = NULL;
|
1245
1244
|
|
data/ext/libstorj/src/storj.c
CHANGED
@@ -22,42 +22,14 @@ static void create_bucket_request_worker(uv_work_t *work)
|
|
22
22
|
create_bucket_request_t *req = work->data;
|
23
23
|
int status_code = 0;
|
24
24
|
|
25
|
-
//
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
&bucket_key_as_str);
|
30
|
-
|
31
|
-
uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
|
32
|
-
if (!bucket_key) {
|
25
|
+
// Encrypt the bucket name
|
26
|
+
if (encrypt_bucket_name(req->encrypt_options->mnemonic,
|
27
|
+
req->bucket_name,
|
28
|
+
(char **)&req->encrypted_bucket_name)) {
|
33
29
|
req->error_code = STORJ_MEMORY_ERROR;
|
34
30
|
return;
|
35
31
|
}
|
36
32
|
|
37
|
-
free(bucket_key_as_str);
|
38
|
-
|
39
|
-
// Get bucket name encryption key with first half of hmac w/ magic
|
40
|
-
struct hmac_sha512_ctx ctx1;
|
41
|
-
hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
|
42
|
-
hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
|
43
|
-
uint8_t key[SHA256_DIGEST_SIZE];
|
44
|
-
hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
|
45
|
-
|
46
|
-
// Generate the synthetic iv with first half of hmac w/ name
|
47
|
-
struct hmac_sha512_ctx ctx2;
|
48
|
-
hmac_sha512_set_key(&ctx2, SHA256_DIGEST_SIZE, bucket_key);
|
49
|
-
hmac_sha512_update(&ctx2, strlen(req->bucket_name),
|
50
|
-
(uint8_t *)req->bucket_name);
|
51
|
-
uint8_t bucketname_iv[SHA256_DIGEST_SIZE];
|
52
|
-
hmac_sha512_digest(&ctx2, SHA256_DIGEST_SIZE, bucketname_iv);
|
53
|
-
|
54
|
-
free(bucket_key);
|
55
|
-
|
56
|
-
// Encrypt the bucket name
|
57
|
-
char *encrypted_bucket_name;
|
58
|
-
encrypt_meta(req->bucket_name, key, bucketname_iv, &encrypted_bucket_name);
|
59
|
-
req->encrypted_bucket_name = encrypted_bucket_name;
|
60
|
-
|
61
33
|
struct json_object *body = json_object_new_object();
|
62
34
|
json_object *name = json_object_new_string(req->encrypted_bucket_name);
|
63
35
|
json_object_object_add(body, "name", name);
|
@@ -72,10 +44,14 @@ static void create_bucket_request_worker(uv_work_t *work)
|
|
72
44
|
req->bucket = malloc(sizeof(storj_bucket_meta_t));
|
73
45
|
|
74
46
|
struct json_object *id;
|
47
|
+
struct json_object *created;
|
48
|
+
|
75
49
|
json_object_object_get_ex(req->response, "id", &id);
|
50
|
+
json_object_object_get_ex(req->response, "created", &created);
|
76
51
|
|
77
52
|
req->bucket->id = json_object_get_string(id);
|
78
53
|
req->bucket->name = req->bucket_name;
|
54
|
+
req->bucket->created = json_object_get_string(created);
|
79
55
|
req->bucket->decrypted = true;
|
80
56
|
}
|
81
57
|
|
@@ -104,29 +80,6 @@ static void get_buckets_request_worker(uv_work_t *work)
|
|
104
80
|
req->total_buckets = num_buckets;
|
105
81
|
}
|
106
82
|
|
107
|
-
// Derive a key based on the master seed
|
108
|
-
char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
|
109
|
-
generate_bucket_key(req->encrypt_options->mnemonic,
|
110
|
-
BUCKET_NAME_MAGIC,
|
111
|
-
&bucket_key_as_str);
|
112
|
-
|
113
|
-
uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
|
114
|
-
if (!bucket_key) {
|
115
|
-
req->error_code = STORJ_MEMORY_ERROR;
|
116
|
-
return;
|
117
|
-
}
|
118
|
-
|
119
|
-
free(bucket_key_as_str);
|
120
|
-
|
121
|
-
// Get bucket name encryption key with first half of hmac w/ magic
|
122
|
-
struct hmac_sha512_ctx ctx1;
|
123
|
-
hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
|
124
|
-
hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
|
125
|
-
uint8_t key[SHA256_DIGEST_SIZE];
|
126
|
-
hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
|
127
|
-
|
128
|
-
free(bucket_key);
|
129
|
-
|
130
83
|
struct json_object *bucket_item;
|
131
84
|
struct json_object *name;
|
132
85
|
struct json_object *created;
|
@@ -154,14 +107,17 @@ static void get_buckets_request_worker(uv_work_t *work)
|
|
154
107
|
continue;
|
155
108
|
}
|
156
109
|
char *decrypted_name;
|
157
|
-
int error_status =
|
158
|
-
|
110
|
+
int error_status = decrypt_bucket_name(req->encrypt_options->mnemonic,
|
111
|
+
encrypted_name,
|
112
|
+
&decrypted_name);
|
159
113
|
if (!error_status) {
|
160
114
|
bucket->decrypted = true;
|
161
115
|
bucket->name = decrypted_name;
|
162
|
-
} else {
|
116
|
+
} else if (error_status == STORJ_META_DECRYPTION_ERROR){
|
163
117
|
bucket->decrypted = false;
|
164
118
|
bucket->name = strdup(encrypted_name);
|
119
|
+
} else {
|
120
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
165
121
|
}
|
166
122
|
}
|
167
123
|
}
|
@@ -182,29 +138,6 @@ static void get_bucket_request_worker(uv_work_t *work)
|
|
182
138
|
return;
|
183
139
|
}
|
184
140
|
|
185
|
-
// Derive a key based on the master seed
|
186
|
-
char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
|
187
|
-
generate_bucket_key(req->encrypt_options->mnemonic,
|
188
|
-
BUCKET_NAME_MAGIC,
|
189
|
-
&bucket_key_as_str);
|
190
|
-
|
191
|
-
uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
|
192
|
-
if (!bucket_key) {
|
193
|
-
req->error_code = STORJ_MEMORY_ERROR;
|
194
|
-
return;
|
195
|
-
}
|
196
|
-
|
197
|
-
free(bucket_key_as_str);
|
198
|
-
|
199
|
-
// Get bucket name encryption key with first half of hmac w/ magic
|
200
|
-
struct hmac_sha512_ctx ctx1;
|
201
|
-
hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
|
202
|
-
hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
|
203
|
-
uint8_t key[SHA256_DIGEST_SIZE];
|
204
|
-
hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
|
205
|
-
|
206
|
-
free(bucket_key);
|
207
|
-
|
208
141
|
struct json_object *name;
|
209
142
|
struct json_object *created;
|
210
143
|
struct json_object *id;
|
@@ -226,18 +159,66 @@ static void get_bucket_request_worker(uv_work_t *work)
|
|
226
159
|
const char *encrypted_name = json_object_get_string(name);
|
227
160
|
if (encrypted_name) {
|
228
161
|
char *decrypted_name;
|
229
|
-
int error_status =
|
230
|
-
|
162
|
+
int error_status = decrypt_bucket_name(req->encrypt_options->mnemonic,
|
163
|
+
encrypted_name,
|
164
|
+
&decrypted_name);
|
231
165
|
if (!error_status) {
|
232
166
|
req->bucket->decrypted = true;
|
233
167
|
req->bucket->name = decrypted_name;
|
234
|
-
} else {
|
168
|
+
} else if (error_status == STORJ_META_DECRYPTION_ERROR){
|
235
169
|
req->bucket->decrypted = false;
|
236
170
|
req->bucket->name = strdup(encrypted_name);
|
171
|
+
} else {
|
172
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
237
173
|
}
|
238
174
|
}
|
239
175
|
}
|
240
176
|
|
177
|
+
static void get_bucket_id_request_worker(uv_work_t *work)
|
178
|
+
{
|
179
|
+
get_bucket_id_request_t *req = work->data;
|
180
|
+
int status_code = 0;
|
181
|
+
|
182
|
+
// Encrypt the bucket name
|
183
|
+
char *encrypted_bucket_name;
|
184
|
+
if (encrypt_bucket_name(req->encrypt_options->mnemonic,
|
185
|
+
req->bucket_name,
|
186
|
+
&encrypted_bucket_name)) {
|
187
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
188
|
+
goto cleanup;
|
189
|
+
}
|
190
|
+
|
191
|
+
char *escaped_encrypted_bucket_name = str_replace("/", "%2F", encrypted_bucket_name);
|
192
|
+
if (!escaped_encrypted_bucket_name) {
|
193
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
194
|
+
goto cleanup;
|
195
|
+
}
|
196
|
+
|
197
|
+
char *path = str_concat_many(2, "/bucket-ids/", escaped_encrypted_bucket_name);
|
198
|
+
if (!path) {
|
199
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
200
|
+
goto cleanup;
|
201
|
+
}
|
202
|
+
|
203
|
+
req->error_code = fetch_json(req->http_options,
|
204
|
+
req->options, "GET", path, NULL,
|
205
|
+
true, &req->response, &status_code);
|
206
|
+
|
207
|
+
if (req->response != NULL) {
|
208
|
+
struct json_object *id;
|
209
|
+
json_object_object_get_ex(req->response, "id", &id);
|
210
|
+
req->bucket_id = json_object_get_string(id);
|
211
|
+
}
|
212
|
+
|
213
|
+
req->status_code = status_code;
|
214
|
+
|
215
|
+
cleanup:
|
216
|
+
|
217
|
+
free(encrypted_bucket_name);
|
218
|
+
free(escaped_encrypted_bucket_name);
|
219
|
+
free(path);
|
220
|
+
}
|
221
|
+
|
241
222
|
static void list_files_request_worker(uv_work_t *work)
|
242
223
|
{
|
243
224
|
list_files_request_t *req = work->data;
|
@@ -260,35 +241,18 @@ static void list_files_request_worker(uv_work_t *work)
|
|
260
241
|
req->total_files = num_files;
|
261
242
|
}
|
262
243
|
|
263
|
-
// Get the bucket key to encrypt the filename from bucket id
|
264
|
-
char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
|
265
|
-
generate_bucket_key(req->encrypt_options->mnemonic,
|
266
|
-
req->bucket_id,
|
267
|
-
&bucket_key_as_str);
|
268
|
-
|
269
|
-
uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
|
270
|
-
if (!bucket_key) {
|
271
|
-
req->error_code = STORJ_MEMORY_ERROR;
|
272
|
-
return;
|
273
|
-
}
|
274
|
-
|
275
|
-
free(bucket_key_as_str);
|
276
|
-
|
277
|
-
// Get file name encryption key with first half of hmac w/ magic
|
278
|
-
struct hmac_sha512_ctx ctx1;
|
279
|
-
hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
|
280
|
-
hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
|
281
|
-
uint8_t key[SHA256_DIGEST_SIZE];
|
282
|
-
hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
|
283
|
-
|
284
|
-
free(bucket_key);
|
285
|
-
|
286
244
|
struct json_object *file;
|
287
245
|
struct json_object *filename;
|
288
246
|
struct json_object *mimetype;
|
289
247
|
struct json_object *size;
|
290
248
|
struct json_object *id;
|
249
|
+
struct json_object *bucket_id;
|
291
250
|
struct json_object *created;
|
251
|
+
struct json_object *hmac;
|
252
|
+
struct json_object *hmac_value;
|
253
|
+
struct json_object *erasure;
|
254
|
+
struct json_object *erasure_type;
|
255
|
+
struct json_object *index;
|
292
256
|
|
293
257
|
for (int i = 0; i < num_files; i++) {
|
294
258
|
file = json_object_array_get_idx(req->response, i);
|
@@ -297,17 +261,24 @@ static void list_files_request_worker(uv_work_t *work)
|
|
297
261
|
json_object_object_get_ex(file, "mimetype", &mimetype);
|
298
262
|
json_object_object_get_ex(file, "size", &size);
|
299
263
|
json_object_object_get_ex(file, "id", &id);
|
264
|
+
json_object_object_get_ex(file, "bucket", &bucket_id);
|
300
265
|
json_object_object_get_ex(file, "created", &created);
|
266
|
+
json_object_object_get_ex(file, "hmac", &hmac);
|
267
|
+
json_object_object_get_ex(hmac, "value", &hmac_value);
|
268
|
+
json_object_object_get_ex(file, "erasure", &erasure);
|
269
|
+
json_object_object_get_ex(erasure, "type", &erasure_type);
|
270
|
+
json_object_object_get_ex(file, "index", &index);
|
301
271
|
|
302
272
|
storj_file_meta_t *file = &req->files[i];
|
303
273
|
|
304
274
|
file->created = json_object_get_string(created);
|
305
275
|
file->mimetype = json_object_get_string(mimetype);
|
306
276
|
file->size = json_object_get_int64(size);
|
307
|
-
file->erasure =
|
308
|
-
file->index =
|
309
|
-
file->hmac =
|
277
|
+
file->erasure = json_object_get_string(erasure_type);
|
278
|
+
file->index = json_object_get_string(index);
|
279
|
+
file->hmac = json_object_get_string(hmac_value);
|
310
280
|
file->id = json_object_get_string(id);
|
281
|
+
file->bucket_id = json_object_get_string(bucket_id);
|
311
282
|
file->decrypted = false;
|
312
283
|
file->filename = NULL;
|
313
284
|
|
@@ -320,18 +291,138 @@ static void list_files_request_worker(uv_work_t *work)
|
|
320
291
|
continue;
|
321
292
|
}
|
322
293
|
char *decrypted_file_name;
|
323
|
-
int error_status =
|
324
|
-
|
294
|
+
int error_status = decrypt_file_name(req->encrypt_options->mnemonic,
|
295
|
+
req->bucket_id,
|
296
|
+
encrypted_file_name,
|
297
|
+
&decrypted_file_name);
|
325
298
|
if (!error_status) {
|
326
299
|
file->decrypted = true;
|
327
300
|
file->filename = decrypted_file_name;
|
328
|
-
} else {
|
301
|
+
} else if (error_status == STORJ_META_DECRYPTION_ERROR) {
|
329
302
|
file->decrypted = false;
|
330
303
|
file->filename = strdup(encrypted_file_name);
|
304
|
+
} else {
|
305
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
static void get_file_info_request_worker(uv_work_t *work)
|
311
|
+
{
|
312
|
+
get_file_info_request_t *req = work->data;
|
313
|
+
int status_code = 0;
|
314
|
+
|
315
|
+
req->error_code = fetch_json(req->http_options,
|
316
|
+
req->options, req->method, req->path, req->body,
|
317
|
+
req->auth, &req->response, &status_code);
|
318
|
+
|
319
|
+
req->status_code = status_code;
|
320
|
+
|
321
|
+
struct json_object *filename;
|
322
|
+
struct json_object *mimetype;
|
323
|
+
struct json_object *size;
|
324
|
+
struct json_object *id;
|
325
|
+
struct json_object *bucket_id;
|
326
|
+
struct json_object *created;
|
327
|
+
struct json_object *hmac;
|
328
|
+
struct json_object *hmac_value;
|
329
|
+
struct json_object *erasure;
|
330
|
+
struct json_object *erasure_type;
|
331
|
+
struct json_object *index;
|
332
|
+
|
333
|
+
json_object_object_get_ex(req->response, "filename", &filename);
|
334
|
+
json_object_object_get_ex(req->response, "mimetype", &mimetype);
|
335
|
+
json_object_object_get_ex(req->response, "size", &size);
|
336
|
+
json_object_object_get_ex(req->response, "id", &id);
|
337
|
+
json_object_object_get_ex(req->response, "bucket", &bucket_id);
|
338
|
+
json_object_object_get_ex(req->response, "created", &created);
|
339
|
+
json_object_object_get_ex(req->response, "hmac", &hmac);
|
340
|
+
json_object_object_get_ex(hmac, "value", &hmac_value);
|
341
|
+
json_object_object_get_ex(req->response, "erasure", &erasure);
|
342
|
+
json_object_object_get_ex(erasure, "type", &erasure_type);
|
343
|
+
json_object_object_get_ex(req->response, "index", &index);
|
344
|
+
|
345
|
+
req->file = malloc(sizeof(storj_file_meta_t));
|
346
|
+
req->file->created = json_object_get_string(created);
|
347
|
+
req->file->mimetype = json_object_get_string(mimetype);
|
348
|
+
req->file->size = json_object_get_int64(size);
|
349
|
+
req->file->erasure = json_object_get_string(erasure_type);
|
350
|
+
req->file->index = json_object_get_string(index);
|
351
|
+
req->file->hmac = json_object_get_string(hmac_value);
|
352
|
+
req->file->id = json_object_get_string(id);
|
353
|
+
req->file->bucket_id = json_object_get_string(bucket_id);
|
354
|
+
req->file->decrypted = false;
|
355
|
+
req->file->filename = NULL;
|
356
|
+
|
357
|
+
// Attempt to decrypt the filename, otherwise
|
358
|
+
// we will default the filename to the encrypted text.
|
359
|
+
// The decrypted flag will be set to indicate the status
|
360
|
+
// of decryption for alternative display.
|
361
|
+
const char *encrypted_file_name = json_object_get_string(filename);
|
362
|
+
if (encrypted_file_name) {
|
363
|
+
char *decrypted_file_name;
|
364
|
+
int error_status = decrypt_file_name(req->encrypt_options->mnemonic,
|
365
|
+
req->bucket_id,
|
366
|
+
encrypted_file_name,
|
367
|
+
&decrypted_file_name);
|
368
|
+
if (!error_status) {
|
369
|
+
req->file->decrypted = true;
|
370
|
+
req->file->filename = decrypted_file_name;
|
371
|
+
} else if (error_status == STORJ_META_DECRYPTION_ERROR) {
|
372
|
+
req->file->decrypted = false;
|
373
|
+
req->file->filename = strdup(encrypted_file_name);
|
374
|
+
} else {
|
375
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
331
376
|
}
|
332
377
|
}
|
333
378
|
}
|
334
379
|
|
380
|
+
static void get_file_id_request_worker(uv_work_t *work)
|
381
|
+
{
|
382
|
+
get_file_id_request_t *req = work->data;
|
383
|
+
int status_code = 0;
|
384
|
+
|
385
|
+
char *encrypted_file_name;
|
386
|
+
if (encrypt_file_name(req->encrypt_options->mnemonic,
|
387
|
+
req->bucket_id,
|
388
|
+
req->file_name,
|
389
|
+
&encrypted_file_name)) {
|
390
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
391
|
+
goto cleanup;
|
392
|
+
}
|
393
|
+
|
394
|
+
char *escaped_encrypted_file_name = str_replace("/", "%2F", encrypted_file_name);
|
395
|
+
if (!escaped_encrypted_file_name) {
|
396
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
397
|
+
goto cleanup;
|
398
|
+
}
|
399
|
+
|
400
|
+
char *path = str_concat_many(4, "/buckets/", req->bucket_id,
|
401
|
+
"/file-ids/", escaped_encrypted_file_name);
|
402
|
+
if (!path) {
|
403
|
+
req->error_code = STORJ_MEMORY_ERROR;
|
404
|
+
goto cleanup;
|
405
|
+
}
|
406
|
+
|
407
|
+
req->error_code = fetch_json(req->http_options,
|
408
|
+
req->options, "GET", path, NULL,
|
409
|
+
true, &req->response, &status_code);
|
410
|
+
|
411
|
+
if (req->response != NULL) {
|
412
|
+
struct json_object *id;
|
413
|
+
json_object_object_get_ex(req->response, "id", &id);
|
414
|
+
req->file_id = json_object_get_string(id);
|
415
|
+
}
|
416
|
+
|
417
|
+
req->status_code = status_code;
|
418
|
+
|
419
|
+
cleanup:
|
420
|
+
|
421
|
+
free(encrypted_file_name);
|
422
|
+
free(escaped_encrypted_file_name);
|
423
|
+
free(path);
|
424
|
+
}
|
425
|
+
|
335
426
|
static uv_work_t *uv_work_new()
|
336
427
|
{
|
337
428
|
uv_work_t *work = malloc(sizeof(uv_work_t));
|
@@ -401,6 +492,39 @@ static list_files_request_t *list_files_request_new(
|
|
401
492
|
return req;
|
402
493
|
}
|
403
494
|
|
495
|
+
static get_file_info_request_t *get_file_info_request_new(
|
496
|
+
storj_http_options_t *http_options,
|
497
|
+
storj_bridge_options_t *options,
|
498
|
+
storj_encrypt_options_t *encrypt_options,
|
499
|
+
const char *bucket_id,
|
500
|
+
char *method,
|
501
|
+
char *path,
|
502
|
+
struct json_object *request_body,
|
503
|
+
bool auth,
|
504
|
+
void *handle)
|
505
|
+
{
|
506
|
+
get_file_info_request_t *req = malloc(sizeof(get_file_info_request_t));
|
507
|
+
if (!req) {
|
508
|
+
return NULL;
|
509
|
+
}
|
510
|
+
|
511
|
+
req->http_options = http_options;
|
512
|
+
req->options = options;
|
513
|
+
req->encrypt_options = encrypt_options;
|
514
|
+
req->bucket_id = bucket_id;
|
515
|
+
req->method = method;
|
516
|
+
req->path = path;
|
517
|
+
req->auth = auth;
|
518
|
+
req->body = request_body;
|
519
|
+
req->response = NULL;
|
520
|
+
req->file = NULL;
|
521
|
+
req->error_code = 0;
|
522
|
+
req->status_code = 0;
|
523
|
+
req->handle = handle;
|
524
|
+
|
525
|
+
return req;
|
526
|
+
}
|
527
|
+
|
404
528
|
static create_bucket_request_t *create_bucket_request_new(
|
405
529
|
storj_http_options_t *http_options,
|
406
530
|
storj_bridge_options_t *bridge_options,
|
@@ -490,6 +614,58 @@ static get_bucket_request_t *get_bucket_request_new(
|
|
490
614
|
return req;
|
491
615
|
}
|
492
616
|
|
617
|
+
static get_bucket_id_request_t *get_bucket_id_request_new(
|
618
|
+
storj_http_options_t *http_options,
|
619
|
+
storj_bridge_options_t *options,
|
620
|
+
storj_encrypt_options_t *encrypt_options,
|
621
|
+
const char *bucket_name,
|
622
|
+
void *handle)
|
623
|
+
{
|
624
|
+
get_bucket_id_request_t *req = malloc(sizeof(get_bucket_id_request_t));
|
625
|
+
if (!req) {
|
626
|
+
return NULL;
|
627
|
+
}
|
628
|
+
|
629
|
+
req->http_options = http_options;
|
630
|
+
req->options = options;
|
631
|
+
req->encrypt_options = encrypt_options;
|
632
|
+
req->bucket_name = bucket_name;
|
633
|
+
req->response = NULL;
|
634
|
+
req->bucket_id = NULL;
|
635
|
+
req->error_code = 0;
|
636
|
+
req->status_code = 0;
|
637
|
+
req->handle = handle;
|
638
|
+
|
639
|
+
return req;
|
640
|
+
}
|
641
|
+
|
642
|
+
static get_file_id_request_t *get_file_id_request_new(
|
643
|
+
storj_http_options_t *http_options,
|
644
|
+
storj_bridge_options_t *options,
|
645
|
+
storj_encrypt_options_t *encrypt_options,
|
646
|
+
const char *bucket_id,
|
647
|
+
const char *file_name,
|
648
|
+
void *handle)
|
649
|
+
{
|
650
|
+
get_file_id_request_t *req = malloc(sizeof(get_file_id_request_t));
|
651
|
+
if (!req) {
|
652
|
+
return NULL;
|
653
|
+
}
|
654
|
+
|
655
|
+
req->http_options = http_options;
|
656
|
+
req->options = options;
|
657
|
+
req->encrypt_options = encrypt_options;
|
658
|
+
req->bucket_id = bucket_id;
|
659
|
+
req->file_name = file_name;
|
660
|
+
req->response = NULL;
|
661
|
+
req->file_id = NULL;
|
662
|
+
req->error_code = 0;
|
663
|
+
req->status_code = 0;
|
664
|
+
req->handle = handle;
|
665
|
+
|
666
|
+
return req;
|
667
|
+
}
|
668
|
+
|
493
669
|
static uv_work_t *json_request_work_new(
|
494
670
|
storj_env_t *env,
|
495
671
|
char *method,
|
@@ -1190,7 +1366,9 @@ STORJ_API int storj_bridge_get_buckets(storj_env_t *env, void *handle, uv_after_
|
|
1190
1366
|
|
1191
1367
|
STORJ_API void storj_free_get_buckets_request(get_buckets_request_t *req)
|
1192
1368
|
{
|
1193
|
-
|
1369
|
+
if (req->response) {
|
1370
|
+
json_object_put(req->response);
|
1371
|
+
}
|
1194
1372
|
if (req->buckets && req->total_buckets > 0) {
|
1195
1373
|
for (int i = 0; i < req->total_buckets; i++) {
|
1196
1374
|
free((char *)req->buckets[i].name);
|
@@ -1271,7 +1449,9 @@ STORJ_API int storj_bridge_get_bucket(storj_env_t *env,
|
|
1271
1449
|
|
1272
1450
|
STORJ_API void storj_free_get_bucket_request(get_bucket_request_t *req)
|
1273
1451
|
{
|
1274
|
-
|
1452
|
+
if (req->response) {
|
1453
|
+
json_object_put(req->response);
|
1454
|
+
}
|
1275
1455
|
free(req->path);
|
1276
1456
|
if (req->bucket) {
|
1277
1457
|
free((char *)req->bucket->name);
|
@@ -1280,6 +1460,27 @@ STORJ_API void storj_free_get_bucket_request(get_bucket_request_t *req)
|
|
1280
1460
|
free(req);
|
1281
1461
|
}
|
1282
1462
|
|
1463
|
+
STORJ_API int storj_bridge_get_bucket_id(storj_env_t *env,
|
1464
|
+
const char *name,
|
1465
|
+
void *handle,
|
1466
|
+
uv_after_work_cb cb)
|
1467
|
+
{
|
1468
|
+
uv_work_t *work = uv_work_new();
|
1469
|
+
if (!work) {
|
1470
|
+
return STORJ_MEMORY_ERROR;
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
work->data = get_bucket_id_request_new(env->http_options,
|
1474
|
+
env->bridge_options,
|
1475
|
+
env->encrypt_options,
|
1476
|
+
name, handle);
|
1477
|
+
if (!work->data) {
|
1478
|
+
return STORJ_MEMORY_ERROR;
|
1479
|
+
}
|
1480
|
+
|
1481
|
+
return uv_queue_work(env->loop, (uv_work_t*) work, get_bucket_id_request_worker, cb);
|
1482
|
+
}
|
1483
|
+
|
1283
1484
|
STORJ_API int storj_bridge_list_files(storj_env_t *env,
|
1284
1485
|
const char *id,
|
1285
1486
|
void *handle,
|
@@ -1310,7 +1511,9 @@ STORJ_API int storj_bridge_list_files(storj_env_t *env,
|
|
1310
1511
|
|
1311
1512
|
STORJ_API void storj_free_list_files_request(list_files_request_t *req)
|
1312
1513
|
{
|
1313
|
-
|
1514
|
+
if (req->response) {
|
1515
|
+
json_object_put(req->response);
|
1516
|
+
}
|
1314
1517
|
free(req->path);
|
1315
1518
|
if (req->files && req->total_files > 0) {
|
1316
1519
|
for (int i = 0; i < req->total_files; i++) {
|
@@ -1452,10 +1655,10 @@ STORJ_API int storj_bridge_delete_frame(storj_env_t *env,
|
|
1452
1655
|
}
|
1453
1656
|
|
1454
1657
|
STORJ_API int storj_bridge_get_file_info(storj_env_t *env,
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1658
|
+
const char *bucket_id,
|
1659
|
+
const char *file_id,
|
1660
|
+
void *handle,
|
1661
|
+
uv_after_work_cb cb)
|
1459
1662
|
{
|
1460
1663
|
char *path = str_concat_many(5, "/buckets/", bucket_id, "/files/",
|
1461
1664
|
file_id, "/info");
|
@@ -1463,13 +1666,58 @@ STORJ_API int storj_bridge_get_file_info(storj_env_t *env,
|
|
1463
1666
|
return STORJ_MEMORY_ERROR;
|
1464
1667
|
}
|
1465
1668
|
|
1466
|
-
uv_work_t *work =
|
1467
|
-
true, handle);
|
1669
|
+
uv_work_t *work = uv_work_new();
|
1468
1670
|
if (!work) {
|
1469
1671
|
return STORJ_MEMORY_ERROR;
|
1470
1672
|
}
|
1471
1673
|
|
1472
|
-
|
1674
|
+
work->data = get_file_info_request_new(env->http_options,
|
1675
|
+
env->bridge_options,
|
1676
|
+
env->encrypt_options,
|
1677
|
+
bucket_id, "GET", path,
|
1678
|
+
NULL, true, handle);
|
1679
|
+
|
1680
|
+
if (!work->data) {
|
1681
|
+
return STORJ_MEMORY_ERROR;
|
1682
|
+
}
|
1683
|
+
|
1684
|
+
return uv_queue_work(env->loop, (uv_work_t*) work,
|
1685
|
+
get_file_info_request_worker, cb);
|
1686
|
+
}
|
1687
|
+
|
1688
|
+
STORJ_API int storj_bridge_get_file_id(storj_env_t *env,
|
1689
|
+
const char *bucket_id,
|
1690
|
+
const char *file_name,
|
1691
|
+
void *handle,
|
1692
|
+
uv_after_work_cb cb)
|
1693
|
+
{
|
1694
|
+
uv_work_t *work = uv_work_new();
|
1695
|
+
if (!work) {
|
1696
|
+
return STORJ_MEMORY_ERROR;
|
1697
|
+
}
|
1698
|
+
|
1699
|
+
work->data = get_file_id_request_new(env->http_options,
|
1700
|
+
env->bridge_options,
|
1701
|
+
env->encrypt_options,
|
1702
|
+
bucket_id, file_name, handle);
|
1703
|
+
if (!work->data) {
|
1704
|
+
return STORJ_MEMORY_ERROR;
|
1705
|
+
}
|
1706
|
+
|
1707
|
+
return uv_queue_work(env->loop, (uv_work_t*) work, get_file_id_request_worker, cb);
|
1708
|
+
}
|
1709
|
+
|
1710
|
+
STORJ_API void storj_free_get_file_info_request(get_file_info_request_t *req)
|
1711
|
+
{
|
1712
|
+
if (req->response) {
|
1713
|
+
json_object_put(req->response);
|
1714
|
+
}
|
1715
|
+
free(req->path);
|
1716
|
+
if (req->file) {
|
1717
|
+
free((char *)req->file->filename);
|
1718
|
+
}
|
1719
|
+
free(req->file);
|
1720
|
+
free(req);
|
1473
1721
|
}
|
1474
1722
|
|
1475
1723
|
STORJ_API int storj_bridge_list_mirrors(storj_env_t *env,
|