
/* MD5 module */

/* This module provides an interface to the RSA Data Security,
   Inc. MD5 Message-Digest Algorithm, described in RFC 1321.
   It requires the files md5c.c and md5.h (which are slightly changed
   from the versions in the RFC to avoid the "global.h" file.) */


/* MD5 objects */

#include "Python.h"
#include "md5.h"

typedef struct {
	PyObject_HEAD
        MD5_CTX	md5;		/* the context holder */
} md5object;

static PyTypeObject MD5type;

#define is_md5object(v)		((v)->ob_type == &MD5type)

static md5object *
newmd5object(void)
{
	md5object *md5p;

	md5p = PyObject_New(md5object, &MD5type);
	if (md5p == NULL)
		return NULL;

	MD5Init(&md5p->md5);	/* actual initialisation */
	return md5p;
}


/* MD5 methods */

static void
md5_dealloc(md5object *md5p)
{
	PyObject_Del(md5p);
}


/* MD5 methods-as-attributes */

static PyObject *
md5_update(md5object *self, PyObject *args)
{
	unsigned char *cp;
	int len;

	if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
		return NULL;

	MD5Update(&self->md5, cp, len);

	Py_INCREF(Py_None);
	return Py_None;
}

PyDoc_STRVAR(update_doc,
"update (arg)\n\
\n\
Update the md5 object with the string arg. Repeated calls are\n\
equivalent to a single call with the concatenation of all the\n\
arguments.");


static PyObject *
md5_digest(md5object *self)
{
 	MD5_CTX mdContext;
	unsigned char aDigest[16];

	/* make a temporary copy, and perform the final */
	mdContext = self->md5;
	MD5Final(aDigest, &mdContext);

	return PyString_FromStringAndSize((char *)aDigest, 16);
}

PyDoc_STRVAR(digest_doc,
"digest() -> string\n\
\n\
Return the digest of the strings passed to the update() method so\n\
far. This is a 16-byte string which may contain non-ASCII characters,\n\
including null bytes.");


static PyObject *
md5_hexdigest(md5object *self)
{
 	MD5_CTX mdContext;
	unsigned char digest[16];
	unsigned char hexdigest[32];
	int i, j;

	/* make a temporary copy, and perform the final */
	mdContext = self->md5;
	MD5Final(digest, &mdContext);

	/* Make hex version of the digest */
	for(i=j=0; i<16; i++) {
		char c;
		c = (digest[i] >> 4) & 0xf;
		c = (c>9) ? c+'a'-10 : c + '0';
		hexdigest[j++] = c;
		c = (digest[i] & 0xf);
		c = (c>9) ? c+'a'-10 : c + '0';
		hexdigest[j++] = c;
	}
	return PyString_FromStringAndSize((char*)hexdigest, 32);
}


PyDoc_STRVAR(hexdigest_doc,
"hexdigest() -> string\n\
\n\
Like digest(), but returns the digest as a string of hexadecimal digits.");


static PyObject *
md5_copy(md5object *self)
{
	md5object *md5p;

	if ((md5p = newmd5object()) == NULL)
		return NULL;

	md5p->md5 = self->md5;

	return (PyObject *)md5p;
}

PyDoc_STRVAR(copy_doc,
"copy() -> md5 object\n\
\n\
Return a copy (``clone'') of the md5 object.");


static PyMethodDef md5_methods[] = {
	{"update",    (PyCFunction)md5_update,    METH_VARARGS, update_doc},
	{"digest",    (PyCFunction)md5_digest,    METH_NOARGS,  digest_doc},
	{"hexdigest", (PyCFunction)md5_hexdigest, METH_NOARGS,  hexdigest_doc},
	{"copy",      (PyCFunction)md5_copy,      METH_NOARGS,  copy_doc},
	{NULL, NULL}			     /* sentinel */
};

static PyObject *
md5_getattr(md5object *self, char *name)
{
        if (strcmp(name, "digest_size") == 0) {
    		return PyInt_FromLong(16);
        }

	return Py_FindMethod(md5_methods, (PyObject *)self, name);
}

PyDoc_STRVAR(module_doc,
"This module implements the interface to RSA's MD5 message digest\n\
algorithm (see also Internet RFC 1321). Its use is quite\n\
straightforward: use the new() to create an md5 object. You can now\n\
feed this object with arbitrary strings using the update() method, and\n\
at any point you can ask it for the digest (a strong kind of 128-bit\n\
checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
fed to it so far using the digest() method.\n\
\n\
Functions:\n\
\n\
new([arg]) -- return a new md5 object, initialized with arg if provided\n\
md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
\n\
Special Objects:\n\
\n\
MD5Type -- type object for md5 objects");

PyDoc_STRVAR(md5type_doc,
"An md5 represents the object used to calculate the MD5 checksum of a\n\
string of information.\n\
\n\
Methods:\n\
\n\
update() -- updates the current digest with an additional string\n\
digest() -- return the current digest value\n\
hexdigest() -- return the current digest as a string of hexadecimal digits\n\
copy() -- return a copy of the current md5 object");

static PyTypeObject MD5type = {
	PyObject_HEAD_INIT(NULL)
	0,			  /*ob_size*/
	"md5.md5",		  /*tp_name*/
	sizeof(md5object),	  /*tp_size*/
	0,			  /*tp_itemsize*/
	/* methods */
	(destructor)md5_dealloc,  /*tp_dealloc*/
	0,			  /*tp_print*/
	(getattrfunc)md5_getattr, /*tp_getattr*/
	0,			  /*tp_setattr*/
	0,			  /*tp_compare*/
	0,			  /*tp_repr*/
        0,			  /*tp_as_number*/
	0,                        /*tp_as_sequence*/
	0,			  /*tp_as_mapping*/
	0, 			  /*tp_hash*/
	0,			  /*tp_call*/
	0,			  /*tp_str*/
	0,			  /*tp_getattro*/
	0,			  /*tp_setattro*/
	0,	                  /*tp_as_buffer*/
	0,			  /*tp_xxx4*/
	md5type_doc,		  /*tp_doc*/
};


/* MD5 functions */

static PyObject *
MD5_new(PyObject *self, PyObject *args)
{
	md5object *md5p;
	unsigned char *cp = NULL;
	int len = 0;

	if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
		return NULL;

	if ((md5p = newmd5object()) == NULL)
		return NULL;

	if (cp)
		MD5Update(&md5p->md5, cp, len);

	return (PyObject *)md5p;
}

PyDoc_STRVAR(new_doc,
"new([arg]) -> md5 object\n\
\n\
Return a new md5 object. If arg is present, the method call update(arg)\n\
is made.");


/* List of functions exported by this module */

static PyMethodDef md5_functions[] = {
	{"new",		(PyCFunction)MD5_new, METH_VARARGS, new_doc},
	{"md5",		(PyCFunction)MD5_new, METH_VARARGS, new_doc}, /* Backward compatibility */
	{NULL,		NULL}	/* Sentinel */
};


/* Initialize this module. */

PyMODINIT_FUNC
initmd5(void)
{
	PyObject *m, *d;

        MD5type.ob_type = &PyType_Type;
	m = Py_InitModule3("md5", md5_functions, module_doc);
	d = PyModule_GetDict(m);
	PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
	PyModule_AddIntConstant(m, "digest_size", 16);
	/* No need to check the error here, the caller will do that */
}
