/*
 # $Id: md5_calc.c,v 1.1 1997/09/02 13:34:27 fbm Exp fbm $
 # Copyright (C) 1997 Farrell McKay
 # All rights reserved.
 #
 # This file is part of the Fortify distribution, a toolkit for
 # upgrading the cryptographic strength of the Netscape Navigator
 # web browser, authored by Farrell McKay.
 #
 # This toolkit is provided to the recipient under the
 # following terms and conditions:-
 #   1.  This copyright notice must not be removed or modified.
 #   2.  This toolkit may not be reproduced or included in any commercial
 #       media distribution, or commercial publication (for example CD-ROM,
 #       disk, book, magazine, journal) without first obtaining the author's
 #       permission.
 #   3.  Subject to the above conditions being observed (1,2), this toolkit
 #       may be freely reproduced or redistributed.
 #   4.  This software is provided "as-is", without express or implied
 #       warranty.  In no event shall the author be liable for any direct,
 #       indirect or consequential damages however caused.
 #   5.  Subject to the above conditions being observed (1-4),
 #       this toolkit may be used at no cost to the recipient.
 #
 # Farrell McKay			Farrell.McKay@mpx.com.au
 */

#include <stdio.h>
#include <unistd.h>
#include "md5.h"

#ifdef  GNU_WIN32
typedef long    off_t;
#endif

static void
range(char *s, long *_start, long *_stop)
{
	long	start, stop;

	start = strtol(s, &s, 0);
	if (*s == '\0')
		stop = start;
	else if (*s == '-' || *s == ':') {
		stop = (*s == ':')? start: 0;
		if (*(++s) == '\0')
			stop = -1;
		else
			stop += strtol(s, &s, 0);
	}

	if (start < 0 || (stop < start && stop >= 0))
		fprintf(stderr, "Warning, bad range ignored: %d to %d\n",
			start, stop
		);
	else {
		*_start = start;
		*_stop = stop;
	}
}

#define BUFSIZE 1024*16

char *
md5_calc(int fd, char *r)
{
        int                     i, nb;
        MD5_CTX                 c;
	long			start = 0;
	long			stop = -1;
	long			posn = 0;
        unsigned char           *p, md[MD5_DIGEST_LENGTH];
        static unsigned char    buf[BUFSIZE];

	MD5_Init(&c);

	if (r && *r)
		range(r, &start, &stop);
	if (start > 0)
		posn = (long) lseek(fd, (off_t) start, SEEK_SET);

	while (posn < stop || stop < 0) {
		nb = sizeof(buf);
		if (stop > 0 && stop - posn < nb)
			nb = stop - posn;
		i = read(fd, buf, nb);
		if (i <= 0)
			break;
		MD5_Update(&c, buf, (unsigned long)i);
		posn += i;
	}

	MD5_Final(&(md[0]),&c);

        for (i = 0, p = buf; i < MD5_DIGEST_LENGTH; i++, p += 2)
                sprintf(p, "%02x", md[i]);
        return buf;
}
