ruby-libstorj 0.0.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/ext/libstorj/src/storj.h
CHANGED
@@ -284,6 +284,20 @@ typedef struct {
|
|
284
284
|
void *handle;
|
285
285
|
} get_bucket_request_t;
|
286
286
|
|
287
|
+
/** @brief A structure for queueing get bucket id request work
|
288
|
+
*/
|
289
|
+
typedef struct {
|
290
|
+
storj_http_options_t *http_options;
|
291
|
+
storj_encrypt_options_t *encrypt_options;
|
292
|
+
storj_bridge_options_t *options;
|
293
|
+
const char *bucket_name;
|
294
|
+
struct json_object *response;
|
295
|
+
const char *bucket_id;
|
296
|
+
int error_code;
|
297
|
+
int status_code;
|
298
|
+
void *handle;
|
299
|
+
} get_bucket_id_request_t;
|
300
|
+
|
287
301
|
/** @brief A structure for that describes a bucket entry/file
|
288
302
|
*/
|
289
303
|
typedef struct {
|
@@ -294,6 +308,7 @@ typedef struct {
|
|
294
308
|
uint64_t size;
|
295
309
|
const char *hmac;
|
296
310
|
const char *id;
|
311
|
+
const char *bucket_id;
|
297
312
|
bool decrypted;
|
298
313
|
const char *index;
|
299
314
|
} storj_file_meta_t;
|
@@ -317,6 +332,39 @@ typedef struct {
|
|
317
332
|
void *handle;
|
318
333
|
} list_files_request_t;
|
319
334
|
|
335
|
+
/** @brief A structure for queueing get file info request work
|
336
|
+
*/
|
337
|
+
typedef struct {
|
338
|
+
storj_http_options_t *http_options;
|
339
|
+
storj_encrypt_options_t *encrypt_options;
|
340
|
+
storj_bridge_options_t *options;
|
341
|
+
const char *bucket_id;
|
342
|
+
char *method;
|
343
|
+
char *path;
|
344
|
+
bool auth;
|
345
|
+
struct json_object *body;
|
346
|
+
struct json_object *response;
|
347
|
+
storj_file_meta_t *file;
|
348
|
+
int error_code;
|
349
|
+
int status_code;
|
350
|
+
void *handle;
|
351
|
+
} get_file_info_request_t;
|
352
|
+
|
353
|
+
/** @brief A structure for queueing get file id request work
|
354
|
+
*/
|
355
|
+
typedef struct {
|
356
|
+
storj_http_options_t *http_options;
|
357
|
+
storj_encrypt_options_t *encrypt_options;
|
358
|
+
storj_bridge_options_t *options;
|
359
|
+
const char *bucket_id;
|
360
|
+
const char *file_name;
|
361
|
+
struct json_object *response;
|
362
|
+
const char *file_id;
|
363
|
+
int error_code;
|
364
|
+
int status_code;
|
365
|
+
void *handle;
|
366
|
+
} get_file_id_request_t;
|
367
|
+
|
320
368
|
typedef enum {
|
321
369
|
BUCKET_PUSH,
|
322
370
|
BUCKET_PULL
|
@@ -356,7 +404,7 @@ typedef void (*storj_finished_download_cb)(int status, FILE *fd, void *handle);
|
|
356
404
|
|
357
405
|
/** @brief A function signature for an upload complete callback
|
358
406
|
*/
|
359
|
-
typedef void (*storj_finished_upload_cb)(int error_status,
|
407
|
+
typedef void (*storj_finished_upload_cb)(int error_status, storj_file_meta_t *file, void *handle);
|
360
408
|
|
361
409
|
/** @brief A structure that represents a pointer to a shard
|
362
410
|
*
|
@@ -484,7 +532,7 @@ typedef struct {
|
|
484
532
|
uint32_t shard_concurrency;
|
485
533
|
const char *index;
|
486
534
|
const char *file_name;
|
487
|
-
|
535
|
+
storj_file_meta_t *info;
|
488
536
|
const char *encrypted_file_name;
|
489
537
|
FILE *original_file;
|
490
538
|
uint64_t file_size;
|
@@ -758,7 +806,7 @@ STORJ_API int storj_bridge_delete_bucket(storj_env_t *env,
|
|
758
806
|
* @brief Get a info of specific bucket.
|
759
807
|
*
|
760
808
|
* @param[in] env The storj environment struct
|
761
|
-
* @param[in]
|
809
|
+
* @param[in] id The bucket id
|
762
810
|
* @param[in] handle A pointer that will be available in the callback
|
763
811
|
* @param[in] cb A function called with response when complete
|
764
812
|
* @return A non-zero error value on failure and 0 on success.
|
@@ -775,6 +823,20 @@ STORJ_API int storj_bridge_get_bucket(storj_env_t *env,
|
|
775
823
|
*/
|
776
824
|
STORJ_API void storj_free_get_bucket_request(get_bucket_request_t *req);
|
777
825
|
|
826
|
+
/**
|
827
|
+
* @brief Get the bucket id by name.
|
828
|
+
*
|
829
|
+
* @param[in] env The storj environment struct
|
830
|
+
* @param[in] name The bucket name
|
831
|
+
* @param[in] handle A pointer that will be available in the callback
|
832
|
+
* @param[in] cb A function called with response when complete
|
833
|
+
* @return A non-zero error value on failure and 0 on success.
|
834
|
+
*/
|
835
|
+
STORJ_API int storj_bridge_get_bucket_id(storj_env_t *env,
|
836
|
+
const char *name,
|
837
|
+
void *handle,
|
838
|
+
uv_after_work_cb cb);
|
839
|
+
|
778
840
|
/**
|
779
841
|
* @brief Get a list of all files in a bucket.
|
780
842
|
*
|
@@ -901,7 +963,7 @@ STORJ_API int storj_bridge_delete_frame(storj_env_t *env,
|
|
901
963
|
*
|
902
964
|
* @param[in] env The storj environment struct
|
903
965
|
* @param[in] bucket_id The bucket id
|
904
|
-
* @param[in] file_id The
|
966
|
+
* @param[in] file_id The file id
|
905
967
|
* @param[in] handle A pointer that will be available in the callback
|
906
968
|
* @param[in] cb A function called with response when complete
|
907
969
|
* @return A non-zero error value on failure and 0 on success.
|
@@ -912,6 +974,29 @@ STORJ_API int storj_bridge_get_file_info(storj_env_t *env,
|
|
912
974
|
void *handle,
|
913
975
|
uv_after_work_cb cb);
|
914
976
|
|
977
|
+
/**
|
978
|
+
* @brief Will free all structs for get file info request
|
979
|
+
*
|
980
|
+
* @param[in] req - The work request from storj_bridge_get_file_info callback
|
981
|
+
*/
|
982
|
+
STORJ_API void storj_free_get_file_info_request(get_file_info_request_t *req);
|
983
|
+
|
984
|
+
/**
|
985
|
+
* @brief Get the file id by name.
|
986
|
+
*
|
987
|
+
* @param[in] env The storj environment struct
|
988
|
+
* @param[in] bucket_id The bucket id
|
989
|
+
* @param[in] file_name The file name
|
990
|
+
* @param[in] handle A pointer that will be available in the callback
|
991
|
+
* @param[in] cb A function called with response when complete
|
992
|
+
* @return A non-zero error value on failure and 0 on success.
|
993
|
+
*/
|
994
|
+
STORJ_API int storj_bridge_get_file_id(storj_env_t *env,
|
995
|
+
const char *bucket_id,
|
996
|
+
const char *file_name,
|
997
|
+
void *handle,
|
998
|
+
uv_after_work_cb cb);
|
999
|
+
|
915
1000
|
/**
|
916
1001
|
* @brief Get mirror data for a file
|
917
1002
|
*
|
@@ -953,6 +1038,13 @@ STORJ_API storj_upload_state_t *storj_bridge_store_file(storj_env_t *env,
|
|
953
1038
|
storj_progress_cb progress_cb,
|
954
1039
|
storj_finished_upload_cb finished_cb);
|
955
1040
|
|
1041
|
+
/**
|
1042
|
+
* @brief Will free the file info struct passed to the upload finished callback
|
1043
|
+
*
|
1044
|
+
* @param[in] file - The storj_file_meta_t struct from storj_finished_upload_cb callback
|
1045
|
+
*/
|
1046
|
+
STORJ_API void storj_free_uploaded_file_info(storj_file_meta_t *file);
|
1047
|
+
|
956
1048
|
/**
|
957
1049
|
* @brief Will cancel a download
|
958
1050
|
*
|
data/ext/libstorj/src/uploader.c
CHANGED
@@ -248,10 +248,6 @@ static void cleanup_state(storj_upload_state_t *state)
|
|
248
248
|
free(state->frame_id);
|
249
249
|
}
|
250
250
|
|
251
|
-
if (state->hmac_id) {
|
252
|
-
free(state->hmac_id);
|
253
|
-
}
|
254
|
-
|
255
251
|
if (state->encrypted_file_name) {
|
256
252
|
free((char *)state->encrypted_file_name);
|
257
253
|
}
|
@@ -260,6 +256,10 @@ static void cleanup_state(storj_upload_state_t *state)
|
|
260
256
|
free(state->exclude);
|
261
257
|
}
|
262
258
|
|
259
|
+
if (state->index) {
|
260
|
+
free((char *)state->index);
|
261
|
+
}
|
262
|
+
|
263
263
|
if (state->encryption_ctr) {
|
264
264
|
free(state->encryption_ctr);
|
265
265
|
}
|
@@ -286,10 +286,6 @@ static void cleanup_state(storj_upload_state_t *state)
|
|
286
286
|
free(state->encrypted_file_path);
|
287
287
|
}
|
288
288
|
|
289
|
-
if (state->index) {
|
290
|
-
free((char *)state->index);
|
291
|
-
}
|
292
|
-
|
293
289
|
if (state->shard) {
|
294
290
|
for (int i = 0; i < state->total_shards; i++ ) {
|
295
291
|
|
@@ -309,7 +305,7 @@ static void cleanup_state(storj_upload_state_t *state)
|
|
309
305
|
free(state->shard);
|
310
306
|
}
|
311
307
|
|
312
|
-
state->finished_cb(state->error_status, state->
|
308
|
+
state->finished_cb(state->error_status, state->info, state->handle);
|
313
309
|
|
314
310
|
free(state);
|
315
311
|
}
|
@@ -358,17 +354,36 @@ static void after_create_bucket_entry(uv_work_t *work, int status)
|
|
358
354
|
req->log->info(state->env->log_options, state->handle,
|
359
355
|
"Successfully Added bucket entry");
|
360
356
|
|
357
|
+
req->log->debug(state->env->log_options, state->handle,
|
358
|
+
"fn[after_create_bucket_entry] - JSON Response: %s", json_object_to_json_string(req->response));
|
359
|
+
|
361
360
|
state->add_bucket_entry_count = 0;
|
362
361
|
state->completed_upload = true;
|
363
362
|
|
363
|
+
state->info = malloc(sizeof(storj_file_meta_t));
|
364
|
+
state->info->created = NULL;
|
365
|
+
state->info->filename = state->file_name;
|
366
|
+
state->info->mimetype = NULL;
|
367
|
+
state->info->erasure = NULL;
|
368
|
+
state->info->size = state->file_size;
|
369
|
+
state->info->hmac = state->hmac_id;
|
370
|
+
state->info->id = NULL;
|
371
|
+
state->info->bucket_id = state->bucket_id;
|
372
|
+
state->info->decrypted = true;
|
373
|
+
state->info->index = strdup(state->index);
|
374
|
+
|
364
375
|
struct json_object *file_id_value = NULL;
|
365
|
-
|
376
|
+
struct json_object *created_value = NULL;
|
377
|
+
struct json_object *mimetype_value = NULL;
|
378
|
+
|
366
379
|
if (json_object_object_get_ex(req->response, "id", &file_id_value)) {
|
367
|
-
|
380
|
+
state->info->id = strdup((char *)json_object_get_string(file_id_value));
|
368
381
|
}
|
369
|
-
|
370
|
-
|
371
|
-
|
382
|
+
if (json_object_object_get_ex(req->response, "created", &created_value)) {
|
383
|
+
state->info->created = strdup((char *)json_object_get_string(created_value));
|
384
|
+
}
|
385
|
+
if (json_object_object_get_ex(req->response, "mimetype", &mimetype_value)) {
|
386
|
+
state->info->mimetype = strdup((char *)json_object_get_string(mimetype_value));
|
372
387
|
}
|
373
388
|
|
374
389
|
} else if (state->add_bucket_entry_count == 6) {
|
@@ -2133,7 +2148,6 @@ static void verify_bucket_id_callback(uv_work_t *work_req, int status)
|
|
2133
2148
|
clean_variables:
|
2134
2149
|
queue_next_work(state);
|
2135
2150
|
|
2136
|
-
json_object_put(req->response);
|
2137
2151
|
storj_free_get_bucket_request(req);
|
2138
2152
|
free(work_req);
|
2139
2153
|
}
|
@@ -2460,44 +2474,14 @@ static void prepare_upload_state(uv_work_t *work)
|
|
2460
2474
|
state->shard[i].work = NULL;
|
2461
2475
|
}
|
2462
2476
|
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
&bucket_key_as_str);
|
2468
|
-
|
2469
|
-
uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
|
2470
|
-
if (!bucket_key) {
|
2477
|
+
if (encrypt_file_name(state->env->encrypt_options->mnemonic,
|
2478
|
+
state->bucket_id,
|
2479
|
+
state->file_name,
|
2480
|
+
(char **)&state->encrypted_file_name)) {
|
2471
2481
|
state->error_status = STORJ_MEMORY_ERROR;
|
2472
2482
|
return;
|
2473
2483
|
}
|
2474
2484
|
|
2475
|
-
free(bucket_key_as_str);
|
2476
|
-
|
2477
|
-
// Get file name encryption key with first half of hmac w/ magic
|
2478
|
-
struct hmac_sha512_ctx ctx1;
|
2479
|
-
hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
|
2480
|
-
hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
|
2481
|
-
uint8_t key[SHA256_DIGEST_SIZE];
|
2482
|
-
hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
|
2483
|
-
|
2484
|
-
// Generate the synthetic iv with first half of hmac w/ bucket and filename
|
2485
|
-
struct hmac_sha512_ctx ctx2;
|
2486
|
-
hmac_sha512_set_key(&ctx2, SHA256_DIGEST_SIZE, bucket_key);
|
2487
|
-
hmac_sha512_update(&ctx2, strlen(state->bucket_id),
|
2488
|
-
(uint8_t *)state->bucket_id);
|
2489
|
-
hmac_sha512_update(&ctx2, strlen(state->file_name),
|
2490
|
-
(uint8_t *)state->file_name);
|
2491
|
-
uint8_t filename_iv[SHA256_DIGEST_SIZE];
|
2492
|
-
hmac_sha512_digest(&ctx2, SHA256_DIGEST_SIZE, filename_iv);
|
2493
|
-
|
2494
|
-
free(bucket_key);
|
2495
|
-
|
2496
|
-
char *encrypted_file_name;
|
2497
|
-
encrypt_meta(state->file_name, key, filename_iv, &encrypted_file_name);
|
2498
|
-
|
2499
|
-
state->encrypted_file_name = encrypted_file_name;
|
2500
|
-
|
2501
2485
|
uint8_t *index = NULL;
|
2502
2486
|
char *key_as_str = NULL;
|
2503
2487
|
|
@@ -2663,7 +2647,7 @@ STORJ_API storj_upload_state_t *storj_bridge_store_file(storj_env_t *env,
|
|
2663
2647
|
} else {
|
2664
2648
|
state->index = NULL;
|
2665
2649
|
}
|
2666
|
-
state->
|
2650
|
+
state->info = NULL;
|
2667
2651
|
state->file_name = opts->file_name;
|
2668
2652
|
state->encrypted_file_name = NULL;
|
2669
2653
|
state->original_file = opts->fd;
|
@@ -2734,3 +2718,15 @@ STORJ_API storj_upload_state_t *storj_bridge_store_file(storj_env_t *env,
|
|
2734
2718
|
}
|
2735
2719
|
return state;
|
2736
2720
|
}
|
2721
|
+
|
2722
|
+
STORJ_API void storj_free_uploaded_file_info(storj_file_meta_t *file)
|
2723
|
+
{
|
2724
|
+
if (file) {
|
2725
|
+
free((char *)file->id);
|
2726
|
+
free((char *)file->created);
|
2727
|
+
free((char *)file->mimetype);
|
2728
|
+
free((char *)file->hmac);
|
2729
|
+
free((char *)file->index);
|
2730
|
+
}
|
2731
|
+
free(file);
|
2732
|
+
}
|
data/ext/libstorj/src/utils.c
CHANGED
@@ -80,6 +80,54 @@ char *str_concat_many(int count, ...)
|
|
80
80
|
return combined;
|
81
81
|
}
|
82
82
|
|
83
|
+
char *str_replace(char *search, char *replace, char *subject) {
|
84
|
+
char *result; // the return string
|
85
|
+
char *ins; // the next insert point
|
86
|
+
char *tmp; // varies
|
87
|
+
size_t len_search; // length of search (the string to remove)
|
88
|
+
size_t len_replace; // length of replace (the string to replace search with)
|
89
|
+
size_t len_front; // distance between search and end of last replace
|
90
|
+
int count; // number of replacements
|
91
|
+
|
92
|
+
// sanity checks and initialization
|
93
|
+
if (!subject || !search)
|
94
|
+
return NULL;
|
95
|
+
len_search = strlen(search);
|
96
|
+
if (len_search == 0)
|
97
|
+
return NULL; // empty search causes infinite loop during count
|
98
|
+
if (!replace)
|
99
|
+
replace = "";
|
100
|
+
len_replace = strlen(replace);
|
101
|
+
|
102
|
+
// count the number of replacements needed
|
103
|
+
ins = subject;
|
104
|
+
tmp = strstr(ins, search);
|
105
|
+
for (count = 0; tmp != NULL; ++count) {
|
106
|
+
ins = tmp + len_search;
|
107
|
+
tmp = strstr(ins, search);
|
108
|
+
}
|
109
|
+
|
110
|
+
tmp = result = malloc(strlen(subject) + (len_replace - len_search) * count + 1);
|
111
|
+
|
112
|
+
if (!result)
|
113
|
+
return NULL;
|
114
|
+
|
115
|
+
// first time through the loop, all the variable are set correctly
|
116
|
+
// from here on,
|
117
|
+
// tmp points to the end of the result string
|
118
|
+
// ins points to the next occurrence of search in subject
|
119
|
+
// orig points to the remainder of subject after "end of search"
|
120
|
+
while (count--) {
|
121
|
+
ins = strstr(subject, search);
|
122
|
+
len_front = ins - subject;
|
123
|
+
tmp = strncpy(tmp, subject, len_front) + len_front;
|
124
|
+
tmp = strcpy(tmp, replace) + len_replace;
|
125
|
+
subject += len_front + len_search; // move to next "end of search"
|
126
|
+
}
|
127
|
+
strcpy(tmp, subject);
|
128
|
+
return result;
|
129
|
+
}
|
130
|
+
|
83
131
|
void random_buffer(uint8_t *buf, size_t len)
|
84
132
|
{
|
85
133
|
static FILE *frand = NULL;
|
data/ext/libstorj/src/utils.h
CHANGED
@@ -48,6 +48,18 @@ uint8_t *str2hex(size_t length, char *data);
|
|
48
48
|
|
49
49
|
char *str_concat_many(int count, ...);
|
50
50
|
|
51
|
+
/**
|
52
|
+
* @brief Replace all occurrences of the search string with the replacement string
|
53
|
+
*
|
54
|
+
* The result string from this function must be freed.
|
55
|
+
*
|
56
|
+
* @param[in] search The value being searched for, otherwise known as the needle
|
57
|
+
* @param[in] replace The replacement value that replaces found search values
|
58
|
+
* @param[in] subject The string being searched and replaced on, otherwise known as the haystack.
|
59
|
+
* @return A null value on error, otherwise a string with replaced values.
|
60
|
+
*/
|
61
|
+
char *str_replace(char *search, char *replace, char *subject);
|
62
|
+
|
51
63
|
void random_buffer(uint8_t *buf, size_t len);
|
52
64
|
|
53
65
|
uint64_t shard_size(int hops);
|
@@ -90,7 +90,12 @@ int mock_bridge_server(void *cls,
|
|
90
90
|
page = get_response_string(responses, "getbucket");
|
91
91
|
status_code = MHD_HTTP_OK;
|
92
92
|
}
|
93
|
-
} else if (0 == strcmp(url, "/
|
93
|
+
} else if (0 == strcmp(url, "/bucket-ids/g9qacwq2AE1+5nzL/HYyYdY9WoIr+1ueOuVEx6/IzzZKK9sULoKDDdYvhOpavHH2P3xQNw==")) {
|
94
|
+
if (check_auth(user, pass, &status_code, page)) {
|
95
|
+
page = get_response_string(responses, "getbucketid");
|
96
|
+
status_code = MHD_HTTP_OK;
|
97
|
+
}
|
98
|
+
} else if (0 == strcmp(url, "/buckets/368be0816766b28fd5f43af5/files")) {
|
94
99
|
if (check_auth(user, pass, &status_code, page)) {
|
95
100
|
page = get_response_string(responses, "listfiles");
|
96
101
|
status_code = MHD_HTTP_OK;
|
@@ -100,6 +105,11 @@ int mock_bridge_server(void *cls,
|
|
100
105
|
page = get_response_string(responses, "getfileinfo");
|
101
106
|
status_code = MHD_HTTP_OK;
|
102
107
|
}
|
108
|
+
} else if (0 == strcmp(url, "/buckets/368be0816766b28fd5f43af5/file-ids/QR6/qHizNFm+t+4vSvr575xVp2R3/rC/qFlmOH10HsdGQtofpUUqwEdaZUJI0jPIImYMZFu6cZDrMIvJtcK3pHAb+kkPv0Y5")) {
|
109
|
+
if (check_auth(user, pass, &status_code, page)) {
|
110
|
+
page = get_response_string(responses, "getfileid");
|
111
|
+
status_code = MHD_HTTP_OK;
|
112
|
+
}
|
103
113
|
} else if (0 == strcmp(url, "/buckets/368be0816766b28fd5f43af5/file-ids/hTY5wsqYyLJQppCMiFQI7v2n/IZZiKb0ES1RCrUqK7Fe5m0/+fYwh+E/vp8M3FCEECle63BhlWlHi/Hj/Yg5y/bIjy8SxQ==")) {
|
104
114
|
if (check_auth(user, pass, &status_code, page)) {
|
105
115
|
status_code = MHD_HTTP_NOT_FOUND;
|
@@ -23,6 +23,9 @@
|
|
23
23
|
"name": "g9qacwq2AE1+5nzL/HYyYdY9WoIr+1ueOuVEx6/IzzZKK9sULoKDDdYvhOpavHH2P3xQNw==",
|
24
24
|
"id": "368be0816766b28fd5f43af5"
|
25
25
|
},
|
26
|
+
"getbucketid": {
|
27
|
+
"id": "368be0816766b28fd5f43af5"
|
28
|
+
},
|
26
29
|
"putbuckets": {
|
27
30
|
"user": "user@sample.com",
|
28
31
|
"encryptionKey": "",
|
data/ext/libstorj/test/tests.c
CHANGED
@@ -26,6 +26,10 @@ storj_encrypt_options_t encrypt_options = {
|
|
26
26
|
.mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
27
27
|
};
|
28
28
|
|
29
|
+
storj_encrypt_options_t encrypt_options_null_mnemonic = {
|
30
|
+
.mnemonic = NULL
|
31
|
+
};
|
32
|
+
|
29
33
|
storj_http_options_t http_options = {
|
30
34
|
.user_agent = "storj-test",
|
31
35
|
.low_speed_limit = 0,
|
@@ -99,6 +103,20 @@ void check_get_bucket(uv_work_t *work_req, int status)
|
|
99
103
|
free(work_req);
|
100
104
|
}
|
101
105
|
|
106
|
+
void check_get_bucket_id(uv_work_t *work_req, int status)
|
107
|
+
{
|
108
|
+
assert(status == 0);
|
109
|
+
get_bucket_id_request_t *req = work_req->data;
|
110
|
+
assert(req->handle == NULL);
|
111
|
+
assert(strcmp(req->bucket_id, "368be0816766b28fd5f43af5") == 0);
|
112
|
+
|
113
|
+
pass("storj_bridge_get_bucket_id");
|
114
|
+
|
115
|
+
json_object_put(req->response);
|
116
|
+
free(req);
|
117
|
+
free(work_req);
|
118
|
+
}
|
119
|
+
|
102
120
|
void check_get_buckets_badauth(uv_work_t *work_req, int status)
|
103
121
|
{
|
104
122
|
assert(status == 0);
|
@@ -188,6 +206,20 @@ void check_list_files_badauth(uv_work_t *work_req, int status)
|
|
188
206
|
free(work_req);
|
189
207
|
}
|
190
208
|
|
209
|
+
void check_get_file_id(uv_work_t *work_req, int status)
|
210
|
+
{
|
211
|
+
assert(status == 0);
|
212
|
+
get_file_id_request_t *req = work_req->data;
|
213
|
+
assert(req->handle == NULL);
|
214
|
+
assert(strcmp(req->file_id, "998960317b6725a3f8080c2b") == 0);
|
215
|
+
|
216
|
+
pass("storj_bridge_get_file_id");
|
217
|
+
|
218
|
+
json_object_put(req->response);
|
219
|
+
free(req);
|
220
|
+
free(work_req);
|
221
|
+
}
|
222
|
+
|
191
223
|
void check_bucket_tokens(uv_work_t *work_req, int status)
|
192
224
|
{
|
193
225
|
assert(status == 0);
|
@@ -261,6 +293,18 @@ void check_resolve_file(int status, FILE *fd, void *handle)
|
|
261
293
|
}
|
262
294
|
}
|
263
295
|
|
296
|
+
void check_resolve_file_null_mnemonic(int status, FILE *fd, void *handle)
|
297
|
+
{
|
298
|
+
fclose(fd);
|
299
|
+
assert(handle == NULL);
|
300
|
+
if (status == STORJ_FILE_DECRYPTION_ERROR) {
|
301
|
+
pass("storj_bridge_resolve_file_null_mnemonic");
|
302
|
+
} else {
|
303
|
+
fail("storj_bridge_resolve_file_null_mnemonic");
|
304
|
+
printf("Status: %d\n", status);
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
264
308
|
void check_resolve_file_cancel(int status, FILE *fd, void *handle)
|
265
309
|
{
|
266
310
|
fclose(fd);
|
@@ -283,11 +327,11 @@ void check_store_file_progress(double progress,
|
|
283
327
|
}
|
284
328
|
}
|
285
329
|
|
286
|
-
void check_store_file(int error_code,
|
330
|
+
void check_store_file(int error_code, storj_file_meta_t *file, void *handle)
|
287
331
|
{
|
288
332
|
assert(handle == NULL);
|
289
333
|
if (error_code == 0) {
|
290
|
-
if (strcmp(
|
334
|
+
if (file && strcmp(file->id, "85fb0ed00de1196dc22e0f6d") == 0 ) {
|
291
335
|
pass("storj_bridge_store_file");
|
292
336
|
} else {
|
293
337
|
fail("storj_bridge_store_file(0)");
|
@@ -297,10 +341,10 @@ void check_store_file(int error_code, char *file_id, void *handle)
|
|
297
341
|
printf("\t\tERROR: %s\n", storj_strerror(error_code));
|
298
342
|
}
|
299
343
|
|
300
|
-
|
344
|
+
storj_free_uploaded_file_info(file);
|
301
345
|
}
|
302
346
|
|
303
|
-
void check_store_file_cancel(int error_code,
|
347
|
+
void check_store_file_cancel(int error_code, storj_file_meta_t *file, void *handle)
|
304
348
|
{
|
305
349
|
assert(handle == NULL);
|
306
350
|
if (error_code == STORJ_TRANSFER_CANCELED) {
|
@@ -310,7 +354,7 @@ void check_store_file_cancel(int error_code, char *file_id, void *handle)
|
|
310
354
|
printf("\t\tERROR: %s\n", storj_strerror(error_code));
|
311
355
|
}
|
312
356
|
|
313
|
-
|
357
|
+
storj_free_uploaded_file_info(file);
|
314
358
|
}
|
315
359
|
|
316
360
|
void check_delete_file(uv_work_t *work_req, int status)
|
@@ -412,22 +456,15 @@ void check_delete_frame(uv_work_t *work_req, int status)
|
|
412
456
|
void check_file_info(uv_work_t *work_req, int status)
|
413
457
|
{
|
414
458
|
assert(status == 0);
|
415
|
-
|
459
|
+
get_file_info_request_t *req = work_req->data;
|
416
460
|
assert(req->handle == NULL);
|
461
|
+
assert(req->file);
|
462
|
+
assert(strcmp(req->file->filename, "storj-test-download.data") == 0);
|
463
|
+
assert(strcmp(req->file->mimetype, "video/ogg") == 0);
|
417
464
|
|
418
|
-
struct json_object *value;
|
419
|
-
int success = json_object_object_get_ex(req->response, "mimetype", &value);
|
420
|
-
assert(success == 1);
|
421
|
-
assert(json_object_is_type(value, json_type_string) == 1);
|
422
|
-
|
423
|
-
const char* mimetype = json_object_get_string(value);
|
424
|
-
|
425
|
-
assert(strcmp(mimetype, "video/ogg") == 0);
|
426
465
|
pass("storj_bridge_get_file_info");
|
427
466
|
|
428
|
-
|
429
|
-
free(req->path);
|
430
|
-
free(req);
|
467
|
+
storj_free_get_file_info_request(req);
|
431
468
|
free(work_req);
|
432
469
|
}
|
433
470
|
|
@@ -614,12 +651,12 @@ int test_upload_cancel()
|
|
614
651
|
return 0;
|
615
652
|
}
|
616
653
|
|
617
|
-
int
|
654
|
+
int _test_download(storj_encrypt_options_t *encrypt_options, void *cb_finished)
|
618
655
|
{
|
619
656
|
|
620
657
|
// initialize event loop and environment
|
621
658
|
storj_env_t *env = storj_init_env(&bridge_options,
|
622
|
-
|
659
|
+
encrypt_options,
|
623
660
|
&http_options,
|
624
661
|
&log_options);
|
625
662
|
assert(env != NULL);
|
@@ -639,7 +676,7 @@ int test_download()
|
|
639
676
|
download_fp,
|
640
677
|
NULL,
|
641
678
|
check_resolve_file_progress,
|
642
|
-
|
679
|
+
cb_finished);
|
643
680
|
|
644
681
|
if (!state || state->error_status != 0) {
|
645
682
|
return 1;
|
@@ -656,6 +693,16 @@ int test_download()
|
|
656
693
|
return 0;
|
657
694
|
}
|
658
695
|
|
696
|
+
int test_download()
|
697
|
+
{
|
698
|
+
return _test_download(&encrypt_options, check_resolve_file);
|
699
|
+
}
|
700
|
+
|
701
|
+
int test_download_null_mnemonic()
|
702
|
+
{
|
703
|
+
return _test_download(&encrypt_options_null_mnemonic, check_resolve_file_null_mnemonic);
|
704
|
+
}
|
705
|
+
|
659
706
|
int test_download_cancel()
|
660
707
|
{
|
661
708
|
|
@@ -775,6 +822,10 @@ int test_api()
|
|
775
822
|
status = storj_bridge_get_bucket(env, bucket_id, NULL, check_get_bucket);
|
776
823
|
assert(status == 0);
|
777
824
|
|
825
|
+
// get bucket id
|
826
|
+
status = storj_bridge_get_bucket_id(env, "test", NULL, check_get_bucket_id);
|
827
|
+
assert(status == 0);
|
828
|
+
|
778
829
|
// create a new bucket with a name
|
779
830
|
status = storj_bridge_create_bucket(env, "backups", NULL,
|
780
831
|
check_create_bucket);
|
@@ -791,6 +842,11 @@ int test_api()
|
|
791
842
|
check_list_files);
|
792
843
|
assert(status == 0);
|
793
844
|
|
845
|
+
// get file id
|
846
|
+
status = storj_bridge_get_file_id(env, bucket_id, "storj-test-download.data",
|
847
|
+
NULL, check_get_file_id);
|
848
|
+
assert(status == 0);
|
849
|
+
|
794
850
|
// create bucket tokens
|
795
851
|
status = storj_bridge_create_bucket_token(env,
|
796
852
|
bucket_id,
|
@@ -1106,6 +1162,31 @@ int test_generate_seed_256_trezor()
|
|
1106
1162
|
return 0;
|
1107
1163
|
}
|
1108
1164
|
|
1165
|
+
int test_generate_seed_null_mnemonic()
|
1166
|
+
{
|
1167
|
+
char *mnemonic = NULL;
|
1168
|
+
char *seed = calloc(128 + 1, sizeof(char));
|
1169
|
+
char *expected_seed = "4ed8d4b17698ddeaa1f1559f152f87b5d472f725ca86d341bd0276f1b61197e21dd5a391f9f5ed7340ff4d4513aab9cce44f9497a5e7ed85fd818876b6eb402e";
|
1170
|
+
|
1171
|
+
mnemonic_to_seed(mnemonic, "", &seed);
|
1172
|
+
seed[128] = '\0';
|
1173
|
+
|
1174
|
+
int check = memcmp(seed, expected_seed, 128);
|
1175
|
+
if (check != 0) {
|
1176
|
+
fail("test_generate_seed");
|
1177
|
+
printf("\t\texpected seed: %s\n", expected_seed);
|
1178
|
+
printf("\t\tactual seed: %s\n", seed);
|
1179
|
+
|
1180
|
+
free(seed);
|
1181
|
+
return 1;
|
1182
|
+
}
|
1183
|
+
|
1184
|
+
free(seed);
|
1185
|
+
pass("test_generate_seed_null_mnemonic");
|
1186
|
+
|
1187
|
+
return 0;
|
1188
|
+
}
|
1189
|
+
|
1109
1190
|
int test_generate_bucket_key()
|
1110
1191
|
{
|
1111
1192
|
char *mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
@@ -1524,6 +1605,34 @@ int test_memory_mapping()
|
|
1524
1605
|
return 0;
|
1525
1606
|
}
|
1526
1607
|
|
1608
|
+
int test_str_replace()
|
1609
|
+
{
|
1610
|
+
char *subject = "g9qacwq2AE1+5nzL/HYyYdY9WoIr+1ueOuVEx6/IzzZKK9sULoKDDdYvhOpavHH2P3xQNw==";
|
1611
|
+
|
1612
|
+
char *result = str_replace("/", "%2F", subject);
|
1613
|
+
if (!result) {
|
1614
|
+
fail("test_str_replace");
|
1615
|
+
return 0;
|
1616
|
+
}
|
1617
|
+
|
1618
|
+
char *expected = "g9qacwq2AE1+5nzL%2FHYyYdY9WoIr+1ueOuVEx6%2FIzzZKK9sULoKDDdYvhOpavHH2P3xQNw==";
|
1619
|
+
|
1620
|
+
int failed = 0;
|
1621
|
+
if (strcmp(expected, result) != 0) {
|
1622
|
+
failed = 1;
|
1623
|
+
}
|
1624
|
+
|
1625
|
+
if (failed) {
|
1626
|
+
fail("test_str_replace");
|
1627
|
+
} else {
|
1628
|
+
pass("test_str_replace");
|
1629
|
+
}
|
1630
|
+
|
1631
|
+
free(result);
|
1632
|
+
|
1633
|
+
return 0;
|
1634
|
+
}
|
1635
|
+
|
1527
1636
|
// Test Bridge Server
|
1528
1637
|
struct MHD_Daemon *start_test_server()
|
1529
1638
|
{
|
@@ -1569,6 +1678,7 @@ int main(void)
|
|
1569
1678
|
|
1570
1679
|
printf("Test Suite: Downloads\n");
|
1571
1680
|
test_download();
|
1681
|
+
test_download_null_mnemonic();
|
1572
1682
|
test_download_cancel();
|
1573
1683
|
printf("\n");
|
1574
1684
|
|
@@ -1580,6 +1690,7 @@ int main(void)
|
|
1580
1690
|
test_generate_seed();
|
1581
1691
|
test_generate_seed_256();
|
1582
1692
|
test_generate_seed_256_trezor();
|
1693
|
+
test_generate_seed_null_mnemonic();
|
1583
1694
|
printf("\n");
|
1584
1695
|
|
1585
1696
|
printf("Test Suite: Crypto\n");
|
@@ -1596,6 +1707,7 @@ int main(void)
|
|
1596
1707
|
test_get_time_milliseconds();
|
1597
1708
|
test_determine_shard_size();
|
1598
1709
|
test_memory_mapping();
|
1710
|
+
test_str_replace();
|
1599
1711
|
|
1600
1712
|
int num_failed = tests_ran - test_status;
|
1601
1713
|
printf(KGRN "\nPASSED: %i" RESET, test_status);
|