Mercurial > hg > xemacs-beta
annotate src/md5.c @ 5518:3cc7470ea71c
gnuclient: if TMPDIR was set and connect failed, try again with /tmp
2011-06-03 Aidan Kehoe <kehoea@parhasard.net>
* gnuslib.c (connect_to_unix_server):
Retry with /tmp as a directory in which to search for Unix sockets
if an attempt to connect with some other directory failed (which
may be because gnuclient and gnuserv don't share an environment
value for TMPDIR, or because gnuserv was compiled with USE_TMPDIR
turned off).
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Fri, 03 Jun 2011 18:40:57 +0100 |
parents | 308d34e9f07d |
children |
rev | line source |
---|---|
428 | 1 /* md5.c - Functions to compute MD5 message digest of files or memory blocks |
2 according to the definition of MD5 in RFC 1321 from April 1992. | |
3 Copyright (C) 1995, 1996 Free Software Foundation, Inc. | |
800 | 4 Copyright (C) 2001, 2002 Ben Wing. |
428 | 5 NOTE: The canonical source of this file is maintained with the GNU C |
6 Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. | |
7 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
8 This file is part of XEmacs. |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
9 |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
10 XEmacs is free software: you can redistribute it and/or modify it |
428 | 11 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
12 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
13 option) any later version. |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
14 |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
18 for more details. |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
19 |
428 | 20 You should have received a copy of the GNU General Public License |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3462
diff
changeset
|
21 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 22 /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ |
23 | |
24 /* XEmacs frontend written by Ben Wing, Jareth Hein and Hrvoje Niksic. */ | |
25 | |
26 #ifdef HAVE_CONFIG_H | |
27 # include <config.h> | |
28 #endif | |
29 | |
30 #include <sys/types.h> | |
31 #include <string.h> | |
32 #include <stdio.h> | |
442 | 33 #include <limits.h> |
428 | 34 |
35 /* The following contortions are an attempt to use the C preprocessor | |
36 to determine an unsigned integral type that is 32 bits wide. An | |
37 alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but | |
38 doing that would require that the configure script compile and *run* | |
39 the resulting executable. Locally running cross-compiled executables | |
40 is usually not possible. */ | |
41 | |
42 #ifdef _LIBC | |
43 # include <sys/types.h> | |
44 typedef u_int32_t md5_uint32; | |
45 #else | |
46 # if defined __STDC__ && __STDC__ | |
47 # define UINT_MAX_32_BITS 4294967295U | |
48 # else | |
49 # define UINT_MAX_32_BITS 0xFFFFFFFF | |
50 # endif | |
51 | |
52 /* If UINT_MAX isn't defined, assume it's a 32-bit type. | |
53 This should be valid for all systems GNU cares about because | |
54 that doesn't include 16-bit systems, and only modern systems | |
55 (that certainly have <limits.h>) have 64+-bit integral types. */ | |
56 | |
57 # ifndef UINT_MAX | |
58 # define UINT_MAX UINT_MAX_32_BITS | |
59 # endif | |
60 | |
61 # if UINT_MAX == UINT_MAX_32_BITS | |
62 typedef unsigned int md5_uint32; | |
63 # else | |
64 # if USHRT_MAX == UINT_MAX_32_BITS | |
65 typedef unsigned short md5_uint32; | |
66 # else | |
67 # if ULONG_MAX == UINT_MAX_32_BITS | |
68 typedef unsigned long md5_uint32; | |
69 # else | |
70 /* The following line is intended to evoke an error. | |
71 Using #error is not portable enough. */ | |
72 "Cannot determine unsigned 32-bit data type." | |
73 # endif | |
74 # endif | |
75 # endif | |
76 #endif | |
77 | |
78 #include "lisp.h" | |
79 #include "buffer.h" | |
80 #include "lstream.h" | |
81 # include "file-coding.h" | |
82 | |
83 /* Structure to save state of computation between the single steps. */ | |
84 struct md5_ctx | |
85 { | |
86 md5_uint32 A; | |
87 md5_uint32 B; | |
88 md5_uint32 C; | |
89 md5_uint32 D; | |
90 | |
91 md5_uint32 total[2]; | |
92 md5_uint32 buflen; | |
93 char buffer[128]; | |
94 }; | |
95 | |
96 #ifdef WORDS_BIGENDIAN | |
97 # define SWAP(n) \ | |
98 (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) | |
99 #else | |
100 # define SWAP(n) (n) | |
101 #endif | |
102 | |
103 | |
104 /* This array contains the bytes used to pad the buffer to the next | |
105 64-byte boundary. (RFC 1321, 3.1: Step 1) */ | |
106 static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; | |
107 | |
108 | |
442 | 109 static void md5_process_block (const void *, size_t, struct md5_ctx *); |
428 | 110 |
111 | |
112 /* Initialize structure containing state of computation. | |
113 (RFC 1321, 3.3: Step 3) */ | |
114 static void | |
115 md5_init_ctx (struct md5_ctx *ctx) | |
116 { | |
117 ctx->A = 0x67452301; | |
118 ctx->B = 0xefcdab89; | |
119 ctx->C = 0x98badcfe; | |
120 ctx->D = 0x10325476; | |
121 | |
122 ctx->total[0] = ctx->total[1] = 0; | |
123 ctx->buflen = 0; | |
124 } | |
125 | |
126 /* Put result from CTX in first 16 bytes following RESBUF. The result | |
127 must be in little endian byte order. | |
128 | |
129 IMPORTANT: On some systems it is required that RESBUF is correctly | |
130 aligned for a 32 bits value. */ | |
131 static void * | |
442 | 132 md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) |
428 | 133 { |
134 ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); | |
135 ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); | |
136 ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); | |
137 ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); | |
138 | |
139 return resbuf; | |
140 } | |
141 | |
142 /* Process the remaining bytes in the internal buffer and the usual | |
143 prolog according to the standard and write the result to RESBUF. | |
144 | |
145 IMPORTANT: On some systems it is required that RESBUF is correctly | |
146 aligned for a 32 bits value. */ | |
147 static void * | |
148 md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) | |
149 { | |
150 /* Take yet unprocessed bytes into account. */ | |
151 md5_uint32 bytes = ctx->buflen; | |
152 size_t pad; | |
153 | |
154 /* Now count remaining bytes. */ | |
155 ctx->total[0] += bytes; | |
156 if (ctx->total[0] < bytes) | |
157 ++ctx->total[1]; | |
158 | |
159 pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; | |
160 memcpy (&ctx->buffer[bytes], fillbuf, pad); | |
161 | |
162 /* Put the 64-bit file length in *bits* at the end of the buffer. */ | |
163 *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); | |
164 *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | | |
165 (ctx->total[0] >> 29)); | |
166 | |
167 /* Process last bytes. */ | |
168 md5_process_block (ctx->buffer, bytes + pad + 8, ctx); | |
169 | |
170 return md5_read_ctx (ctx, resbuf); | |
171 } | |
172 | |
173 #ifndef emacs /* unused in Emacs */ | |
174 /* Compute MD5 message digest for bytes read from STREAM. The | |
175 resulting message digest number will be written into the 16 bytes | |
176 beginning at RESBLOCK. */ | |
177 int | |
178 md5_stream (FILE *stream, void *resblock) | |
179 { | |
180 /* Important: BLOCKSIZE must be a multiple of 64. */ | |
181 #define BLOCKSIZE 4096 | |
182 struct md5_ctx ctx; | |
183 char buffer[BLOCKSIZE + 72]; | |
184 size_t sum; | |
185 | |
186 /* Initialize the computation context. */ | |
187 md5_init_ctx (&ctx); | |
188 | |
189 /* Iterate over full file contents. */ | |
190 while (1) | |
191 { | |
192 /* We read the file in blocks of BLOCKSIZE bytes. One call of the | |
193 computation function processes the whole buffer so that with the | |
194 next round of the loop another block can be read. */ | |
195 size_t n; | |
196 sum = 0; | |
197 | |
198 /* Read block. Take care for partial reads. */ | |
199 do | |
200 { | |
771 | 201 n = retry_fread (buffer + sum, 1, BLOCKSIZE - sum, stream); |
428 | 202 |
203 sum += n; | |
204 } | |
205 while (sum < BLOCKSIZE && n != 0); | |
206 if (n == 0 && ferror (stream)) | |
207 return 1; | |
208 | |
209 /* If end of file is reached, end the loop. */ | |
210 if (n == 0) | |
211 break; | |
212 | |
213 /* Process buffer with BLOCKSIZE bytes. Note that | |
214 BLOCKSIZE % 64 == 0 | |
215 */ | |
216 md5_process_block (buffer, BLOCKSIZE, &ctx); | |
217 } | |
218 | |
219 /* Add the last bytes if necessary. */ | |
220 if (sum > 0) | |
221 md5_process_bytes (buffer, sum, &ctx); | |
222 | |
223 /* Construct result in desired memory. */ | |
224 md5_finish_ctx (&ctx, resblock); | |
225 return 0; | |
226 } | |
227 | |
228 /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The | |
229 result is always in little endian byte order, so that a byte-wise | |
230 output yields to the wanted ASCII representation of the message | |
231 digest. */ | |
232 void * | |
233 md5_buffer (const char *buffer, size_t len, void *resblock) | |
234 { | |
235 struct md5_ctx ctx; | |
236 | |
237 /* Initialize the computation context. */ | |
238 md5_init_ctx (&ctx); | |
239 | |
240 /* Process whole buffer but last len % 64 bytes. */ | |
241 md5_process_bytes (buffer, len, &ctx); | |
242 | |
243 /* Put result in desired memory area. */ | |
244 return md5_finish_ctx (&ctx, resblock); | |
245 } | |
246 #endif /* not emacs */ | |
247 | |
248 | |
249 static void | |
442 | 250 md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) |
428 | 251 { |
252 /* When we already have some bits in our internal buffer concatenate | |
253 both inputs first. */ | |
254 if (ctx->buflen != 0) | |
255 { | |
256 size_t left_over = ctx->buflen; | |
257 size_t add = 128 - left_over > len ? len : 128 - left_over; | |
258 | |
259 memcpy (&ctx->buffer[left_over], buffer, add); | |
260 ctx->buflen += add; | |
261 | |
262 if (left_over + add > 64) | |
263 { | |
264 md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); | |
265 /* The regions in the following copy operation cannot overlap. */ | |
266 memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], | |
267 (left_over + add) & 63); | |
268 ctx->buflen = (left_over + add) & 63; | |
269 } | |
270 | |
271 buffer = (const char *) buffer + add; | |
272 len -= add; | |
273 } | |
274 | |
275 /* Process available complete blocks. */ | |
276 if (len > 64) | |
277 { | |
278 md5_process_block (buffer, len & ~63, ctx); | |
279 buffer = (const char *) buffer + (len & ~63); | |
280 len &= 63; | |
281 } | |
282 | |
283 /* Move remaining bytes in internal buffer. */ | |
284 if (len > 0) | |
285 { | |
286 memcpy (ctx->buffer, buffer, len); | |
287 ctx->buflen = len; | |
288 } | |
289 } | |
290 | |
291 | |
292 /* These are the four functions used in the four steps of the MD5 algorithm | |
293 and defined in the RFC 1321. The first function is a little bit optimized | |
294 (as found in Colin Plumbs public domain implementation). */ | |
295 /* #define FF(b, c, d) ((b & c) | (~b & d)) */ | |
296 #define FF(b, c, d) (d ^ (b & (c ^ d))) | |
297 #define FG(b, c, d) FF (d, b, c) | |
298 #define FH(b, c, d) (b ^ c ^ d) | |
299 #define FI(b, c, d) (c ^ (b | ~d)) | |
300 | |
301 /* Process LEN bytes of BUFFER, accumulating context into CTX. | |
302 It is assumed that LEN % 64 == 0. */ | |
303 | |
304 static void | |
442 | 305 md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) |
428 | 306 { |
307 md5_uint32 correct_words[16]; | |
308 const md5_uint32 *words = (const md5_uint32 *) buffer; | |
309 size_t nwords = len / sizeof (md5_uint32); | |
310 const md5_uint32 *endp = words + nwords; | |
311 md5_uint32 A = ctx->A; | |
312 md5_uint32 B = ctx->B; | |
313 md5_uint32 C = ctx->C; | |
314 md5_uint32 D = ctx->D; | |
315 | |
316 /* First increment the byte count. RFC 1321 specifies the possible | |
317 length of the file up to 2^64 bits. Here we only compute the | |
318 number of bytes. Do a double word increment. */ | |
319 ctx->total[0] += len; | |
320 if (ctx->total[0] < len) | |
321 ++ctx->total[1]; | |
322 | |
323 /* Process all bytes in the buffer with 64 bytes in each round of | |
324 the loop. */ | |
325 while (words < endp) | |
326 { | |
327 md5_uint32 *cwp = correct_words; | |
328 md5_uint32 A_save = A; | |
329 md5_uint32 B_save = B; | |
330 md5_uint32 C_save = C; | |
331 md5_uint32 D_save = D; | |
332 | |
333 /* First round: using the given function, the context and a constant | |
334 the next context is computed. Because the algorithms processing | |
335 unit is a 32-bit word and it is determined to work on words in | |
336 little endian byte order we perhaps have to change the byte order | |
337 before the computation. To reduce the work for the next steps | |
338 we store the swapped words in the array CORRECT_WORDS. */ | |
339 | |
340 #define OP(a, b, c, d, s, T) \ | |
341 do \ | |
342 { \ | |
343 a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ | |
344 ++words; \ | |
345 CYCLIC (a, s); \ | |
346 a += b; \ | |
347 } \ | |
348 while (0) | |
349 | |
350 /* It is unfortunate that C does not provide an operator for | |
351 cyclic rotation. Hope the C compiler is smart enough. */ | |
352 #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) | |
353 | |
354 /* Before we start, one word to the strange constants. | |
355 They are defined in RFC 1321 as | |
356 | |
357 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 | |
358 */ | |
359 | |
360 /* Round 1. */ | |
361 OP (A, B, C, D, 7, 0xd76aa478); | |
362 OP (D, A, B, C, 12, 0xe8c7b756); | |
363 OP (C, D, A, B, 17, 0x242070db); | |
364 OP (B, C, D, A, 22, 0xc1bdceee); | |
365 OP (A, B, C, D, 7, 0xf57c0faf); | |
366 OP (D, A, B, C, 12, 0x4787c62a); | |
367 OP (C, D, A, B, 17, 0xa8304613); | |
368 OP (B, C, D, A, 22, 0xfd469501); | |
369 OP (A, B, C, D, 7, 0x698098d8); | |
370 OP (D, A, B, C, 12, 0x8b44f7af); | |
371 OP (C, D, A, B, 17, 0xffff5bb1); | |
372 OP (B, C, D, A, 22, 0x895cd7be); | |
373 OP (A, B, C, D, 7, 0x6b901122); | |
374 OP (D, A, B, C, 12, 0xfd987193); | |
375 OP (C, D, A, B, 17, 0xa679438e); | |
376 OP (B, C, D, A, 22, 0x49b40821); | |
377 | |
378 /* For the second to fourth round we have the possibly swapped words | |
379 in CORRECT_WORDS. Redefine the macro to take an additional first | |
380 argument specifying the function to use. */ | |
381 #undef OP | |
382 #define OP(f, a, b, c, d, k, s, T) \ | |
383 do \ | |
384 { \ | |
385 a += f (b, c, d) + correct_words[k] + T; \ | |
386 CYCLIC (a, s); \ | |
387 a += b; \ | |
388 } \ | |
389 while (0) | |
390 | |
391 /* Round 2. */ | |
392 OP (FG, A, B, C, D, 1, 5, 0xf61e2562); | |
393 OP (FG, D, A, B, C, 6, 9, 0xc040b340); | |
394 OP (FG, C, D, A, B, 11, 14, 0x265e5a51); | |
395 OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); | |
396 OP (FG, A, B, C, D, 5, 5, 0xd62f105d); | |
397 OP (FG, D, A, B, C, 10, 9, 0x02441453); | |
398 OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); | |
399 OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); | |
400 OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); | |
401 OP (FG, D, A, B, C, 14, 9, 0xc33707d6); | |
402 OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); | |
403 OP (FG, B, C, D, A, 8, 20, 0x455a14ed); | |
404 OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); | |
405 OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); | |
406 OP (FG, C, D, A, B, 7, 14, 0x676f02d9); | |
407 OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); | |
408 | |
409 /* Round 3. */ | |
410 OP (FH, A, B, C, D, 5, 4, 0xfffa3942); | |
411 OP (FH, D, A, B, C, 8, 11, 0x8771f681); | |
412 OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); | |
413 OP (FH, B, C, D, A, 14, 23, 0xfde5380c); | |
414 OP (FH, A, B, C, D, 1, 4, 0xa4beea44); | |
415 OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); | |
416 OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); | |
417 OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); | |
418 OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); | |
419 OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); | |
420 OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); | |
421 OP (FH, B, C, D, A, 6, 23, 0x04881d05); | |
422 OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); | |
423 OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); | |
424 OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); | |
425 OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); | |
426 | |
427 /* Round 4. */ | |
428 OP (FI, A, B, C, D, 0, 6, 0xf4292244); | |
429 OP (FI, D, A, B, C, 7, 10, 0x432aff97); | |
430 OP (FI, C, D, A, B, 14, 15, 0xab9423a7); | |
431 OP (FI, B, C, D, A, 5, 21, 0xfc93a039); | |
432 OP (FI, A, B, C, D, 12, 6, 0x655b59c3); | |
433 OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); | |
434 OP (FI, C, D, A, B, 10, 15, 0xffeff47d); | |
435 OP (FI, B, C, D, A, 1, 21, 0x85845dd1); | |
436 OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); | |
437 OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); | |
438 OP (FI, C, D, A, B, 6, 15, 0xa3014314); | |
439 OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); | |
440 OP (FI, A, B, C, D, 4, 6, 0xf7537e82); | |
441 OP (FI, D, A, B, C, 11, 10, 0xbd3af235); | |
442 OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); | |
443 OP (FI, B, C, D, A, 9, 21, 0xeb86d391); | |
444 | |
445 /* Add the starting values of the context. */ | |
446 A += A_save; | |
447 B += B_save; | |
448 C += C_save; | |
449 D += D_save; | |
450 } | |
451 | |
452 /* Put checksum in context given as argument. */ | |
453 ctx->A = A; | |
454 ctx->B = B; | |
455 ctx->C = C; | |
456 ctx->D = D; | |
457 } | |
458 | |
459 | |
460 #ifdef emacs | |
461 /* Find out what format the buffer will be saved in, so we can make | |
462 the digest based on what it will look like on disk. */ | |
463 static Lisp_Object | |
464 md5_coding_system (Lisp_Object object, Lisp_Object coding, Lisp_Object istream, | |
465 int error_me_not) | |
466 { | |
467 Lisp_Object coding_system; | |
468 | |
469 if (NILP (coding)) | |
470 { | |
471 if (BUFFERP (object)) | |
771 | 472 /* Use the file coding for this buffer by default. */ |
473 coding = XBUFFER (object)->buffer_file_coding_system; | |
428 | 474 else |
771 | 475 /* Attempt to autodetect the coding of the string. This is |
476 VERY hit-and-miss. #### It shouldn't be. */ | |
477 coding = detect_coding_stream (istream); | |
478 } | |
479 | |
480 if (error_me_not) | |
481 { | |
482 coding_system = find_coding_system_for_text_file (coding, 0); | |
483 if (NILP (coding_system)) | |
484 /* Default to binary. */ | |
428 | 485 coding_system = Fget_coding_system (Qbinary); |
486 } | |
487 else | |
771 | 488 coding_system = get_coding_system_for_text_file (coding, 0); |
489 | |
428 | 490 return coding_system; |
491 } | |
492 | |
493 DEFUN ("md5", Fmd5, 1, 5, 0, /* | |
494 Return the MD5 message digest of OBJECT, a buffer or string. | |
495 | |
496 Optional arguments START and END denote positions for computing the | |
497 digest of a portion of OBJECT. | |
498 | |
499 The optional CODING argument specifies the coding system the text is to be | |
500 represented in while computing the digest. If unspecified, it defaults | |
501 to the current format of the data, or is guessed. | |
502 | |
503 If NOERROR is non-nil, silently assume binary coding if the guesswork | |
504 fails. Normally, an error is signaled in such case. | |
505 | |
506 CODING and NOERROR arguments are meaningful only in XEmacsen with | |
507 file-coding or Mule support. Otherwise, they are ignored. | |
508 */ | |
509 (object, start, end, coding, noerror)) | |
510 { | |
511 /* This function can GC */ | |
512 /* Can this really GC? How? */ | |
513 struct md5_ctx ctx; | |
514 unsigned char digest[16]; | |
515 unsigned char thehash[33]; | |
516 int i; | |
517 | |
800 | 518 Lisp_Object raw_instream = Qnil, instream = Qnil; |
519 struct gcpro gcpro1, gcpro2; | |
428 | 520 |
800 | 521 GCPRO2 (raw_instream, instream); |
428 | 522 /* Set up the input stream. */ |
523 if (BUFFERP (object)) | |
524 { | |
525 struct buffer *b; | |
665 | 526 Charbpos begv, endv; |
428 | 527 CHECK_LIVE_BUFFER (object); |
528 b = XBUFFER (object); | |
529 /* Figure out where we need to get info from */ | |
530 get_buffer_range_char (b, start, end, &begv, &endv, GB_ALLOW_NIL); | |
531 | |
800 | 532 raw_instream = make_lisp_buffer_input_stream (b, begv, endv, 0); |
428 | 533 } |
534 else | |
535 { | |
536 Bytecount bstart, bend; | |
537 CHECK_STRING (object); | |
538 get_string_range_byte (object, start, end, &bstart, &bend, | |
539 GB_HISTORICAL_STRING_BEHAVIOR); | |
800 | 540 raw_instream = make_lisp_string_input_stream (object, bstart, |
541 bend - bstart); | |
428 | 542 } |
543 | |
544 /* Determine the coding and set up the conversion stream. */ | |
800 | 545 coding = md5_coding_system (object, coding, raw_instream, !NILP (noerror)); |
546 Lstream_rewind (XLSTREAM (raw_instream)); | |
547 instream = make_coding_input_stream (XLSTREAM (raw_instream), coding, | |
548 CODING_ENCODE, 0); | |
428 | 549 |
550 /* Initialize MD5 context. */ | |
551 md5_init_ctx (&ctx); | |
552 | |
553 /* Get the data while doing the conversion. */ | |
554 while (1) | |
555 { | |
867 | 556 Ibyte tempbuf[1024]; /* some random amount */ |
665 | 557 Bytecount size_in_bytes = |
428 | 558 Lstream_read (XLSTREAM (instream), tempbuf, sizeof (tempbuf)); |
3462 | 559 if (size_in_bytes <= 0) |
428 | 560 break; |
561 | |
562 /* Process the bytes. */ | |
563 md5_process_bytes (tempbuf, size_in_bytes, &ctx); | |
564 } | |
565 Lstream_delete (XLSTREAM (instream)); | |
566 Lstream_delete (XLSTREAM (raw_instream)); | |
567 UNGCPRO; | |
568 | |
569 md5_finish_ctx (&ctx, digest); | |
570 for (i = 0; i < 16; i++) | |
571 sprintf ((char *) (thehash + (i * 2)), "%02x", digest[i]); | |
572 | |
573 return make_string (thehash, 32); | |
574 } | |
575 | |
576 void | |
577 syms_of_md5 (void) | |
578 { | |
579 DEFSUBR (Fmd5); | |
580 } | |
581 | |
582 void | |
583 vars_of_md5 (void) | |
584 { | |
585 Fprovide (intern ("md5")); | |
586 } | |
587 #endif /* emacs */ |