/*
 * Copyright (C) 1996 Michael R. Elkins <me@cs.hmc.edu>
 * 
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */ 

#include "muttlib.h"
#include "rfc1864.h"
#include "rfc1321.h"

#include <stdio.h>
#include <ctype.h>
#include <string.h>


/* Currently, there is no error checking (what could cause an error here?)
 */
void mutt_content_md5(BODY *a)
{
  FILE *fp;

  fp = fopen(a->filename,"r");
  fseek(fp,a->offset,0);
  a->md5 = rfc1864_md5_file(fp);
  fclose(fp);
}

/* Given a file that is already open (and possibly not at the beginning),
 * return the base64 encoding of the md5 of the content.  This routine
 * allocates memory.
 * 
 * The routine has a lineage, it may have originally come from:
 *     mpack, John G. Myers - jgm+@cmu.edu 
 *  It may also be:   
 *  Copyright (C) 1993,1994 by Carnegie Mellon University
 *  Copyright (C) 1991 Bell Communications Research, Inc. (Bellcore)
 *  
 *  Seem a little ridiculous for 35 lines of code?
 *   
 */
char *rfc1864_md5_file(FILE *fp)
{
  rfc1321_MD5_CTX context;
  char buf[1000];
  unsigned char digest[18];
  long length = 0;
  int nbytes;
  int i;
  char *p;
  char *encodedDigest;
                    
  rfc1321_MD5Init(&context);
  while ((nbytes = fread(buf, 1, sizeof(buf), fp))) {
    length += nbytes;
    rfc1321_MD5Update(&context, buf, nbytes);
  }
  rfc1321_MD5Final(digest, &context);
  digest[sizeof(digest)-1] = digest[sizeof(digest)-2] = 0;  

  encodedDigest = (char *)safe_malloc(25 * sizeof(char));

  /* Seems there is no base64_encode_string in mutt yet, so we'll do it
   * right here.  Michael may want to add one later.
   */

  p = encodedDigest;
  for (i=0; i < sizeof(digest); i+=3) {
    *p++ = Base64_chars[digest[i]>>2];
    *p++ = Base64_chars[((digest[i] & 0x3)<<4) | ((digest[i+1] & 0xF0)>>4)];
    *p++ = Base64_chars[((digest[i+1] & 0xF)<<2) | ((digest[i+2] & 0xC0)>>6)];+
    *p++ = Base64_chars[digest[i+2] & 0x3F];
  }
  *p-- = '\0';
  *p-- = '=';
  *p-- = '=';
  return encodedDigest;                
}
