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
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);
|