You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
4.9 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
2 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /**
  2. * @file bloblist.c
  3. * @brief implemantation of functions for list structure to hold data of unspecified
  4. * format (hence, "blob list"); can contain additional format information in structure's mime info
  5. * @license GNU General Public License 3.0 - see LICENSE.txt
  6. */
  7. #include <stdbool.h>
  8. #include <stdlib.h>
  9. #include <assert.h>
  10. #include <string.h>
  11. #include "platform.h"
  12. #include "bloblist.h"
  13. static bool set_blob_data(bloblist_t* bloblist, char* blob, size_t size, const char* mime_type,
  14. const char* filename)
  15. {
  16. if (!bloblist)
  17. return false;
  18. if (mime_type) {
  19. bloblist->mime_type = strdup(mime_type);
  20. if (bloblist->mime_type == NULL) {
  21. return false;
  22. }
  23. }
  24. if (filename) {
  25. bloblist->filename = strdup(filename);
  26. if (bloblist->filename == NULL) {
  27. free(bloblist->mime_type);
  28. return false;
  29. }
  30. /* Default behaviour, can be overwritten post-allocation with
  31. set_blob_content_disposition */
  32. if (strncmp(filename, "cid://", 6) == 0)
  33. bloblist->disposition = PEP_CONTENT_DISP_INLINE;
  34. }
  35. if (blob) {
  36. bloblist->value = blob;
  37. bloblist->size = size;
  38. }
  39. return true;
  40. }
  41. DYNAMIC_API bloblist_t *new_bloblist(char *blob, size_t size, const char *mime_type,
  42. const char *filename)
  43. {
  44. bloblist_t * bloblist = calloc(1, sizeof(bloblist_t));
  45. assert(bloblist);
  46. if (bloblist == NULL)
  47. return NULL;
  48. if (!set_blob_data(bloblist, blob, size, mime_type, filename)) {
  49. free(bloblist);
  50. bloblist = NULL;
  51. }
  52. return bloblist;
  53. }
  54. DYNAMIC_API void free_bloblist(bloblist_t *bloblist)
  55. {
  56. bloblist_t *curr = bloblist;
  57. while (curr) {
  58. bloblist_t *next = curr->next;
  59. if (curr->release_value)
  60. curr->release_value(curr->value);
  61. else
  62. free(curr->value);
  63. free(curr->mime_type);
  64. free(curr->filename);
  65. free(curr);
  66. curr = next;
  67. }
  68. }
  69. DYNAMIC_API bloblist_t *bloblist_dup(const bloblist_t *src)
  70. {
  71. assert(src);
  72. if (src == NULL)
  73. return NULL;
  74. bloblist_t* head_ptr = NULL;
  75. bloblist_t** dst_curr_ptr = &head_ptr;
  76. const bloblist_t* src_curr = src;
  77. char* blob2 = NULL;
  78. for ( ; src_curr; src_curr = src_curr->next, dst_curr_ptr = &((*dst_curr_ptr)->next)) {
  79. blob2 = malloc(src_curr->size);
  80. assert(blob2);
  81. if (blob2 == NULL)
  82. goto enomem;
  83. // This is why we don't calloc
  84. memcpy(blob2, src_curr->value, src_curr->size);
  85. *dst_curr_ptr = new_bloblist(blob2, src_curr->size, src_curr->mime_type, src_curr->filename);
  86. if (*dst_curr_ptr == NULL)
  87. goto enomem;
  88. }
  89. if (!head_ptr)
  90. return NULL;
  91. return head_ptr;
  92. enomem:
  93. free(blob2);
  94. free_bloblist(head_ptr);
  95. return NULL;
  96. }
  97. DYNAMIC_API bloblist_t *bloblist_add(bloblist_t *bloblist, char *blob, size_t size,
  98. const char *mime_type, const char *filename)
  99. {
  100. assert(blob);
  101. if (!blob)
  102. return NULL;
  103. if (!bloblist)
  104. return new_bloblist(blob, size, mime_type, filename);
  105. if (!bloblist->value) { // empty list
  106. assert(!bloblist->next);
  107. if (bloblist->next)
  108. return NULL; // invalid list
  109. if (!set_blob_data(bloblist, blob, size, mime_type, filename)) {
  110. free(bloblist);
  111. bloblist = NULL;
  112. }
  113. return bloblist;
  114. }
  115. bloblist_t* list_curr = bloblist;
  116. void (*release_value)(char *) = list_curr->release_value;
  117. while (list_curr->next)
  118. list_curr = list_curr->next;
  119. list_curr->next = new_bloblist(blob, size, mime_type, filename);
  120. list_curr->next->release_value = release_value;
  121. assert(list_curr->next);
  122. if (!list_curr->next)
  123. return NULL;
  124. return list_curr->next;
  125. }
  126. DYNAMIC_API bloblist_t* bloblist_join(bloblist_t* first, bloblist_t* second) {
  127. if (!first)
  128. return second;
  129. if (!second)
  130. return first;
  131. if (first == second)
  132. return first;
  133. bloblist_t* list_curr = first;
  134. while (list_curr->next) {
  135. list_curr = list_curr->next;
  136. }
  137. list_curr->next = second;
  138. return first;
  139. }
  140. DYNAMIC_API int bloblist_length(const bloblist_t *bloblist)
  141. {
  142. int len = 0;
  143. for (const bloblist_t *_bl = bloblist; _bl && _bl->value; _bl = _bl->next)
  144. len++;
  145. return len;
  146. }
  147. DYNAMIC_API void set_blob_disposition(bloblist_t* blob,
  148. content_disposition_type disposition)
  149. {
  150. if (blob)
  151. blob->disposition = disposition;
  152. }
  153. bloblist_t* find_blob_by_URI(bloblist_t* bloblist, const char* uri) {
  154. if (!bloblist || !uri)
  155. return NULL;
  156. bloblist_t* retval = bloblist;
  157. for (; retval ; retval = retval->next) {
  158. if (retval->filename && strcmp(retval->filename, uri) == 0) {
  159. break;
  160. }
  161. }
  162. return retval;
  163. }