int mailmime_smart_remove_part(struct mailmime * mime)
{
  struct mailmime * parent;
  int res;

  parent = mime->mm_parent;
  if (parent == NULL) {
    res = MAILIMF_ERROR_INVAL;
    goto err;
  }

  switch (mime->mm_type) {
  case MAILMIME_MESSAGE:
    if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
      res = MAILIMF_ERROR_INVAL;
      goto err;
    }

    mailmime_remove_part(mime);
    
    mailmime_free(mime);

    return MAILIMF_NO_ERROR;

  case MAILMIME_MULTIPLE:
    if (!clist_isempty(mime->mm_data.mm_multipart.mm_mp_list)) {
      res = MAILIMF_ERROR_INVAL;
      goto err;
    }
      
    mailmime_remove_part(mime);
    
    mailmime_free(mime);
    
    return MAILIMF_NO_ERROR;

  case MAILMIME_SINGLE:
    mailmime_remove_part(mime);

    mailmime_free(mime);

    return MAILIMF_NO_ERROR;
    
  default:
    return MAILIMF_ERROR_INVAL;
  }

 err:
  return res;
}
int mailprivacy_get_part_from_file(struct mailprivacy * privacy,
    int check_security, int reencode, char * filename,
    struct mailmime ** result_mime)
{
  int fd;
  struct mailmime * mime;
  int r;
  struct stat stat_info;
  int res;
  char * mapping;

  fd = open(filename, O_RDONLY);
  if (fd < 0) {
    res = MAIL_ERROR_FILE;
    goto err;
  }

  r = fstat(fd, &stat_info);
  if (r < 0) {
    res = MAIL_ERROR_FILE;
    goto close;
  }

  mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (mapping == (char *)MAP_FAILED) {
    res = MAIL_ERROR_FILE;
    goto close;
  }
  
  mime = NULL;
  /* check recursive parts if privacy is set */
  r = mailprivacy_get_mime(privacy, check_security, reencode,
      mapping, stat_info.st_size, &mime);
  if (r != MAIL_NO_ERROR) {
    res =  r;
    goto unmap;
  }

  if (mime->mm_type == MAILMIME_MESSAGE) {
    struct mailmime * submime;
    
    submime = mime->mm_data.mm_message.mm_msg_mime;
    if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
      mailmime_remove_part(submime);
      mailmime_free(mime);
      
      mime = submime;
    }
  }

  munmap(mapping, stat_info.st_size);
  
  close(fd);

  * result_mime = mime;

  return MAIL_NO_ERROR;
  
 unmap:
  munmap(mapping, stat_info.st_size);
 close:
  close(fd);
 err:
  return res;
}
int mailmime_smart_add_part(struct mailmime * mime,
    struct mailmime * mime_sub)
{
  struct mailmime * saved_sub;
  struct mailmime * mp;
  int res;
  int r;

  switch (mime->mm_type) {
  case MAILMIME_SINGLE:
    res = MAILIMF_ERROR_INVAL;
    goto err;

  case MAILMIME_MULTIPLE:
    r = mailmime_add_part(mime, mime_sub);
    if (r != MAILIMF_NO_ERROR) {
      res = MAILIMF_ERROR_MEMORY;
      goto err;
    }

    return MAILIMF_NO_ERROR;
  }

  /* MAILMIME_MESSAGE */

  if (mime->mm_data.mm_message.mm_msg_mime == NULL) {
    /* there is no subpart, we can simply attach it */
    
    r = mailmime_add_part(mime, mime_sub);
    if (r != MAILIMF_NO_ERROR) {
      res = MAILIMF_ERROR_MEMORY;
      goto err;
    }

    return MAILIMF_NO_ERROR;
  }

  if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE) {
    /* in case the subpart is multipart, simply attach it to the subpart */
    
    return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub);
  }

  /* we save the current subpart, ... */

  saved_sub = mime->mm_data.mm_message.mm_msg_mime;

  /* create a multipart */
  
  mp = mailmime_multiple_new("multipart/mixed");
  if (mp == NULL) {
    res = MAILIMF_ERROR_MEMORY;
    goto err;
  }

  /* detach the saved subpart from the parent */

  mailmime_remove_part(saved_sub);
  
  /* the created multipart is the new child of the parent */

  r = mailmime_add_part(mime, mp);
  if (r != MAILIMF_NO_ERROR) {
    res = MAILIMF_ERROR_MEMORY;
    goto free_mp;
  }

  /* then, attach the saved subpart and ... */
  
  r = mailmime_add_part(mp, saved_sub);
  if (r != MAILIMF_NO_ERROR) {
    res = MAILIMF_ERROR_MEMORY;
    goto free_saved_sub;
  }

  /* the given part to the parent */

  r = mailmime_add_part(mp, mime_sub);
  if (r != MAILIMF_NO_ERROR) {
    res = MAILIMF_ERROR_MEMORY;
    goto free_saved_sub;
  }

  return MAILIMF_NO_ERROR;

 free_mp:
  mailmime_free(mp);
 free_saved_sub:
  mailmime_free(saved_sub);
 err:
  return res;
}
Beispiel #4
0
static struct mailmime *
mime_add_alternative(struct mailprivacy * privacy,
    mailmessage * msg,
    struct mailmime * mime,
    struct mailmime * alternative)
{
  struct mailmime * multipart;
  int r;
  struct mailmime * mime_copy;
  char original_filename[PATH_MAX];
  
  if (mime->mm_parent == NULL)
    goto err;
  
  r = mailmime_new_with_content("multipart/alternative", NULL, &multipart);
  if (r != MAILIMF_NO_ERROR)
    goto err;
  
  r = mailmime_smart_add_part(multipart, alternative);
  if (r != MAILIMF_NO_ERROR) {
    goto free_multipart;
  }

  /* get copy of mime part "mime" and set parts */
  
  r = mailprivacy_fetch_mime_body_to_file(privacy,
      original_filename, sizeof(original_filename),
      msg, mime);
  if (r != MAIL_NO_ERROR)
    goto detach_alternative;
  
  r = mailprivacy_get_part_from_file(privacy, 0, 0,
      original_filename, &mime_copy);
  unlink(original_filename);
  if (r != MAIL_NO_ERROR) {
    goto detach_alternative;
  }
  
  r = mailmime_smart_add_part(multipart, mime_copy);
  if (r != MAILIMF_NO_ERROR) {
    goto free_mime_copy;
  }
  
  r = recursive_register_mime(privacy, multipart);
  if (r != MAIL_NO_ERROR)
    goto detach_mime_copy;
  
  mailmime_substitute(mime, multipart);
  
  mailmime_free(mime);
  
  return multipart;
  
 detach_mime_copy:
  mailprivacy_recursive_unregister_mime(privacy, multipart);
  mailmime_remove_part(alternative);
 free_mime_copy:
  mailprivacy_mime_clear(mime_copy);
  mailmime_free(mime_copy);
 detach_alternative:
  mailmime_remove_part(alternative);
 free_multipart:
  mailmime_free(multipart);
 err:
  return NULL;
}