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.
@@ -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, char *file_id, void *handle);
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
- char *file_id;
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] bucket_id The bucket id
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 bucket id
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
  *
@@ -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->file_id, state->handle);
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
- char *file_id = NULL;
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
- file_id = (char *)json_object_get_string(file_id_value);
380
+ state->info->id = strdup((char *)json_object_get_string(file_id_value));
368
381
  }
369
-
370
- if (file_id) {
371
- state->file_id = strdup(file_id);
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
- // Get the bucket key to encrypt the filename
2464
- char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
2465
- generate_bucket_key(state->env->encrypt_options->mnemonic,
2466
- state->bucket_id,
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->file_id = NULL;
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
+ }
@@ -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;
@@ -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, "/buckets/368be0816766b28fd5f43af5/files")) {
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": "",
@@ -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, char *file_id, void *handle)
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(file_id, "85fb0ed00de1196dc22e0f6d") == 0 ) {
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
- free(file_id);
344
+ storj_free_uploaded_file_info(file);
301
345
  }
302
346
 
303
- void check_store_file_cancel(int error_code, char *file_id, void *handle)
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
- free(file_id);
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
- json_request_t *req = work_req->data;
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
- json_object_put(req->response);
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 test_download()
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
- &encrypt_options,
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
- check_resolve_file);
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);