src/bloblist.c
author Krista Bennett <krista@pep-project.org>
Fri, 04 May 2018 16:30:21 +0200
branchlocal_cpptest
changeset 2652 43b913f99a27
parent 2462 48b526a0daac
permissions -rw-r--r--
Shelving broken things to break other things
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #include <stdbool.h>
     5 #include <stdlib.h>
     6 #include <assert.h>
     7 #include <string.h>
     8 
     9 #include "platform.h"
    10 #include "bloblist.h"
    11 
    12 static bool set_blob_data(bloblist_t* bloblist, char* blob, size_t size, const char* mime_type,
    13         const char* filename)
    14 {
    15     if (!bloblist)
    16         return false;
    17         
    18     if (mime_type) {
    19        bloblist->mime_type = strdup(mime_type);
    20        if (bloblist->mime_type == NULL) {
    21            return false;
    22        }
    23     }
    24     
    25     if (filename) {
    26        bloblist->filename = strdup(filename);
    27        if (bloblist->filename == NULL) {
    28            free(bloblist->mime_type);
    29            return false;
    30        }
    31        /* Default behaviour, can be overwritten post-allocation with
    32           set_blob_content_disposition */
    33        if (strncmp(filename, "cid://", 6) == 0)
    34            bloblist->disposition = PEP_CONTENT_DISP_INLINE;
    35     }               
    36     
    37     if (blob) {
    38         bloblist->value = blob;
    39         bloblist->size = size;
    40     }
    41     
    42     return true;
    43 }
    44 
    45 DYNAMIC_API bloblist_t *new_bloblist(char *blob, size_t size, const char *mime_type,
    46         const char *filename)
    47 {
    48     bloblist_t * bloblist = calloc(1, sizeof(bloblist_t));
    49     assert(bloblist);
    50     if (bloblist == NULL)
    51         return NULL;
    52 
    53     if (!set_blob_data(bloblist, blob, size, mime_type, filename)) {
    54         free(bloblist);
    55         bloblist = NULL;
    56     }
    57 
    58     return bloblist;
    59 }
    60 
    61 DYNAMIC_API void free_bloblist(bloblist_t *bloblist)
    62 {
    63     bloblist_t *curr = bloblist;
    64 
    65     while (curr) {
    66         bloblist_t *next = curr->next;
    67         if (curr->release_value)
    68             curr->release_value(curr->value);
    69         else
    70             free(curr->value);
    71         free(curr->mime_type);
    72         free(curr->filename);
    73         free(curr);
    74         curr = next;
    75     }
    76 }
    77 
    78 DYNAMIC_API bloblist_t *bloblist_dup(const bloblist_t *src)
    79 {
    80     assert(src);
    81     if (src == NULL)
    82         return NULL;
    83     
    84     bloblist_t *bloblist = NULL;
    85 
    86     // head
    87     char *blob2 = malloc(src->size);
    88     assert(blob2);
    89     if (blob2 == NULL)
    90         goto enomem;
    91 
    92     memcpy(blob2, src->value, src->size);
    93 
    94     bloblist = new_bloblist(blob2, src->size, src->mime_type, src->filename);
    95     if (bloblist == NULL)
    96         goto enomem;
    97     blob2 = NULL;
    98 
    99     bloblist_t* src_curr = src->next;
   100     bloblist_t** dst_curr_ptr = &bloblist->next;
   101 
   102     // list
   103     while (src_curr) {
   104         blob2 = malloc(src_curr->size);
   105 
   106         assert(blob2);
   107         if (blob2 == NULL)
   108             goto enomem;
   109 
   110         memcpy(blob2, src_curr->value, src_curr->size);
   111         *dst_curr_ptr = new_bloblist(blob2, src_curr->size, src_curr->mime_type, src_curr->filename);
   112         if (*dst_curr_ptr == NULL)
   113             goto enomem;
   114 
   115         src_curr = src_curr->next;
   116         dst_curr_ptr = &((*dst_curr_ptr)->next);
   117     }
   118 
   119     return bloblist;
   120 
   121 enomem:
   122     free(blob2);
   123     free_bloblist(bloblist);
   124     return NULL;
   125 }
   126 
   127 DYNAMIC_API bloblist_t *bloblist_add(bloblist_t *bloblist, char *blob, size_t size,
   128         const char *mime_type, const char *filename)
   129 {
   130     assert(blob);
   131     if (!blob)
   132         return NULL;
   133 
   134     if (!bloblist)
   135         return new_bloblist(blob, size, mime_type, filename);
   136 
   137     if (!bloblist->value) { // empty list
   138         assert(!bloblist->next);
   139         if (bloblist->next)
   140             return NULL; // invalid list
   141             
   142         if (!set_blob_data(bloblist, blob, size, mime_type, filename)) {
   143             free(bloblist);
   144             bloblist = NULL;
   145         }
   146 
   147         return bloblist;
   148     }
   149 
   150     bloblist_t* list_curr = bloblist;
   151     void (*release_value)(char *) = list_curr->release_value;
   152 
   153     while (list_curr->next)
   154         list_curr = list_curr->next;
   155 
   156     list_curr->next = new_bloblist(blob, size, mime_type, filename);
   157     list_curr->release_value = release_value;
   158 
   159     assert(list_curr->next);
   160     if (!list_curr->next)
   161         return NULL;
   162 
   163     return list_curr->next;
   164 }
   165 
   166 DYNAMIC_API int bloblist_length(const bloblist_t *bloblist)
   167 {
   168     int len = 0;
   169 
   170     for (const bloblist_t *_bl = bloblist; _bl && _bl->value; _bl = _bl->next)
   171         len++;
   172 
   173     return len;
   174 }
   175 
   176 DYNAMIC_API void set_blob_disposition(bloblist_t* blob, 
   177         content_disposition_type disposition)
   178 {
   179     if (blob)                                    
   180         blob->disposition = disposition;
   181 }