merge default into my branch rok-mac
authorRoker <roker@pep-project.org>
Mon, 18 Jul 2016 08:55:01 +0200
branchrok-mac
changeset 9068988b8816f6b
parent 874 c88b2d6f23cd
parent 904 a3c701c6109f
child 2566 5bc6ee7ca646
merge default into my branch
     1.1 --- a/Makefile	Thu Jul 14 10:23:05 2016 +0200
     1.2 +++ b/Makefile	Mon Jul 18 08:55:01 2016 +0200
     1.3 @@ -1,5 +1,9 @@
     1.4  include Makefile.conf
     1.5  
     1.6 +# add it to the environment of all executed programs:
     1.7 +export YML_PATH
     1.8 +
     1.9 +
    1.10  all:
    1.11  	$(MAKE) -C asn.1 generate
    1.12  	$(MAKE) -C asn.1
     2.1 --- a/asn.1/pEpEngineASN1/pEpEngineASN1.vcxproj	Thu Jul 14 10:23:05 2016 +0200
     2.2 +++ b/asn.1/pEpEngineASN1/pEpEngineASN1.vcxproj	Mon Jul 18 08:55:01 2016 +0200
     2.3 @@ -60,14 +60,24 @@
     2.4        <GenerateDebugInformation>true</GenerateDebugInformation>
     2.5      </Link>
     2.6      <PreBuildEvent>
     2.7 +      <Command>
     2.8 +      </Command>
     2.9 +    </PreBuildEvent>
    2.10 +    <PreBuildEvent>
    2.11 +      <Message>ASN.1 source generation</Message>
    2.12 +    </PreBuildEvent>
    2.13 +    <CustomBuildStep>
    2.14        <Command>cd ..
    2.15  asn1c -gen-PER -fincludes-quoted -fcompound-names -pdu=PEP.Message pEp.asn1 devicegroup.asn1
    2.16  del converter-sample.c
    2.17  </Command>
    2.18 -    </PreBuildEvent>
    2.19 -    <PreBuildEvent>
    2.20 -      <Message>ASN.1 source generation</Message>
    2.21 -    </PreBuildEvent>
    2.22 +    </CustomBuildStep>
    2.23 +    <CustomBuildStep>
    2.24 +      <Message>compiling ASN.1 description</Message>
    2.25 +    </CustomBuildStep>
    2.26 +    <CustomBuildStep>
    2.27 +      <Outputs>$(ProjectDir)..\DeviceGroup-Protocol.c;%(Outputs)</Outputs>
    2.28 +    </CustomBuildStep>
    2.29    </ItemDefinitionGroup>
    2.30    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    2.31      <ClCompile>
    2.32 @@ -86,11 +96,21 @@
    2.33        <OptimizeReferences>true</OptimizeReferences>
    2.34      </Link>
    2.35      <PreBuildEvent>
    2.36 +      <Command>
    2.37 +      </Command>
    2.38 +    </PreBuildEvent>
    2.39 +    <CustomBuildStep>
    2.40        <Command>cd ..
    2.41  asn1c -gen-PER -fincludes-quoted -fcompound-names -pdu=PEP.Message pEp.asn1 devicegroup.asn1
    2.42  del converter-sample.c
    2.43  </Command>
    2.44 -    </PreBuildEvent>
    2.45 +    </CustomBuildStep>
    2.46 +    <CustomBuildStep>
    2.47 +      <Message>compiling ASN.1 description</Message>
    2.48 +    </CustomBuildStep>
    2.49 +    <CustomBuildStep>
    2.50 +      <Outputs>$(ProjectDir)..\DeviceGroup-Protocol.c;%(Outputs)</Outputs>
    2.51 +    </CustomBuildStep>
    2.52    </ItemDefinitionGroup>
    2.53    <ItemGroup>
    2.54      <Text Include="ReadMe.txt" />
     3.1 --- a/pEpEngine.vcxproj	Thu Jul 14 10:23:05 2016 +0200
     3.2 +++ b/pEpEngine.vcxproj	Mon Jul 18 08:55:01 2016 +0200
     3.3 @@ -116,6 +116,7 @@
     3.4      <ClCompile Include="src\sync_actions.c" />
     3.5      <ClCompile Include="src\sync_driver.c" />
     3.6      <ClCompile Include="src\sync_fsm.c" />
     3.7 +    <ClCompile Include="src\sync_send_actions.c" />
     3.8      <ClCompile Include="src\timestamp.c" />
     3.9      <ClCompile Include="src\transport.c" />
    3.10      <ClCompile Include="src\trans_auto.c" />
     4.1 --- a/pEpEngine.vcxproj.filters	Thu Jul 14 10:23:05 2016 +0200
     4.2 +++ b/pEpEngine.vcxproj.filters	Mon Jul 18 08:55:01 2016 +0200
     4.3 @@ -90,6 +90,9 @@
     4.4      <ClCompile Include="src\baseprotocol.c">
     4.5        <Filter>Quelldateien</Filter>
     4.6      </ClCompile>
     4.7 +    <ClCompile Include="src\sync_send_actions.c">
     4.8 +      <Filter>Quelldateien</Filter>
     4.9 +    </ClCompile>
    4.10    </ItemGroup>
    4.11    <ItemGroup>
    4.12      <ClInclude Include="src\keymanagement.h">
     5.1 --- a/src/blacklist.c	Thu Jul 14 10:23:05 2016 +0200
     5.2 +++ b/src/blacklist.c	Mon Jul 18 08:55:01 2016 +0200
     5.3 @@ -115,21 +115,21 @@
     5.4      sqlite3_reset(session->blacklist_retrieve);
     5.5  
     5.6      int result;
     5.7 -    const char *fpr = NULL;
     5.8  
     5.9      stringlist_t *_bl = _blacklist;
    5.10      do {
    5.11          result = sqlite3_step(session->blacklist_retrieve);
    5.12          switch (result) {
    5.13          case SQLITE_ROW:
    5.14 -            fpr = (const char *) sqlite3_column_text(session->blacklist_retrieve, 0);
    5.15 +        {
    5.16 +            const char *fpr = (const char *) sqlite3_column_text(session->blacklist_retrieve, 0);
    5.17  
    5.18              _bl = stringlist_add(_bl, fpr);
    5.19              if (_bl == NULL)
    5.20                  goto enomem;
    5.21  
    5.22              break;
    5.23 -
    5.24 +        }
    5.25          case SQLITE_DONE:
    5.26              break;
    5.27  
     6.1 --- a/src/bloblist.c	Thu Jul 14 10:23:05 2016 +0200
     6.2 +++ b/src/bloblist.c	Mon Jul 18 08:55:01 2016 +0200
     6.3 @@ -41,13 +41,18 @@
     6.4  
     6.5  DYNAMIC_API void free_bloblist(bloblist_t *bloblist)
     6.6  {
     6.7 -    if (bloblist) {
     6.8 -        if (bloblist->next)
     6.9 -            free_bloblist(bloblist->next);
    6.10 -        free(bloblist->value);
    6.11 -        free(bloblist->mime_type);
    6.12 -        free(bloblist->filename);
    6.13 -        free(bloblist);
    6.14 +    bloblist_t *curr;
    6.15 +    bloblist_t *next;
    6.16 +    
    6.17 +    curr = bloblist;
    6.18 +    
    6.19 +    while (curr) {
    6.20 +        next = curr->next;
    6.21 +        free(curr->value);
    6.22 +        free(curr->mime_type);
    6.23 +        free(curr->filename);
    6.24 +        free(curr);
    6.25 +        curr = next;
    6.26      }
    6.27  }
    6.28  
    6.29 @@ -56,7 +61,10 @@
    6.30      bloblist_t *bloblist = NULL;
    6.31  
    6.32      assert(src);
    6.33 +    if (src == NULL)
    6.34 +        return NULL;
    6.35  
    6.36 +    // head
    6.37      char *blob2 = malloc(src->size);
    6.38      assert(blob2);
    6.39      if (blob2 == NULL)
    6.40 @@ -69,12 +77,26 @@
    6.41          goto enomem;
    6.42      blob2 = NULL;
    6.43  
    6.44 -    if (src->next) {
    6.45 -        bloblist->next = bloblist_dup(src->next);
    6.46 -        if (bloblist->next == NULL)
    6.47 +    bloblist_t* src_curr = src->next;
    6.48 +    bloblist_t** dst_curr_ptr = &bloblist->next;
    6.49 +    
    6.50 +    // list
    6.51 +    while (src_curr) {
    6.52 +        blob2 = malloc(src_curr->size);
    6.53 +
    6.54 +        assert(blob2);
    6.55 +        if (blob2 == NULL)
    6.56              goto enomem;
    6.57 +
    6.58 +        memcpy(blob2, src_curr->value, src_curr->size);
    6.59 +        *dst_curr_ptr = new_bloblist(blob2, src_curr->size, src_curr->mime_type, src_curr->filename);
    6.60 +        if (*dst_curr_ptr == NULL)
    6.61 +            goto enomem;
    6.62 +        
    6.63 +        src_curr = src_curr->next;
    6.64 +        dst_curr_ptr = &((*dst_curr_ptr)->next);
    6.65      }
    6.66 -
    6.67 +        
    6.68      return bloblist;
    6.69  
    6.70  enomem:
    6.71 @@ -87,11 +109,16 @@
    6.72          const char *mime_type, const char *filename)
    6.73  {
    6.74      assert(blob);
    6.75 -
    6.76 +    if (blob == NULL)
    6.77 +        return NULL;
    6.78 +    
    6.79      if (bloblist == NULL)
    6.80          return new_bloblist(blob, size, mime_type, filename);
    6.81  
    6.82 -    if (bloblist->value == NULL) {
    6.83 +    if (bloblist->value == NULL) { // empty list
    6.84 +        if (bloblist->next != NULL)
    6.85 +            return NULL; // invalid list
    6.86 +            
    6.87          if (mime_type) {
    6.88              bloblist->mime_type = strdup(mime_type);
    6.89              if (bloblist->mime_type == NULL) {
    6.90 @@ -108,20 +135,25 @@
    6.91              }
    6.92          }
    6.93  
    6.94 -        assert((blob == NULL && size == 0) || (blob && size));
    6.95 -
    6.96          bloblist->value = blob;
    6.97          bloblist->size = size;
    6.98  
    6.99          return bloblist;
   6.100      }
   6.101  
   6.102 -    if (bloblist->next == NULL) {
   6.103 -        bloblist->next = new_bloblist(blob, size, mime_type, filename);
   6.104 -        return bloblist->next;
   6.105 -    }
   6.106 -
   6.107 -    return bloblist_add(bloblist->next, blob, size, mime_type, filename);
   6.108 +    bloblist_t* list_curr = bloblist;
   6.109 +    
   6.110 +    while (list_curr->next)
   6.111 +        list_curr = list_curr->next;
   6.112 +    
   6.113 +    list_curr->next = new_bloblist(blob, size, mime_type, filename);
   6.114 +    
   6.115 +    assert(list_curr->next);
   6.116 +    if (list_curr->next == NULL)
   6.117 +        return NULL;
   6.118 +   
   6.119 +    return list_curr->next;
   6.120 +    
   6.121  }
   6.122  
   6.123  DYNAMIC_API int bloblist_length(const bloblist_t *bloblist)
     7.1 --- a/src/bloblist.h	Thu Jul 14 10:23:05 2016 +0200
     7.2 +++ b/src/bloblist.h	Mon Jul 18 08:55:01 2016 +0200
     7.3 @@ -68,11 +68,14 @@
     7.4  //      filename (in)  file name of the blob or NULL if unknown
     7.5  //
     7.6  //  return value:
     7.7 -//      pointer to the last element of bloblist or NULL if out of memory
     7.8 +//      pointer to the last element of bloblist or NULL if out of memory or
     7.9 +//      NULL passed in as blob value
    7.10  //
    7.11  //  caveat:
    7.12  //      the ownership of the blob goes to the bloblist; mime_type and filename
    7.13 -//      are being copied, the originals remain in the ownership of the caller
    7.14 +//      are being copied, the originals remain in the ownership of the caller.
    7.15 +//      bloblist input parameter equal to NULL or with value == NULL is a valid
    7.16 +//      empty input list.
    7.17  
    7.18  DYNAMIC_API bloblist_t *bloblist_add(bloblist_t *bloblist, char *blob, size_t size,
    7.19          const char *mime_type, const char *filename);
     8.1 --- a/src/etpan_mime.c	Thu Jul 14 10:23:05 2016 +0200
     8.2 +++ b/src/etpan_mime.c	Mon Jul 18 08:55:01 2016 +0200
     8.3 @@ -755,9 +755,10 @@
     8.4          if (_type == NULL)
     8.5              return ENOMEM;
     8.6  
     8.7 -        strcpy(_type, _main_type);
     8.8 -        strcat(_type, "/");
     8.9 -        strcat(_type, content->ct_subtype);
    8.10 +        strncpy(_type, _main_type, len);
    8.11 +        len -= strlen(_main_type);
    8.12 +        strncat(_type, "/", len--);
    8.13 +        strncat(_type, content->ct_subtype, len);
    8.14  
    8.15          if (content->ct_parameters) {
    8.16              clistiter *cur;
     9.1 --- a/src/identity_list.c	Thu Jul 14 10:23:05 2016 +0200
     9.2 +++ b/src/identity_list.c	Mon Jul 18 08:55:01 2016 +0200
     9.3 @@ -14,6 +14,7 @@
     9.4          return NULL;
     9.5  
     9.6      id_list->ident = ident;
     9.7 +    id_list->next = NULL;
     9.8  
     9.9      return id_list;
    9.10  }
    9.11 @@ -32,23 +33,43 @@
    9.12      if (id_list == NULL)
    9.13          return NULL;
    9.14  
    9.15 -    if (src->next) {
    9.16 -        id_list->next = identity_list_dup(src->next);
    9.17 -        if (id_list->next == NULL) {
    9.18 +    identity_list* src_curr = src->next;
    9.19 +    identity_list** dst_curr_ptr = &id_list->next;
    9.20 +    
    9.21 +    while (src_curr) {
    9.22 +        _ident = identity_dup(src_curr->ident);
    9.23 +        if (_ident == NULL) {
    9.24              free_identity_list(id_list);
    9.25              return NULL;
    9.26          }
    9.27 +        
    9.28 +        *dst_curr_ptr = new_identity_list(_ident);
    9.29 +        if (*dst_curr_ptr == NULL) {
    9.30 +            free_identity(_ident);
    9.31 +            free_identity_list(id_list);
    9.32 +            return NULL;
    9.33 +        }
    9.34 +        
    9.35 +        src_curr = src_curr->next;
    9.36 +        dst_curr_ptr = &((*dst_curr_ptr)->next);
    9.37      }
    9.38 -
    9.39 +    
    9.40      return id_list;
    9.41 +    
    9.42  }
    9.43  
    9.44  DYNAMIC_API void free_identity_list(identity_list *id_list)
    9.45  {
    9.46 -    if (id_list) {
    9.47 -        free_identity_list(id_list->next);
    9.48 -        free_identity(id_list->ident);
    9.49 -        free(id_list);
    9.50 +    identity_list *curr;
    9.51 +    identity_list *next;
    9.52 +    
    9.53 +    curr = id_list;
    9.54 +    
    9.55 +    while (curr) {
    9.56 +        next = curr->next;
    9.57 +        free_identity(curr->ident);
    9.58 +        free(curr);
    9.59 +        curr = next;
    9.60      }
    9.61  }
    9.62  
    9.63 @@ -61,17 +82,26 @@
    9.64      if (id_list == NULL)
    9.65          return new_identity_list(ident);
    9.66  
    9.67 +    // empty list
    9.68      if (id_list->ident == NULL) {
    9.69 +        if (id_list->next)
    9.70 +            return NULL; // invalid list
    9.71 +            
    9.72          id_list->ident = ident;
    9.73 +        
    9.74 +        if (id_list->ident == NULL)
    9.75 +            return NULL;
    9.76 +        
    9.77          return id_list;
    9.78      }
    9.79 -    else if (id_list->next == NULL) {
    9.80 -        id_list->next = new_identity_list(ident);
    9.81 -        return id_list->next;
    9.82 -    }
    9.83 -    else {
    9.84 -        return identity_list_add(id_list->next, ident);
    9.85 -    }
    9.86 + 
    9.87 +    identity_list* list_curr = id_list;
    9.88 +    while (list_curr->next)
    9.89 +        list_curr = list_curr->next;
    9.90 +    
    9.91 +    list_curr->next = new_identity_list(ident);
    9.92 +    
    9.93 +    return list_curr->next;
    9.94  }
    9.95  
    9.96  DYNAMIC_API int identity_list_length(const identity_list *id_list)
    10.1 --- a/src/message_api.c	Thu Jul 14 10:23:05 2016 +0200
    10.2 +++ b/src/message_api.c	Mon Jul 18 08:55:01 2016 +0200
    10.3 @@ -101,15 +101,22 @@
    10.4      if (longmsg == NULL)
    10.5          longmsg = "";
    10.6  
    10.7 -    ptext = calloc(1, strlen(shortmsg) + strlen(longmsg) + 12);
    10.8 +    size_t bufsize = strlen(shortmsg) + strlen(longmsg) + 12;
    10.9 +    ptext = calloc(1, bufsize);
   10.10      assert(ptext);
   10.11      if (ptext == NULL)
   10.12          return NULL;
   10.13  
   10.14 -    strcpy(ptext, "Subject: ");
   10.15 -    strcat(ptext, shortmsg);
   10.16 -    strcat(ptext, "\n\n");
   10.17 -    strcat(ptext, longmsg);
   10.18 +    strncpy(ptext, "Subject: ", bufsize);
   10.19 +    bufsize -= 9;
   10.20 +    
   10.21 +    strncat(ptext, shortmsg, bufsize);
   10.22 +    bufsize -= strlen(shortmsg);
   10.23 +    
   10.24 +    strncat(ptext, "\n\n", bufsize);
   10.25 +    bufsize -= 2;
   10.26 +    
   10.27 +    strncat(ptext, longmsg, bufsize);
   10.28  
   10.29      return ptext;
   10.30  }
   10.31 @@ -329,8 +336,7 @@
   10.32      PEP_STATUS status = PEP_STATUS_OK;
   10.33      bool free_ptext = false;
   10.34      char *ptext = NULL;
   10.35 -    char *ctext;
   10.36 -    char *_ctext = NULL;
   10.37 +    char *ctext = NULL;
   10.38      char *mimetext = NULL;
   10.39      size_t csize;
   10.40      assert(dst->longmsg == NULL);
   10.41 @@ -402,13 +408,7 @@
   10.42          goto enomem;
   10.43      dst->attachments = _a;
   10.44  
   10.45 -    _ctext = malloc(csize);
   10.46 -    assert(_ctext);
   10.47 -    if (_ctext == NULL)
   10.48 -        goto enomem;
   10.49 -    memcpy(_ctext, ctext, csize);
   10.50 -
   10.51 -    _a = bloblist_add(_a, _ctext, csize, "application/octet-stream",
   10.52 +    _a = bloblist_add(_a, ctext, csize, "application/octet-stream",
   10.53          "msg.asc");
   10.54      if (_a == NULL)
   10.55          goto enomem;
   10.56 @@ -421,7 +421,7 @@
   10.57  pep_error:
   10.58      if (free_ptext)
   10.59          free(ptext);
   10.60 -    free(_ctext);
   10.61 +    free(ctext);
   10.62      return status;
   10.63  }
   10.64  
   10.65 @@ -433,7 +433,7 @@
   10.66      )
   10.67  {
   10.68      PEP_STATUS status = PEP_STATUS_OK;
   10.69 -    char *ctext;
   10.70 +    char *ctext = NULL;
   10.71      size_t csize;
   10.72      char *ptext = NULL;
   10.73      bool free_ptext = false;
   10.74 @@ -464,10 +464,7 @@
   10.75              free(ptext);
   10.76          free_ptext = false;
   10.77          if (ctext) {
   10.78 -            dst->longmsg = strndup(ctext, csize);
   10.79 -            assert(dst->longmsg);
   10.80 -            if (dst->longmsg == NULL)
   10.81 -                goto enomem;
   10.82 +            dst->longmsg = ctext;
   10.83          }
   10.84          else {
   10.85              goto pep_error;
   10.86 @@ -478,10 +475,7 @@
   10.87          status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
   10.88              &csize);
   10.89          if (ctext) {
   10.90 -            dst->longmsg = strndup(ctext, csize);
   10.91 -            assert(dst->longmsg);
   10.92 -            if (dst->longmsg == NULL)
   10.93 -                goto enomem;
   10.94 +            dst->longmsg = ctext;
   10.95          }
   10.96          else {
   10.97              goto pep_error;
   10.98 @@ -499,13 +493,8 @@
   10.99          status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
  10.100              &csize);
  10.101          if (ctext) {
  10.102 -            char *_ctext = malloc(csize);
  10.103 -            assert(_ctext);
  10.104 -            if (_ctext == NULL)
  10.105 -                goto enomem;
  10.106 -            memcpy(_ctext, ctext, csize);
  10.107  
  10.108 -            bloblist_t *_a = bloblist_add(dst->attachments, _ctext, csize,
  10.109 +            bloblist_t *_a = bloblist_add(dst->attachments, ctext, csize,
  10.110                  "application/octet-stream", "PGPexch.htm.pgp");
  10.111              if (_a == NULL)
  10.112                  goto enomem;
  10.113 @@ -547,8 +536,8 @@
  10.114                          if (filename == NULL)
  10.115                              goto enomem;
  10.116  
  10.117 -                        strcpy(filename, _s->filename);
  10.118 -                        strcpy(filename + len, ".pgp");
  10.119 +                        strncpy(filename, _s->filename, len);
  10.120 +                        strncpy(filename + len, ".pgp", 5);
  10.121                      }
  10.122                      else {
  10.123                          filename = calloc(1, 20);
  10.124 @@ -560,15 +549,7 @@
  10.125                          snprintf(filename, 20, "Attachment%d.pgp", n);
  10.126                      }
  10.127  
  10.128 -                    char *_ctext = malloc(csize);
  10.129 -                    assert(_ctext);
  10.130 -                    if (_ctext == NULL) {
  10.131 -                        free(filename);
  10.132 -                        goto enomem;
  10.133 -                    }
  10.134 -                    memcpy(_ctext, ctext, csize);
  10.135 -
  10.136 -                    _d = bloblist_add(_d, _ctext, csize, "application/octet-stream",
  10.137 +                    _d = bloblist_add(_d, ctext, csize, "application/octet-stream",
  10.138                          filename);
  10.139                      free(filename);
  10.140                      if (_d == NULL)
  10.141 @@ -1346,10 +1327,8 @@
  10.142                  if (msg == NULL)
  10.143                      goto enomem;
  10.144  
  10.145 -                msg->longmsg = strdup(ptext);
  10.146 -                assert(msg->longmsg);
  10.147 -                if (msg->longmsg == NULL)
  10.148 -                    goto enomem;
  10.149 +                msg->longmsg = ptext;
  10.150 +                ptext = NULL;
  10.151  
  10.152                  bloblist_t *_m = msg->attachments;
  10.153                  if (_m == NULL && src->attachments && src->attachments->value) {
  10.154 @@ -1379,10 +1358,8 @@
  10.155  
  10.156                          if (ptext) {
  10.157                              if (is_encrypted_html_attachment(_s)) {
  10.158 -                                msg->longmsg_formatted = strdup(ptext);
  10.159 -                                assert(msg->longmsg_formatted);
  10.160 -                                if (msg->longmsg_formatted == NULL)
  10.161 -                                    goto pep_error;
  10.162 +                                msg->longmsg_formatted = ptext;
  10.163 +                                ptext = NULL;
  10.164                              }
  10.165                              else {
  10.166                                  static const char * const mime_type = "application/octet-stream";
  10.167 @@ -1391,18 +1368,14 @@
  10.168                                  if (filename == NULL)
  10.169                                      goto enomem;
  10.170  
  10.171 -                                char *_ptext = malloc(psize);
  10.172 -                                assert(_ptext);
  10.173 -                                if (_ptext == NULL)
  10.174 -                                    goto enomem;
  10.175 -                                memcpy(_ptext, ptext, psize);
  10.176 -
  10.177 -                                _m = bloblist_add(_m, _ptext, psize, mime_type,
  10.178 +                                _m = bloblist_add(_m, ptext, psize, mime_type,
  10.179                                      filename);
  10.180                                  free(filename);
  10.181                                  if (_m == NULL)
  10.182                                      goto enomem;
  10.183  
  10.184 +                                ptext = NULL;
  10.185 +
  10.186                                  if (msg->attachments == NULL)
  10.187                                      msg->attachments = _m;
  10.188                              }
  10.189 @@ -1512,8 +1485,7 @@
  10.190              status = cryptotech[crypto].decrypt_and_verify(session, ctext,
  10.191                  csize, &re_ptext, &re_psize, &_keylist);
  10.192              
  10.193 -            if (re_ptext)
  10.194 -                free(re_ptext);
  10.195 +            free(re_ptext);
  10.196              
  10.197              if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
  10.198                  goto pep_error;
  10.199 @@ -1591,6 +1563,7 @@
  10.200      status = PEP_OUT_OF_MEMORY;
  10.201  
  10.202  pep_error:
  10.203 +    free(ptext);
  10.204      free_message(msg);
  10.205      free_stringlist(_keylist);
  10.206  
    11.1 --- a/src/pEpEngine.c	Thu Jul 14 10:23:05 2016 +0200
    11.2 +++ b/src/pEpEngine.c	Mon Jul 18 08:55:01 2016 +0200
    11.3 @@ -564,7 +564,6 @@
    11.4          )
    11.5  {
    11.6      PEP_STATUS status = PEP_STATUS_OK;
    11.7 -    int result;
    11.8  
    11.9      assert(session);
   11.10      assert(word);
   11.11 @@ -589,7 +588,7 @@
   11.12      sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
   11.13      sqlite3_bind_int(session->trustword, 2, value);
   11.14  
   11.15 -    result = sqlite3_step(session->trustword);
   11.16 +    const int result = sqlite3_step(session->trustword);
   11.17      if (result == SQLITE_ROW) {
   11.18          *word = strdup((const char *) sqlite3_column_text(session->trustword,
   11.19                      1));
   11.20 @@ -778,8 +777,6 @@
   11.21  {
   11.22      PEP_STATUS status = PEP_STATUS_OK;
   11.23      static pEp_identity *_identity;
   11.24 -    int result;
   11.25 -    const char *_lang;
   11.26  
   11.27      assert(session);
   11.28      assert(address);
   11.29 @@ -795,7 +792,7 @@
   11.30      sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
   11.31      sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
   11.32  
   11.33 -    result = sqlite3_step(session->get_identity);
   11.34 +    const int result = sqlite3_step(session->get_identity);
   11.35      switch (result) {
   11.36      case SQLITE_ROW:
   11.37          _identity = new_identity(
   11.38 @@ -809,7 +806,7 @@
   11.39              return PEP_OUT_OF_MEMORY;
   11.40  
   11.41          _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 2);
   11.42 -        _lang = (const char *) sqlite3_column_text(session->get_identity, 3);
   11.43 +        const char* const _lang = (const char *) sqlite3_column_text(session->get_identity, 3);
   11.44          if (_lang && _lang[0]) {
   11.45              assert(_lang[0] >= 'a' && _lang[0] <= 'z');
   11.46              assert(_lang[1] >= 'a' && _lang[1] <= 'z');
    12.1 --- a/src/pEpEngine.h	Thu Jul 14 10:23:05 2016 +0200
    12.2 +++ b/src/pEpEngine.h	Mon Jul 18 08:55:01 2016 +0200
    12.3 @@ -71,6 +71,8 @@
    12.4      PEP_CONTRAINTS_VIOLATED                         = 0x0802,
    12.5      PEP_CANNOT_ENCODE                               = 0x0803,
    12.6  
    12.7 +    PEP_SYNC_NO_TRUSTWORDS_CALLBACK                 = 0x0901,
    12.8 +
    12.9      PEP_COMMIT_FAILED                               = 0xff01,
   12.10  
   12.11      PEP_CANNOT_CREATE_TEMP_FILE                     = -5,
    13.1 --- a/src/pgp_gpg.c	Thu Jul 14 10:23:05 2016 +0200
    13.2 +++ b/src/pgp_gpg.c	Mon Jul 18 08:55:01 2016 +0200
    13.3 @@ -95,7 +95,6 @@
    13.4      PEP_STATUS status = PEP_STATUS_OK;
    13.5      gpgme_error_t gpgme_error;
    13.6      bool bResult;
    13.7 -    char *cLocal;
    13.8      
    13.9      if (in_first) {
   13.10          stringlist_t *conf_keys   = new_stringlist("keyserver");
   13.11 @@ -333,7 +332,7 @@
   13.12  
   13.13          gpg.version = gpg.gpgme_check(NULL);
   13.14          
   13.15 -        cLocal = setlocale(LC_ALL, NULL);
   13.16 +        const char * const cLocal = setlocale(LC_ALL, NULL);
   13.17          if (!cLocal || (strcmp(cLocal, "C") == 0))
   13.18              setlocale(LC_ALL, "");
   13.19  
   13.20 @@ -1314,8 +1313,6 @@
   13.21  {
   13.22      gpgme_error_t gpgme_error;
   13.23      gpgme_key_t key;
   13.24 -    stringlist_t *_keylist;
   13.25 -    char *fpr;
   13.26  
   13.27      assert(session);
   13.28      assert(pattern);
   13.29 @@ -1336,7 +1333,7 @@
   13.30          return PEP_GET_KEY_FAILED;
   13.31      };
   13.32  
   13.33 -    _keylist = new_stringlist(NULL);
   13.34 +    stringlist_t *_keylist = new_stringlist(NULL);
   13.35      stringlist_t *_k = _keylist;
   13.36  
   13.37      do {
   13.38 @@ -1349,7 +1346,7 @@
   13.39          case GPG_ERR_NO_ERROR:
   13.40              assert(key);
   13.41              assert(key->subkeys);
   13.42 -            fpr = key->subkeys->fpr;
   13.43 +            char *fpr = key->subkeys->fpr;
   13.44              assert(fpr);
   13.45              _k = stringlist_add(_k, fpr);
   13.46              assert(_k);
    14.1 --- a/src/stringlist.c	Thu Jul 14 10:23:05 2016 +0200
    14.2 +++ b/src/stringlist.c	Mon Jul 18 08:55:01 2016 +0200
    14.3 @@ -41,6 +41,10 @@
    14.4      
    14.5      while (src_curr) {
    14.6          *dst_curr_ptr = new_stringlist(src_curr->value);
    14.7 +        if (*dst_curr_ptr == NULL) {
    14.8 +            free_stringlist(dst);
    14.9 +            return NULL;
   14.10 +        }
   14.11          src_curr = src_curr->next;
   14.12          dst_curr_ptr = &((*dst_curr_ptr)->next);
   14.13      }
    15.1 --- a/src/stringpair.c	Thu Jul 14 10:23:05 2016 +0200
    15.2 +++ b/src/stringpair.c	Mon Jul 18 08:55:01 2016 +0200
    15.3 @@ -85,7 +85,16 @@
    15.4  
    15.5      while (src_curr) {
    15.6          copy_pair = stringpair_dup(src_curr->value);
    15.7 +        if (copy_pair == NULL) {
    15.8 +            free_stringpair_list(dst);
    15.9 +            return NULL;
   15.10 +        }
   15.11          *dst_curr_ptr = new_stringpair_list(copy_pair);
   15.12 +        if (*dst_curr_ptr == NULL) {
   15.13 +            free_stringpair(copy_pair);
   15.14 +            free_stringpair_list(dst);
   15.15 +            return NULL;
   15.16 +        }
   15.17          src_curr = src_curr->next;
   15.18          dst_curr_ptr = &((*dst_curr_ptr)->next);
   15.19      }
    16.1 --- a/src/sync_actions.c	Thu Jul 14 10:23:05 2016 +0200
    16.2 +++ b/src/sync_actions.c	Mon Jul 18 08:55:01 2016 +0200
    16.3 @@ -2,202 +2,11 @@
    16.4  
    16.5  #include <assert.h>
    16.6  #include "pEp_internal.h"
    16.7 -#include "keymanagement.h"
    16.8  #include "message.h"
    16.9  #include "sync_fsm.h"
   16.10 -#include "baseprotocol.h"
   16.11 -#include "map_asn1.h"
   16.12 -#include "../asn.1/Beacon.h"
   16.13 -#include "../asn.1/HandshakeRequest.h"
   16.14 -#include "../asn.1/GroupKeys.h"
   16.15  
   16.16  
   16.17 -// sendBeacon() - send Beacon message
   16.18 -//
   16.19 -//  params:
   16.20 -//      session (in)        session handle
   16.21 -//      state (in)          state the state machine is in
   16.22 -//      partner (in)        (must be NULL)
   16.23 -//
   16.24 -//  returns:
   16.25 -//      PEP_STATUS_OK or any other value on error
   16.26 -
   16.27 -PEP_STATUS sendBeacon(
   16.28 -        PEP_SESSION session,
   16.29 -        DeviceState_state state,
   16.30 -        const Identity partner
   16.31 -    )
   16.32 -{
   16.33 -    PEP_STATUS status = PEP_STATUS_OK;
   16.34 -    Beacon_t *msg = NULL;
   16.35 -    char *payload = NULL;
   16.36 -    message *_message = NULL;
   16.37 -    pEp_identity *me = NULL;
   16.38 -
   16.39 -    assert(session);
   16.40 -    assert(!partner);
   16.41 -    if (!(session && !partner))
   16.42 -        return PEP_ILLEGAL_VALUE;
   16.43 -
   16.44 -    assert(session->messageToSend);
   16.45 -    if (!session->messageToSend)
   16.46 -        return PEP_SEND_FUNCTION_NOT_REGISTERED;
   16.47 -
   16.48 -    msg = (Beacon_t *) calloc(1, sizeof(Beacon_t));
   16.49 -    assert(msg);
   16.50 -    if (!msg)
   16.51 -        goto enomem;
   16.52 -
   16.53 -    int32_t seq;
   16.54 -    status = sequence_value(session, "DeviceGroup", &seq);
   16.55 -    if (status != PEP_STATUS_OK)
   16.56 -        goto error;
   16.57 -    msg->header.sequence = (long) seq;
   16.58 -
   16.59 -    msg->state = (long) state;
   16.60 -
   16.61 -    me = new_identity(NULL, NULL, NULL, NULL);
   16.62 -    if (!me)
   16.63 -        goto enomem;
   16.64 -    status = myself(session, me);
   16.65 -    if (status != PEP_STATUS_OK)
   16.66 -        goto error;
   16.67 -    if (Identity_from_Struct(me, &msg->me) == NULL)
   16.68 -        goto enomem;
   16.69 -
   16.70 -    if (asn_check_constraints(&asn_DEF_Beacon, msg, NULL, NULL)) {
   16.71 -        status = PEP_CONTRAINTS_VIOLATED;
   16.72 -        goto error;
   16.73 -    }
   16.74 -
   16.75 -    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_Beacon,
   16.76 -            NULL, msg, (void **) &payload);
   16.77 -    if (size == -1) {
   16.78 -        status = PEP_CANNOT_ENCODE;
   16.79 -        goto error;
   16.80 -    }
   16.81 -
   16.82 -    status = prepare_message(me, partner, payload, size, &_message);
   16.83 -    if (status != PEP_STATUS_OK)
   16.84 -        goto error;
   16.85 -    payload = NULL;
   16.86 -
   16.87 -    free_identity(me);
   16.88 -    me = NULL;
   16.89 -
   16.90 -    status = session->messageToSend(session->sync_obj, _message);
   16.91 -
   16.92 -    free_message(_message);
   16.93 -    ASN_STRUCT_FREE(asn_DEF_Beacon, msg);
   16.94 -
   16.95 -    return status;
   16.96 -
   16.97 -enomem:
   16.98 -    status = PEP_OUT_OF_MEMORY;
   16.99 -error:
  16.100 -    ASN_STRUCT_FREE(asn_DEF_Beacon, msg);
  16.101 -    free(payload);
  16.102 -    free_message(_message);
  16.103 -    free_identity(me);
  16.104 -    return status;
  16.105 -}
  16.106 -
  16.107 -
  16.108 -// sendHandshakeRequest() - send HandshakeRequest message
  16.109 -//
  16.110 -//  params:
  16.111 -//      session (in)        session handle
  16.112 -//      state (in)          state the state machine is in
  16.113 -//      partner (in)        partner to communicate with
  16.114 -//
  16.115 -//  returns:
  16.116 -//      PEP_STATUS_OK or any other value on error
  16.117 -
  16.118 -PEP_STATUS sendHandshakeRequest(
  16.119 -        PEP_SESSION session,
  16.120 -        DeviceState_state state,
  16.121 -        const Identity partner
  16.122 -    )
  16.123 -{
  16.124 -    PEP_STATUS status = PEP_STATUS_OK;
  16.125 -    HandshakeRequest_t *msg = NULL;
  16.126 -    char *payload = NULL;
  16.127 -    message *_message = NULL;
  16.128 -    pEp_identity *me = NULL;
  16.129 -
  16.130 -    assert(session);
  16.131 -    assert(partner);
  16.132 -    if (!(session && partner))
  16.133 -        return PEP_ILLEGAL_VALUE;
  16.134 -
  16.135 -    assert(session->messageToSend);
  16.136 -    if (!session->messageToSend)
  16.137 -        return PEP_SEND_FUNCTION_NOT_REGISTERED;
  16.138 -
  16.139 -    msg = (HandshakeRequest_t *) calloc(1, sizeof(HandshakeRequest_t));
  16.140 -    assert(msg);
  16.141 -    if (!msg)
  16.142 -        goto enomem;
  16.143 -
  16.144 -    int32_t seq;
  16.145 -    status = sequence_value(session, "DeviceGroup", &seq);
  16.146 -    if (status != PEP_STATUS_OK)
  16.147 -        goto error;
  16.148 -    msg->header.sequence = (long) seq;
  16.149 -
  16.150 -    msg->state = (long) state;
  16.151 -
  16.152 -    me = new_identity(NULL, NULL, NULL, NULL);
  16.153 -    if (!me)
  16.154 -        goto enomem;
  16.155 -    status = myself(session, me);
  16.156 -    if (status != PEP_STATUS_OK)
  16.157 -        goto error;
  16.158 -    if (Identity_from_Struct(me, &msg->me) == NULL)
  16.159 -        goto enomem;
  16.160 -
  16.161 -    if (Identity_from_Struct(partner, &msg->partner) == NULL)
  16.162 -        goto enomem;
  16.163 -
  16.164 -    if (asn_check_constraints(&asn_DEF_HandshakeRequest, msg, NULL, NULL)) {
  16.165 -        status = PEP_CONTRAINTS_VIOLATED;
  16.166 -        goto error;
  16.167 -    }
  16.168 -
  16.169 -    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_HandshakeRequest,
  16.170 -            NULL, msg, (void **) &payload);
  16.171 -    if (size == -1) {
  16.172 -        status = PEP_CANNOT_ENCODE;
  16.173 -        goto error;
  16.174 -    }
  16.175 -
  16.176 -    status = prepare_message(me, partner, payload, size, &_message);
  16.177 -    if (status != PEP_STATUS_OK)
  16.178 -        goto error;
  16.179 -    payload = NULL;
  16.180 -
  16.181 -    free_identity(me);
  16.182 -    me = NULL;
  16.183 -
  16.184 -    status = session->messageToSend(session->sync_obj, _message);
  16.185 -
  16.186 -    free_message(_message);
  16.187 -    ASN_STRUCT_FREE(asn_DEF_HandshakeRequest, msg);
  16.188 -
  16.189 -    return status;
  16.190 -
  16.191 -enomem:
  16.192 -    status = PEP_OUT_OF_MEMORY;
  16.193 -error:
  16.194 -    ASN_STRUCT_FREE(asn_DEF_HandshakeRequest, msg);
  16.195 -    free(payload);
  16.196 -    free_message(_message);
  16.197 -    free_identity(me);
  16.198 -    return status;
  16.199 -}
  16.200 -
  16.201 -
  16.202 -// showHandshake() - 
  16.203 +// showHandshake() - trigger the handshake dialog of the application
  16.204  //
  16.205  //  params:
  16.206  //      session (in)        session handle
  16.207 @@ -214,21 +23,30 @@
  16.208      )
  16.209  {
  16.210      PEP_STATUS status = PEP_STATUS_OK;
  16.211 -
  16.212      assert(session);
  16.213      assert(partner);
  16.214 +    assert(session->showHandshake);
  16.215      if (!(session && partner))
  16.216          return PEP_ILLEGAL_VALUE;
  16.217 +    if (!session->showHandshake)
  16.218 +        return PEP_SYNC_NO_TRUSTWORDS_CALLBACK;
  16.219  
  16.220 -    // working code
  16.221 +    pEp_identity *me = NULL;
  16.222 +    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
  16.223 +    if (status != PEP_STATUS_OK)
  16.224 +        goto error;
  16.225 +    
  16.226 +    status = session->showHandshake(session, me, partner);
  16.227 +    if (status != PEP_STATUS_OK)
  16.228 +        goto error;
  16.229  
  16.230 -
  16.231 +    free_identity(me);
  16.232      return status;
  16.233  
  16.234  enomem:
  16.235      status = PEP_OUT_OF_MEMORY;
  16.236  error:
  16.237 -    // free...
  16.238 +    free_identity(me);
  16.239      return status;
  16.240  }
  16.241  
  16.242 @@ -304,95 +122,3 @@
  16.243      return status;
  16.244  }
  16.245  
  16.246 -
  16.247 -// sendGroupKeys() - send GroupKeys message
  16.248 -//
  16.249 -//  params:
  16.250 -//      session (in)        session handle
  16.251 -//      state (in)          state the state machine is in
  16.252 -//      partner (in)        (must be NULL)
  16.253 -//
  16.254 -//  returns:
  16.255 -//      PEP_STATUS_OK or any other value on error
  16.256 -
  16.257 -PEP_STATUS sendGroupKeys(
  16.258 -        PEP_SESSION session,
  16.259 -        DeviceState_state state,
  16.260 -        const Identity partner
  16.261 -    )
  16.262 -{
  16.263 -    PEP_STATUS status = PEP_STATUS_OK;
  16.264 -    GroupKeys_t *msg = NULL;
  16.265 -    char *payload = NULL;
  16.266 -    message *_message = NULL;
  16.267 -    pEp_identity *me = NULL;
  16.268 -
  16.269 -    assert(session);
  16.270 -    assert(!partner);
  16.271 -    if (!(session && !partner))
  16.272 -        return PEP_ILLEGAL_VALUE;
  16.273 -
  16.274 -    assert(session->messageToSend);
  16.275 -    if (!session->messageToSend)
  16.276 -        return PEP_SEND_FUNCTION_NOT_REGISTERED;
  16.277 -
  16.278 -    msg = (GroupKeys_t *) calloc(1, sizeof(GroupKeys_t));
  16.279 -    assert(msg);
  16.280 -    if (!msg)
  16.281 -        goto enomem;
  16.282 -
  16.283 -    int32_t seq;
  16.284 -    status = sequence_value(session, "DeviceGroup", &seq);
  16.285 -    if (status != PEP_STATUS_OK)
  16.286 -        goto error;
  16.287 -    msg->header.sequence = (long) seq;
  16.288 -
  16.289 -    msg->state = (long) state;
  16.290 -
  16.291 -    me = new_identity(NULL, NULL, NULL, NULL);
  16.292 -    if (!me)
  16.293 -        goto enomem;
  16.294 -    status = myself(session, me);
  16.295 -    if (status != PEP_STATUS_OK)
  16.296 -        goto error;
  16.297 -    if (Identity_from_Struct(me, &msg->me) == NULL)
  16.298 -        goto enomem;
  16.299 -
  16.300 -    if (asn_check_constraints(&asn_DEF_GroupKeys, msg, NULL, NULL)) {
  16.301 -        status = PEP_CONTRAINTS_VIOLATED;
  16.302 -        goto error;
  16.303 -    }
  16.304 -
  16.305 -    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_GroupKeys,
  16.306 -            NULL, msg, (void **) &payload);
  16.307 -    if (size == -1) {
  16.308 -        status = PEP_CANNOT_ENCODE;
  16.309 -        goto error;
  16.310 -    }
  16.311 -
  16.312 -    status = prepare_message(me, partner, payload, size, &_message);
  16.313 -    if (status != PEP_STATUS_OK)
  16.314 -        goto error;
  16.315 -    payload = NULL;
  16.316 -
  16.317 -    free_identity(me);
  16.318 -    me = NULL;
  16.319 -
  16.320 -    status = session->messageToSend(session->sync_obj, _message);
  16.321 -
  16.322 -    free_message(_message);
  16.323 -    ASN_STRUCT_FREE(asn_DEF_GroupKeys, msg);
  16.324 -
  16.325 -    return status;
  16.326 -
  16.327 -enomem:
  16.328 -    status = PEP_OUT_OF_MEMORY;
  16.329 -error:
  16.330 -    ASN_STRUCT_FREE(asn_DEF_GroupKeys, msg);
  16.331 -    free(payload);
  16.332 -    free_message(_message);
  16.333 -    free_identity(me);
  16.334 -    return status;
  16.335 -}
  16.336 -
  16.337 -
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/sync_send_actions.c	Mon Jul 18 08:55:01 2016 +0200
    17.3 @@ -0,0 +1,289 @@
    17.4 +// Send Actions for DeviceState state machine
    17.5 +
    17.6 +#include <assert.h>
    17.7 +#include "pEp_internal.h"
    17.8 +#include "keymanagement.h"
    17.9 +#include "message.h"
   17.10 +#include "sync_fsm.h"
   17.11 +#include "baseprotocol.h"
   17.12 +#include "map_asn1.h"
   17.13 +#include "../asn.1/Beacon.h"
   17.14 +#include "../asn.1/HandshakeRequest.h"
   17.15 +#include "../asn.1/GroupKeys.h"
   17.16 +
   17.17 +
   17.18 +// sendBeacon() - send Beacon message
   17.19 +//
   17.20 +//  params:
   17.21 +//      session (in)        session handle
   17.22 +//      state (in)          state the state machine is in
   17.23 +//      partner (in)        (must be NULL)
   17.24 +//
   17.25 +//  returns:
   17.26 +//      PEP_STATUS_OK or any other value on error
   17.27 +
   17.28 +PEP_STATUS sendBeacon(
   17.29 +        PEP_SESSION session,
   17.30 +        DeviceState_state state,
   17.31 +        const Identity partner
   17.32 +    )
   17.33 +{
   17.34 +    PEP_STATUS status = PEP_STATUS_OK;
   17.35 +    Beacon_t *msg = NULL;
   17.36 +    char *payload = NULL;
   17.37 +    message *_message = NULL;
   17.38 +    pEp_identity *me = NULL;
   17.39 +
   17.40 +    assert(session);
   17.41 +    assert(!partner);
   17.42 +    if (!(session && !partner))
   17.43 +        return PEP_ILLEGAL_VALUE;
   17.44 +
   17.45 +    assert(session->messageToSend);
   17.46 +    if (!session->messageToSend)
   17.47 +        return PEP_SEND_FUNCTION_NOT_REGISTERED;
   17.48 +
   17.49 +    msg = (Beacon_t *) calloc(1, sizeof(Beacon_t));
   17.50 +    assert(msg);
   17.51 +    if (!msg)
   17.52 +        goto enomem;
   17.53 +
   17.54 +    int32_t seq;
   17.55 +    status = sequence_value(session, "DeviceGroup", &seq);
   17.56 +    if (status != PEP_STATUS_OK)
   17.57 +        goto error;
   17.58 +    msg->header.sequence = (long) seq;
   17.59 +
   17.60 +    msg->state = (long) state;
   17.61 +
   17.62 +    me = new_identity(NULL, NULL, NULL, NULL);
   17.63 +    if (!me)
   17.64 +        goto enomem;
   17.65 +    status = myself(session, me);
   17.66 +    if (status != PEP_STATUS_OK)
   17.67 +        goto error;
   17.68 +    if (Identity_from_Struct(me, &msg->me) == NULL)
   17.69 +        goto enomem;
   17.70 +
   17.71 +    if (asn_check_constraints(&asn_DEF_Beacon, msg, NULL, NULL)) {
   17.72 +        status = PEP_CONTRAINTS_VIOLATED;
   17.73 +        goto error;
   17.74 +    }
   17.75 +
   17.76 +    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_Beacon,
   17.77 +            NULL, msg, (void **) &payload);
   17.78 +    if (size == -1) {
   17.79 +        status = PEP_CANNOT_ENCODE;
   17.80 +        goto error;
   17.81 +    }
   17.82 +
   17.83 +    status = prepare_message(me, partner, payload, size, &_message);
   17.84 +    if (status != PEP_STATUS_OK)
   17.85 +        goto error;
   17.86 +    payload = NULL;
   17.87 +
   17.88 +    free_identity(me);
   17.89 +    me = NULL;
   17.90 +
   17.91 +    status = session->messageToSend(session->sync_obj, _message);
   17.92 +
   17.93 +    free_message(_message);
   17.94 +    ASN_STRUCT_FREE(asn_DEF_Beacon, msg);
   17.95 +
   17.96 +    return status;
   17.97 +
   17.98 +enomem:
   17.99 +    status = PEP_OUT_OF_MEMORY;
  17.100 +error:
  17.101 +    ASN_STRUCT_FREE(asn_DEF_Beacon, msg);
  17.102 +    free(payload);
  17.103 +    free_message(_message);
  17.104 +    free_identity(me);
  17.105 +    return status;
  17.106 +}
  17.107 +
  17.108 +
  17.109 +// sendHandshakeRequest() - send HandshakeRequest message
  17.110 +//
  17.111 +//  params:
  17.112 +//      session (in)        session handle
  17.113 +//      state (in)          state the state machine is in
  17.114 +//      partner (in)        partner to communicate with
  17.115 +//
  17.116 +//  returns:
  17.117 +//      PEP_STATUS_OK or any other value on error
  17.118 +
  17.119 +PEP_STATUS sendHandshakeRequest(
  17.120 +        PEP_SESSION session,
  17.121 +        DeviceState_state state,
  17.122 +        const Identity partner
  17.123 +    )
  17.124 +{
  17.125 +    PEP_STATUS status = PEP_STATUS_OK;
  17.126 +    HandshakeRequest_t *msg = NULL;
  17.127 +    char *payload = NULL;
  17.128 +    message *_message = NULL;
  17.129 +    pEp_identity *me = NULL;
  17.130 +
  17.131 +    assert(session);
  17.132 +    assert(partner);
  17.133 +    if (!(session && partner))
  17.134 +        return PEP_ILLEGAL_VALUE;
  17.135 +
  17.136 +    assert(session->messageToSend);
  17.137 +    if (!session->messageToSend)
  17.138 +        return PEP_SEND_FUNCTION_NOT_REGISTERED;
  17.139 +
  17.140 +    msg = (HandshakeRequest_t *) calloc(1, sizeof(HandshakeRequest_t));
  17.141 +    assert(msg);
  17.142 +    if (!msg)
  17.143 +        goto enomem;
  17.144 +
  17.145 +    int32_t seq;
  17.146 +    status = sequence_value(session, "DeviceGroup", &seq);
  17.147 +    if (status != PEP_STATUS_OK)
  17.148 +        goto error;
  17.149 +    msg->header.sequence = (long) seq;
  17.150 +
  17.151 +    msg->state = (long) state;
  17.152 +
  17.153 +    me = new_identity(NULL, NULL, NULL, NULL);
  17.154 +    if (!me)
  17.155 +        goto enomem;
  17.156 +    status = myself(session, me);
  17.157 +    if (status != PEP_STATUS_OK)
  17.158 +        goto error;
  17.159 +    if (Identity_from_Struct(me, &msg->me) == NULL)
  17.160 +        goto enomem;
  17.161 +
  17.162 +    if (Identity_from_Struct(partner, &msg->partner) == NULL)
  17.163 +        goto enomem;
  17.164 +
  17.165 +    if (asn_check_constraints(&asn_DEF_HandshakeRequest, msg, NULL, NULL)) {
  17.166 +        status = PEP_CONTRAINTS_VIOLATED;
  17.167 +        goto error;
  17.168 +    }
  17.169 +
  17.170 +    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_HandshakeRequest,
  17.171 +            NULL, msg, (void **) &payload);
  17.172 +    if (size == -1) {
  17.173 +        status = PEP_CANNOT_ENCODE;
  17.174 +        goto error;
  17.175 +    }
  17.176 +
  17.177 +    status = prepare_message(me, partner, payload, size, &_message);
  17.178 +    if (status != PEP_STATUS_OK)
  17.179 +        goto error;
  17.180 +    payload = NULL;
  17.181 +
  17.182 +    free_identity(me);
  17.183 +    me = NULL;
  17.184 +
  17.185 +    status = session->messageToSend(session->sync_obj, _message);
  17.186 +
  17.187 +    free_message(_message);
  17.188 +    ASN_STRUCT_FREE(asn_DEF_HandshakeRequest, msg);
  17.189 +
  17.190 +    return status;
  17.191 +
  17.192 +enomem:
  17.193 +    status = PEP_OUT_OF_MEMORY;
  17.194 +error:
  17.195 +    ASN_STRUCT_FREE(asn_DEF_HandshakeRequest, msg);
  17.196 +    free(payload);
  17.197 +    free_message(_message);
  17.198 +    free_identity(me);
  17.199 +    return status;
  17.200 +}
  17.201 +
  17.202 +
  17.203 +// sendGroupKeys() - send GroupKeys message
  17.204 +//
  17.205 +//  params:
  17.206 +//      session (in)        session handle
  17.207 +//      state (in)          state the state machine is in
  17.208 +//      partner (in)        (must be NULL)
  17.209 +//
  17.210 +//  returns:
  17.211 +//      PEP_STATUS_OK or any other value on error
  17.212 +
  17.213 +PEP_STATUS sendGroupKeys(
  17.214 +        PEP_SESSION session,
  17.215 +        DeviceState_state state,
  17.216 +        const Identity partner
  17.217 +    )
  17.218 +{
  17.219 +    PEP_STATUS status = PEP_STATUS_OK;
  17.220 +    GroupKeys_t *msg = NULL;
  17.221 +    char *payload = NULL;
  17.222 +    message *_message = NULL;
  17.223 +    pEp_identity *me = NULL;
  17.224 +
  17.225 +    assert(session);
  17.226 +    assert(!partner);
  17.227 +    if (!(session && !partner))
  17.228 +        return PEP_ILLEGAL_VALUE;
  17.229 +
  17.230 +    assert(session->messageToSend);
  17.231 +    if (!session->messageToSend)
  17.232 +        return PEP_SEND_FUNCTION_NOT_REGISTERED;
  17.233 +
  17.234 +    msg = (GroupKeys_t *) calloc(1, sizeof(GroupKeys_t));
  17.235 +    assert(msg);
  17.236 +    if (!msg)
  17.237 +        goto enomem;
  17.238 +
  17.239 +    int32_t seq;
  17.240 +    status = sequence_value(session, "DeviceGroup", &seq);
  17.241 +    if (status != PEP_STATUS_OK)
  17.242 +        goto error;
  17.243 +    msg->header.sequence = (long) seq;
  17.244 +
  17.245 +    msg->state = (long) state;
  17.246 +
  17.247 +    me = new_identity(NULL, NULL, NULL, NULL);
  17.248 +    if (!me)
  17.249 +        goto enomem;
  17.250 +    status = myself(session, me);
  17.251 +    if (status != PEP_STATUS_OK)
  17.252 +        goto error;
  17.253 +    if (Identity_from_Struct(me, &msg->me) == NULL)
  17.254 +        goto enomem;
  17.255 +
  17.256 +    if (asn_check_constraints(&asn_DEF_GroupKeys, msg, NULL, NULL)) {
  17.257 +        status = PEP_CONTRAINTS_VIOLATED;
  17.258 +        goto error;
  17.259 +    }
  17.260 +
  17.261 +    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_GroupKeys,
  17.262 +            NULL, msg, (void **) &payload);
  17.263 +    if (size == -1) {
  17.264 +        status = PEP_CANNOT_ENCODE;
  17.265 +        goto error;
  17.266 +    }
  17.267 +
  17.268 +    status = prepare_message(me, partner, payload, size, &_message);
  17.269 +    if (status != PEP_STATUS_OK)
  17.270 +        goto error;
  17.271 +    payload = NULL;
  17.272 +
  17.273 +    free_identity(me);
  17.274 +    me = NULL;
  17.275 +
  17.276 +    status = session->messageToSend(session->sync_obj, _message);
  17.277 +
  17.278 +    free_message(_message);
  17.279 +    ASN_STRUCT_FREE(asn_DEF_GroupKeys, msg);
  17.280 +
  17.281 +    return status;
  17.282 +
  17.283 +enomem:
  17.284 +    status = PEP_OUT_OF_MEMORY;
  17.285 +error:
  17.286 +    ASN_STRUCT_FREE(asn_DEF_GroupKeys, msg);
  17.287 +    free(payload);
  17.288 +    free_message(_message);
  17.289 +    free_identity(me);
  17.290 +    return status;
  17.291 +}
  17.292 +
    18.1 --- a/sync/Makefile	Thu Jul 14 10:23:05 2016 +0200
    18.2 +++ b/sync/Makefile	Mon Jul 18 08:55:01 2016 +0200
    18.3 @@ -1,6 +1,6 @@
    18.4  include ../Makefile.conf
    18.5  
    18.6 -all: .statemachines
    18.7 +all: .statemachines .skeletons
    18.8  
    18.9  skeleton: .skeletons
   18.10  
    19.1 --- a/sync/gen_actions_skeleton.ysl2	Thu Jul 14 10:23:05 2016 +0200
    19.2 +++ b/sync/gen_actions_skeleton.ysl2	Mon Jul 18 08:55:01 2016 +0200
    19.3 @@ -9,11 +9,16 @@
    19.4  tstylesheet {
    19.5      include ./functions.ysl2
    19.6  
    19.7 -    template "/protocol/fsm" document "../src/{@filename}_actions.c.skeleton", "text" {
    19.8 +    template "/protocol" {
    19.9 +        apply "fsm", mode=send, 0;
   19.10 +        apply "fsm", mode=other, 0;
   19.11 +    }
   19.12 +
   19.13 +    template "fsm", mode=send document "../src/{@filename}_send_actions.c", "text" {
   19.14          const "name", "@name";
   19.15          const "filename", "@filename";
   19.16          ||
   19.17 -        // Actions for «@name» state machine
   19.18 +        // Send Actions for «@name» state machine
   19.19  
   19.20          #include <assert.h>
   19.21          #include "pEp_internal.h"
   19.22 @@ -28,29 +33,32 @@
   19.23                  | #include "../asn.1/«substring(@name, 5, 255)».h"
   19.24          |
   19.25          for "func:distinctName(//action)"
   19.26 -            call "action"
   19.27 -                with "action", ".",
   19.28 -                with "fsm", "$name",
   19.29 -                with "filename", "$filename";
   19.30 -        |
   19.31 +            if "substring(@name, 1, 4) = 'send'"
   19.32 +                call "send_action"
   19.33 +                    with "action", ".",
   19.34 +                    with "fsm", "$name",
   19.35 +                    with "filename", "$filename";
   19.36      }
   19.37  
   19.38 -    function "action" {
   19.39 -        param "action";
   19.40 -        param "fsm";
   19.41 -        param "filename", "'###'";
   19.42 -        choose {
   19.43 -            when "substring($action/@name, 1, 4) = 'send'"
   19.44 -                call "send_action"
   19.45 -                    with "action", "$action",
   19.46 -                    with "fsm", "$fsm",
   19.47 +    template "fsm", mode=other document "../src/{@filename}_actions.c.skeleton", "text" {
   19.48 +        const "name", "@name";
   19.49 +        const "filename", "@filename";
   19.50 +        ||
   19.51 +        // Actions for «@name» state machine
   19.52 +
   19.53 +        #include <assert.h>
   19.54 +        #include "pEp_internal.h"
   19.55 +        #include "keymanagement.h"
   19.56 +        #include "message.h"
   19.57 +        #include "«@filename»_fsm.h"
   19.58 +
   19.59 +        ||
   19.60 +        for "func:distinctName(//action)"
   19.61 +            if "substring(@name, 1, 4) != 'send'"
   19.62 +                call "other_action"
   19.63 +                    with "action", ".",
   19.64 +                    with "fsm", "$name",
   19.65                      with "filename", "$filename";
   19.66 -            otherwise
   19.67 -                call "other_action"
   19.68 -                    with "action", "$action",
   19.69 -                    with "fsm", "$fsm",
   19.70 -                    with "filename", "$filename";
   19.71 -        }
   19.72      }
   19.73  
   19.74      function "paramcheck" {
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/bloblist_test.cc	Mon Jul 18 08:55:01 2016 +0200
    20.3 @@ -0,0 +1,131 @@
    20.4 +#include <stdlib.h>
    20.5 +#include <string.h>
    20.6 +#include "platform.h"
    20.7 +#include <iostream>
    20.8 +#include <fstream>
    20.9 +#include <assert.h>
   20.10 +
   20.11 +#include "bloblist.h"
   20.12 +
   20.13 +using namespace std;
   20.14 +
   20.15 +/*
   20.16 + *     char *address;              // C string with address UTF-8 encoded
   20.17 +    char *fpr;                  // C string with fingerprint UTF-8 encoded
   20.18 +    char *user_id;              // C string with user ID UTF-8 encoded
   20.19 +    char *username;             // C string with user name UTF-8 encoded
   20.20 +    PEP_comm_type comm_type;    // type of communication with this ID
   20.21 +    char lang[3];               // language of conversation
   20.22 +                                // ISO 639-1 ALPHA-2, last byte is 0
   20.23 +    bool me;                    // if this is the local user herself/himself
   20.24 +    */
   20.25 +
   20.26 +bool test_blob_equals(size_t size1, char* blob1, size_t size2, char* blob2) {
   20.27 +    if (size1 != size2)
   20.28 +        return false;
   20.29 +    size_t i;
   20.30 +    for (i = 0; i < size1; i++) {
   20.31 +        if (blob1[i] != blob2[i])
   20.32 +            return false;
   20.33 +    }
   20.34 +    return true;
   20.35 +}
   20.36 +
   20.37 +bool test_bloblist_node_equals(bloblist_t* val1, bloblist_t* val2) {
   20.38 +    assert(val1);
   20.39 +    assert(val2);
   20.40 +    assert(val1->size == val2->size);
   20.41 +    assert(test_blob_equals(val1->size, val1->value, val2->size, val2->value));
   20.42 +    return( ((!val1->mime_type && !val2->mime_type) || (strcmp(val1->mime_type, val2->mime_type) == 0))
   20.43 +        && ((!val1->filename && !val2->filename) || (strcmp(val1->filename, val2->filename) == 0)));
   20.44 +}
   20.45 +
   20.46 +int main() {
   20.47 +    cout << "\n*** data structures: bloblist_test ***\n\n";
   20.48 +    char* text1 = strdup("This is just some text.");
   20.49 +    char* text2 = strdup("More text.");
   20.50 +    char* text3 = strdup("Unpleasant news and witty one-liners.");
   20.51 +    char* text4 = strdup("I AM URDNOT WREX AND THIS IS MY PLANET!");
   20.52 +    bloblist_t* bl1 = new_bloblist(text1, strlen(text1) + 1, "text/plain", NULL);
   20.53 +    bloblist_t* bl2 = new_bloblist(text2, strlen(text2) + 1, "text/richtext", "bob.rtf");
   20.54 +    bloblist_t* bl3 = new_bloblist(text3, strlen(text3) + 1, NULL, "dummy.bin");
   20.55 +    bloblist_t* bl4 = new_bloblist(text4, strlen(text4) + 1, NULL, NULL);
   20.56 +    
   20.57 +    bloblist_t* bl_arr[4] = {bl1, bl2, bl3, bl4};
   20.58 +        
   20.59 +    int i;
   20.60 +        
   20.61 +    cout << "duping one-element bloblist...\n";
   20.62 +    
   20.63 +    bloblist_t* new_bl = bloblist_dup(bl1);
   20.64 +    assert(new_bl);
   20.65 +    assert(test_bloblist_node_equals(bl1, new_bl));
   20.66 +    assert(new_bl->next == NULL);
   20.67 +    assert(bl1->value != new_bl->value);
   20.68 +    assert(bl1->mime_type != new_bl->mime_type || !(bl1->mime_type || new_bl->mime_type));
   20.69 +    assert(bl1->filename != new_bl->filename || !(bl1->filename || new_bl->filename));
   20.70 +    cout << "one-element bloblist duplicated.\n\n";
   20.71 +    
   20.72 +    cout << "freeing bloblist...\n";
   20.73 +    free_bloblist(new_bl);
   20.74 +    new_bl = NULL;
   20.75 +    
   20.76 +    bloblist_t* p;
   20.77 +    cout << "\ncreating four-element list...\n";
   20.78 +    bloblist_t* to_copy = bl_arr[0];
   20.79 +    new_bl = bloblist_add(new_bl, strdup(to_copy->value), to_copy->size, to_copy->mime_type, to_copy->filename);
   20.80 +    for (i = 1; i < 4; i++) {
   20.81 +        to_copy = bl_arr[i];
   20.82 +        p = bloblist_add(new_bl, strdup(to_copy->value), to_copy->size, to_copy->mime_type, to_copy->filename);
   20.83 +
   20.84 +        assert(p);
   20.85 +    }
   20.86 +    
   20.87 +    p = new_bl;
   20.88 +    
   20.89 +    for (i = 0; i < 4; i++) {
   20.90 +        assert(p);
   20.91 +        
   20.92 +        assert(test_bloblist_node_equals(p, bl_arr[i]));
   20.93 +        assert(p->value != bl_arr[i]->value);
   20.94 +        assert(p->mime_type != bl_arr[i]->mime_type || !(p->mime_type || bl_arr[i]->mime_type));
   20.95 +        assert(p->filename != bl_arr[i]->filename || !(p->filename || bl_arr[i]->filename));
   20.96 +        
   20.97 +        p = p->next;
   20.98 +    }
   20.99 +    assert(p == NULL);
  20.100 +    
  20.101 +    cout << "\nduplicating four-element list...\n\n";
  20.102 +    bloblist_t* duplist = bloblist_dup(new_bl);
  20.103 +    
  20.104 +    p = new_bl;
  20.105 +    bloblist_t* dup_p = duplist;
  20.106 +    
  20.107 +    while (dup_p) {
  20.108 +        assert(test_bloblist_node_equals(p, dup_p));
  20.109 +        assert(p != dup_p);
  20.110 +        assert(p->value != dup_p->value);
  20.111 +        assert(p->mime_type != dup_p->mime_type || !(p->mime_type || dup_p->mime_type));
  20.112 +        assert(p->filename != dup_p->filename || !(p->filename || dup_p->filename));
  20.113 +
  20.114 +        dup_p = dup_p->next;
  20.115 +        p = p->next;
  20.116 +        assert((p == NULL) == (dup_p == NULL));
  20.117 +    }
  20.118 +    cout << "\nfour-element bloblist successfully duplicated.\n\n";
  20.119 +
  20.120 +    cout << "freeing bloblists...\n";
  20.121 +    free_bloblist(new_bl);
  20.122 +    free_bloblist(duplist);
  20.123 +    new_bl = NULL;
  20.124 +    duplist = NULL;
  20.125 +    free(text1);
  20.126 +    free(text2);
  20.127 +    free(text3);
  20.128 +    free(text4);    
  20.129 +    cout << "done.\n";
  20.130 +        
  20.131 +    
  20.132 +    return 0;
  20.133 +}
  20.134 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/identity_list_test.cc	Mon Jul 18 08:55:01 2016 +0200
    21.3 @@ -0,0 +1,172 @@
    21.4 +#include <stdlib.h>
    21.5 +#include <string.h>
    21.6 +#include "platform.h"
    21.7 +#include <iostream>
    21.8 +#include <fstream>
    21.9 +#include <assert.h>
   21.10 +
   21.11 +#include "identity_list.h"
   21.12 +
   21.13 +using namespace std;
   21.14 +
   21.15 +/*
   21.16 + *     char *address;              // C string with address UTF-8 encoded
   21.17 +    char *fpr;                  // C string with fingerprint UTF-8 encoded
   21.18 +    char *user_id;              // C string with user ID UTF-8 encoded
   21.19 +    char *username;             // C string with user name UTF-8 encoded
   21.20 +    PEP_comm_type comm_type;    // type of communication with this ID
   21.21 +    char lang[3];               // language of conversation
   21.22 +                                // ISO 639-1 ALPHA-2, last byte is 0
   21.23 +    bool me;                    // if this is the local user herself/himself
   21.24 +    */
   21.25 +
   21.26 +int test_identity_equals(pEp_identity* val1, pEp_identity* val2) {
   21.27 +    assert(val1);
   21.28 +    assert(val2);
   21.29 +    assert(val1->address);
   21.30 +    assert(val2->address);
   21.31 +    assert(val1->fpr);
   21.32 +    assert(val2->fpr);
   21.33 +    assert(val1->username);
   21.34 +    assert(val2->username);
   21.35 +    return((strcmp(val1->address, val2->address) == 0) && (strcmp(val1->fpr, val2->fpr) == 0)
   21.36 +        && (strcmp(val1->username, val2->username) == 0) && (val1->comm_type == val2->comm_type)
   21.37 +        && (val1->lang[0] == val2->lang[0]) && (val1->lang[1] == val2->lang[1])
   21.38 +        && (val1->lang[2] == val2->lang[2]) && (val1->me == val2->me));
   21.39 +}
   21.40 +
   21.41 +int main() {
   21.42 +    cout << "\n*** data structures: identity_list_test ***\n\n";
   21.43 +
   21.44 +    pEp_identity* id1 = new_identity(
   21.45 +        "leon.schumacher@digitalekho.com",
   21.46 +        "8BD08954C74D830EEFFB5DEB2682A17F7C87F73D",
   21.47 +        "23",
   21.48 +        "Leon Schumacher"
   21.49 +    );
   21.50 +    id1->comm_type = PEP_ct_pEp;
   21.51 +    
   21.52 +    pEp_identity* id2 = new_identity(
   21.53 +        "krista@kgrothoff.org",
   21.54 +        "62D4932086185C15917B72D30571AFBCA5493553",
   21.55 +        "42",
   21.56 +        "Krista Bennett Grothoff"
   21.57 +    );
   21.58 +    
   21.59 +    id2->comm_type = PEP_ct_OpenPGP;
   21.60 +
   21.61 +    pEp_identity* id3 = new_identity(
   21.62 +        "krista@pep-project.org",
   21.63 +        "51BF42D25BB5B154D71BF6CD3CF25B776D149247",
   21.64 +        "10",
   21.65 +        "Krista Grothoff"
   21.66 +    );
   21.67 +    
   21.68 +    id3->comm_type = PEP_ct_OTR;
   21.69 +
   21.70 +    pEp_identity* id4 = new_identity(
   21.71 +        "papa@smurf.lu",
   21.72 +        "00001111222233334444555566667777DEADBEEF",
   21.73 +        "667",
   21.74 +        "Papa Smurf"
   21.75 +    );
   21.76 +    
   21.77 +    id4->comm_type = PEP_ct_key_b0rken;
   21.78 +    
   21.79 +    pEp_identity* id_arr[4] = {id1, id2, id3, id4};
   21.80 +        
   21.81 +    int i;
   21.82 +        
   21.83 +    cout << "creating one-element identity_list...\n";
   21.84 +    
   21.85 +    pEp_identity* new_id = identity_dup(id1);
   21.86 +    assert(new_id);
   21.87 +    identity_list* idlist = new_identity_list(new_id);
   21.88 +    assert(idlist->ident);
   21.89 +    assert(test_identity_equals(id1, idlist->ident));
   21.90 +    assert(idlist->next == NULL);
   21.91 +    cout << "one-element identity_list created, next element is NULL\n\n";
   21.92 +    
   21.93 +    cout << "duplicating one-element list...\n";
   21.94 +    identity_list* duplist = identity_list_dup(idlist);
   21.95 +    pEp_identity* srcid = idlist->ident;
   21.96 +    pEp_identity* dstid = duplist->ident;
   21.97 +    assert(dstid);
   21.98 +    assert(test_identity_equals(srcid, dstid));
   21.99 +    assert(srcid->address != dstid->address);   // test deep copies 
  21.100 +    assert(srcid->fpr != dstid->fpr);
  21.101 +    assert(srcid->username != dstid->username);
  21.102 +    assert(duplist->next == NULL);
  21.103 +    cout << "one-element identity_list duplicated.\n\n";
  21.104 +    
  21.105 +    cout << "freeing identity_lists...\n";
  21.106 +    free_identity_list(idlist); // will free srcid
  21.107 +    free_identity_list(duplist);
  21.108 +    idlist = NULL;
  21.109 +    duplist = NULL;
  21.110 +    srcid = NULL;
  21.111 +    
  21.112 +    identity_list* p;
  21.113 +    cout << "\ncreating four-element list...\n";
  21.114 +    idlist = identity_list_add(idlist, identity_dup(id_arr[0]));
  21.115 +    for (i = 1; i < 4; i++) {
  21.116 +        p = identity_list_add(idlist, identity_dup(id_arr[i]));
  21.117 +        assert(p);
  21.118 +    }
  21.119 +    
  21.120 +    p = idlist;
  21.121 +    
  21.122 +    for (i = 0; i < 4; i++) {
  21.123 +        assert(p);
  21.124 +        
  21.125 +        srcid = p->ident;
  21.126 +        assert(srcid);
  21.127 +        
  21.128 +        assert(test_identity_equals(srcid, id_arr[i]));
  21.129 +        assert(srcid->address != id_arr[i]->address);   // test deep copies
  21.130 +        assert(srcid->fpr != id_arr[i]->fpr);
  21.131 +        assert(srcid->username != id_arr[i]->username);
  21.132 +
  21.133 +        p = p->next;
  21.134 +    }
  21.135 +    assert(p == NULL);
  21.136 +    
  21.137 +    cout << "\nduplicating four-element list...\n\n";
  21.138 +    duplist = identity_list_dup(idlist);
  21.139 +    
  21.140 +    p = idlist;
  21.141 +    identity_list* dup_p = duplist;
  21.142 +    
  21.143 +    while (dup_p) {
  21.144 +        srcid = p->ident;
  21.145 +        dstid = dup_p->ident;
  21.146 +
  21.147 +        assert(dstid);
  21.148 +        
  21.149 +        assert(test_identity_equals(srcid, dstid));
  21.150 +
  21.151 +        assert(srcid != dstid);   // test deep copies
  21.152 +        assert(srcid->address != dstid->address);   // test deep copies
  21.153 +        assert(srcid->fpr != dstid->fpr);
  21.154 +        assert(srcid->username != dstid->username);
  21.155 +        
  21.156 +        i++;
  21.157 +        p = p->next;
  21.158 +
  21.159 +        dup_p = dup_p->next;
  21.160 +        assert((p == NULL) == (dup_p == NULL));
  21.161 +    }
  21.162 +    cout << "\nfour-element identity_list successfully duplicated.\n\n";
  21.163 +
  21.164 +    cout << "freeing identity_lists...\n";
  21.165 +    free_identity_list(idlist); // will free srcid
  21.166 +    free_identity_list(duplist);
  21.167 +    idlist = NULL;
  21.168 +    duplist = NULL;
  21.169 +    
  21.170 +    cout << "done.\n";
  21.171 +        
  21.172 +    
  21.173 +    return 0;
  21.174 +}
  21.175 +