source: python/vendor/Python-2.7.6/Modules/md5module.c

Last change on this file was 388, checked in by dmik, 11 years ago

python: Update vendor to 2.7.6.

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1
2/* MD5 module */
3
4/* This module provides an interface to the RSA Data Security,
5 Inc. MD5 Message-Digest Algorithm, described in RFC 1321.
6 It requires the files md5c.c and md5.h (which are slightly changed
7 from the versions in the RFC to avoid the "global.h" file.) */
8
9
10/* MD5 objects */
11
12#include "Python.h"
13#include "structmember.h"
14#include "md5.h"
15
16typedef struct {
17 PyObject_HEAD
18 md5_state_t md5; /* the context holder */
19} md5object;
20
21static PyTypeObject MD5type;
22
23#define is_md5object(v) ((v)->ob_type == &MD5type)
24
25static md5object *
26newmd5object(void)
27{
28 md5object *md5p;
29
30 md5p = PyObject_New(md5object, &MD5type);
31 if (md5p == NULL)
32 return NULL;
33
34 md5_init(&md5p->md5); /* actual initialisation */
35 return md5p;
36}
37
38
39/* MD5 methods */
40
41static void
42md5_dealloc(md5object *md5p)
43{
44 PyObject_Del(md5p);
45}
46
47
48/* MD5 methods-as-attributes */
49
50static PyObject *
51md5_update(md5object *self, PyObject *args)
52{
53 Py_buffer view;
54 Py_ssize_t n;
55 unsigned char *buf;
56
57 if (!PyArg_ParseTuple(args, "s*:update", &view))
58 return NULL;
59
60 n = view.len;
61 buf = (unsigned char *) view.buf;
62 while (n > 0) {
63 Py_ssize_t nbytes;
64 if (n > INT_MAX)
65 nbytes = INT_MAX;
66 else
67 nbytes = n;
68 md5_append(&self->md5, buf,
69 Py_SAFE_DOWNCAST(nbytes, Py_ssize_t, unsigned int));
70 buf += nbytes;
71 n -= nbytes;
72 }
73
74 PyBuffer_Release(&view);
75 Py_RETURN_NONE;
76}
77
78PyDoc_STRVAR(update_doc,
79"update (arg)\n\
80\n\
81Update the md5 object with the string arg. Repeated calls are\n\
82equivalent to a single call with the concatenation of all the\n\
83arguments.");
84
85
86static PyObject *
87md5_digest(md5object *self)
88{
89 md5_state_t mdContext;
90 unsigned char aDigest[16];
91
92 /* make a temporary copy, and perform the final */
93 mdContext = self->md5;
94 md5_finish(&mdContext, aDigest);
95
96 return PyString_FromStringAndSize((char *)aDigest, 16);
97}
98
99PyDoc_STRVAR(digest_doc,
100"digest() -> string\n\
101\n\
102Return the digest of the strings passed to the update() method so\n\
103far. This is a 16-byte string which may contain non-ASCII characters,\n\
104including null bytes.");
105
106
107static PyObject *
108md5_hexdigest(md5object *self)
109{
110 md5_state_t mdContext;
111 unsigned char digest[16];
112 unsigned char hexdigest[32];
113 int i, j;
114
115 /* make a temporary copy, and perform the final */
116 mdContext = self->md5;
117 md5_finish(&mdContext, digest);
118
119 /* Make hex version of the digest */
120 for(i=j=0; i<16; i++) {
121 char c;
122 c = (digest[i] >> 4) & 0xf;
123 c = (c>9) ? c+'a'-10 : c + '0';
124 hexdigest[j++] = c;
125 c = (digest[i] & 0xf);
126 c = (c>9) ? c+'a'-10 : c + '0';
127 hexdigest[j++] = c;
128 }
129 return PyString_FromStringAndSize((char*)hexdigest, 32);
130}
131
132
133PyDoc_STRVAR(hexdigest_doc,
134"hexdigest() -> string\n\
135\n\
136Like digest(), but returns the digest as a string of hexadecimal digits.");
137
138
139static PyObject *
140md5_copy(md5object *self)
141{
142 md5object *md5p;
143
144 if ((md5p = newmd5object()) == NULL)
145 return NULL;
146
147 md5p->md5 = self->md5;
148
149 return (PyObject *)md5p;
150}
151
152PyDoc_STRVAR(copy_doc,
153"copy() -> md5 object\n\
154\n\
155Return a copy (``clone'') of the md5 object.");
156
157
158static PyMethodDef md5_methods[] = {
159 {"update", (PyCFunction)md5_update, METH_VARARGS, update_doc},
160 {"digest", (PyCFunction)md5_digest, METH_NOARGS, digest_doc},
161 {"hexdigest", (PyCFunction)md5_hexdigest, METH_NOARGS, hexdigest_doc},
162 {"copy", (PyCFunction)md5_copy, METH_NOARGS, copy_doc},
163 {NULL, NULL} /* sentinel */
164};
165
166static PyObject *
167md5_get_block_size(PyObject *self, void *closure)
168{
169 return PyInt_FromLong(64);
170}
171
172static PyObject *
173md5_get_digest_size(PyObject *self, void *closure)
174{
175 return PyInt_FromLong(16);
176}
177
178static PyObject *
179md5_get_name(PyObject *self, void *closure)
180{
181 return PyString_FromStringAndSize("MD5", 3);
182}
183
184static PyGetSetDef md5_getseters[] = {
185 {"digest_size",
186 (getter)md5_get_digest_size, NULL,
187 NULL,
188 NULL},
189 {"block_size",
190 (getter)md5_get_block_size, NULL,
191 NULL,
192 NULL},
193 {"name",
194 (getter)md5_get_name, NULL,
195 NULL,
196 NULL},
197 /* the old md5 and sha modules support 'digest_size' as in PEP 247.
198 * the old sha module also supported 'digestsize'. ugh. */
199 {"digestsize",
200 (getter)md5_get_digest_size, NULL,
201 NULL,
202 NULL},
203 {NULL} /* Sentinel */
204};
205
206
207PyDoc_STRVAR(module_doc,
208"This module implements the interface to RSA's MD5 message digest\n\
209algorithm (see also Internet RFC 1321). Its use is quite\n\
210straightforward: use the new() to create an md5 object. You can now\n\
211feed this object with arbitrary strings using the update() method, and\n\
212at any point you can ask it for the digest (a strong kind of 128-bit\n\
213checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
214fed to it so far using the digest() method.\n\
215\n\
216Functions:\n\
217\n\
218new([arg]) -- return a new md5 object, initialized with arg if provided\n\
219md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
220\n\
221Special Objects:\n\
222\n\
223MD5Type -- type object for md5 objects");
224
225PyDoc_STRVAR(md5type_doc,
226"An md5 represents the object used to calculate the MD5 checksum of a\n\
227string of information.\n\
228\n\
229Methods:\n\
230\n\
231update() -- updates the current digest with an additional string\n\
232digest() -- return the current digest value\n\
233hexdigest() -- return the current digest as a string of hexadecimal digits\n\
234copy() -- return a copy of the current md5 object");
235
236static PyTypeObject MD5type = {
237 PyVarObject_HEAD_INIT(NULL, 0)
238 "_md5.md5", /*tp_name*/
239 sizeof(md5object), /*tp_size*/
240 0, /*tp_itemsize*/
241 /* methods */
242 (destructor)md5_dealloc, /*tp_dealloc*/
243 0, /*tp_print*/
244 0, /*tp_getattr*/
245 0, /*tp_setattr*/
246 0, /*tp_compare*/
247 0, /*tp_repr*/
248 0, /*tp_as_number*/
249 0, /*tp_as_sequence*/
250 0, /*tp_as_mapping*/
251 0, /*tp_hash*/
252 0, /*tp_call*/
253 0, /*tp_str*/
254 0, /*tp_getattro*/
255 0, /*tp_setattro*/
256 0, /*tp_as_buffer*/
257 Py_TPFLAGS_DEFAULT, /*tp_flags*/
258 md5type_doc, /*tp_doc*/
259 0, /*tp_traverse*/
260 0, /*tp_clear*/
261 0, /*tp_richcompare*/
262 0, /*tp_weaklistoffset*/
263 0, /*tp_iter*/
264 0, /*tp_iternext*/
265 md5_methods, /*tp_methods*/
266 0, /*tp_members*/
267 md5_getseters, /*tp_getset*/
268};
269
270
271/* MD5 functions */
272
273static PyObject *
274MD5_new(PyObject *self, PyObject *args)
275{
276 md5object *md5p;
277 Py_buffer view = { 0 };
278 Py_ssize_t n;
279 unsigned char *buf;
280
281 if (!PyArg_ParseTuple(args, "|s*:new", &view))
282 return NULL;
283
284 if ((md5p = newmd5object()) == NULL) {
285 PyBuffer_Release(&view);
286 return NULL;
287 }
288
289 n = view.len;
290 buf = (unsigned char *) view.buf;
291 while (n > 0) {
292 Py_ssize_t nbytes;
293 if (n > INT_MAX)
294 nbytes = INT_MAX;
295 else
296 nbytes = n;
297 md5_append(&md5p->md5, buf,
298 Py_SAFE_DOWNCAST(nbytes, Py_ssize_t, unsigned int));
299 buf += nbytes;
300 n -= nbytes;
301 }
302 PyBuffer_Release(&view);
303
304 return (PyObject *)md5p;
305}
306
307PyDoc_STRVAR(new_doc,
308"new([arg]) -> md5 object\n\
309\n\
310Return a new md5 object. If arg is present, the method call update(arg)\n\
311is made.");
312
313
314/* List of functions exported by this module */
315
316static PyMethodDef md5_functions[] = {
317 {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
318 {NULL, NULL} /* Sentinel */
319};
320
321
322/* Initialize this module. */
323
324PyMODINIT_FUNC
325init_md5(void)
326{
327 PyObject *m, *d;
328
329 Py_TYPE(&MD5type) = &PyType_Type;
330 if (PyType_Ready(&MD5type) < 0)
331 return;
332 m = Py_InitModule3("_md5", md5_functions, module_doc);
333 if (m == NULL)
334 return;
335 d = PyModule_GetDict(m);
336 PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
337 PyModule_AddIntConstant(m, "digest_size", 16);
338 /* No need to check the error here, the caller will do that */
339}
Note: See TracBrowser for help on using the repository browser.