misc/vim: inform the user when no results are found
[nit.git] / lib / md5.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2011 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Implements the md5 function in C
18 module md5
19
20 in "C Header" `{
21 /*
22 This C code block as a different source:
23
24 Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
25
26 This software is provided 'as-is', without any express or implied
27 warranty. In no event will the authors be held liable for any damages
28 arising from the use of this software.
29
30 Permission is granted to anyone to use this software for any purpose,
31 including commercial applications, and to alter it and redistribute it
32 freely, subject to the following restrictions:
33
34 1. The origin of this software must not be misrepresented; you must not
35 claim that you wrote the original software. If you use this software
36 in a product, an acknowledgment in the product documentation would be
37 appreciated but is not required.
38 2. Altered source versions must be plainly marked as such, and must not be
39 misrepresented as being the original software.
40 3. This notice may not be removed or altered from any source distribution.
41
42 L. Peter Deutsch
43 ghost@aladdin.com
44
45 */
46 /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
47 /*
48 Independent implementation of MD5 (RFC 1321).
49
50 This code implements the MD5 Algorithm defined in RFC 1321, whose
51 text is available at
52 http://www.ietf.org/rfc/rfc1321.txt
53 The code is derived from the text of the RFC, including the test suite
54 (section A.5) but excluding the rest of Appendix A. It does not include
55 any code or documentation that is identified in the RFC as being
56 copyrighted.
57
58 The original and principal author of md5.h is L. Peter Deutsch
59 <ghost@aladdin.com>. Other authors are noted in the change history
60 that follows (in reverse chronological order):
61
62 2002-04-13 lpd Removed support for non-ANSI compilers; removed
63 references to Ghostscript; clarified derivation from RFC 1321;
64 now handles byte order either statically or dynamically.
65 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
66 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
67 added conditionalization for C++ compilation from Martin
68 Purschke <purschke@bnl.gov>.
69 1999-05-03 lpd Original version.
70 */
71
72 /*
73 * This package supports both compile-time and run-time determination of CPU
74 * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
75 * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
76 * defined as non-zero, the code will be compiled to run only on big-endian
77 * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
78 * run on either big- or little-endian CPUs, but will run slightly less
79 * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
80 */
81
82 typedef unsigned char md5_byte_t; /* 8-bit byte */
83 typedef unsigned int md5_word_t; /* 32-bit word */
84
85 /* Define the state of the MD5 Algorithm. */
86 typedef struct md5_state_s {
87 md5_word_t count[2]; /* message length in bits, lsw first */
88 md5_word_t abcd[4]; /* digest buffer */
89 md5_byte_t buf[64]; /* accumulate block */
90 } md5_state_t;
91
92 #ifdef __cplusplus
93 extern "C"
94 {
95 #endif
96
97 /* Initialize the algorithm. */
98 void md5_init(md5_state_t *pms);
99
100 /* Append a string to the message. */
101 void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
102
103 /* Finish the message and return the digest. */
104 void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
105 `}
106
107 `{
108 /*
109 This C code block as a different source:
110
111 Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
112
113 This software is provided 'as-is', without any express or implied
114 warranty. In no event will the authors be held liable for any damages
115 arising from the use of this software.
116
117 Permission is granted to anyone to use this software for any purpose,
118 including commercial applications, and to alter it and redistribute it
119 freely, subject to the following restrictions:
120
121 1. The origin of this software must not be misrepresented; you must not
122 claim that you wrote the original software. If you use this software
123 in a product, an acknowledgment in the product documentation would be
124 appreciated but is not required.
125 2. Altered source versions must be plainly marked as such, and must not be
126 misrepresented as being the original software.
127 3. This notice may not be removed or altered from any source distribution.
128
129 L. Peter Deutsch
130 ghost@aladdin.com
131
132 */
133 /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
134 /*
135 Independent implementation of MD5 (RFC 1321).
136
137 This code implements the MD5 Algorithm defined in RFC 1321, whose
138 text is available at
139 http://www.ietf.org/rfc/rfc1321.txt
140 The code is derived from the text of the RFC, including the test suite
141 (section A.5) but excluding the rest of Appendix A. It does not include
142 any code or documentation that is identified in the RFC as being
143 copyrighted.
144
145 The original and principal author of md5.c is L. Peter Deutsch
146 <ghost@aladdin.com>. Other authors are noted in the change history
147 that follows (in reverse chronological order):
148
149 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
150 either statically or dynamically; added missing #include <string.h>
151 in library.
152 2002-03-11 lpd Corrected argument list for main(), and added int return
153 type, in test program and T value program.
154 2002-02-21 lpd Added missing #include <stdio.h> in test program.
155 2000-07-03 lpd Patched to eliminate warnings about "constant is
156 unsigned in ANSI C, signed in traditional"; made test program
157 self-checking.
158 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
159 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
160 1999-05-03 lpd Original version.
161 */
162
163 #include <string.h>
164
165 #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
166 #ifdef ARCH_IS_BIG_ENDIAN
167 # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1: -1)
168 #else
169 # define BYTE_ORDER 0
170 #endif
171
172 #define T_MASK ((md5_word_t)~0)
173 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
174 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
175 #define T3 0x242070db
176 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
177 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
178 #define T6 0x4787c62a
179 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
180 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
181 #define T9 0x698098d8
182 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
183 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
184 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
185 #define T13 0x6b901122
186 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
187 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
188 #define T16 0x49b40821
189 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
190 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
191 #define T19 0x265e5a51
192 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
193 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
194 #define T22 0x02441453
195 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
196 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
197 #define T25 0x21e1cde6
198 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
199 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
200 #define T28 0x455a14ed
201 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
202 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
203 #define T31 0x676f02d9
204 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
205 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
206 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
207 #define T35 0x6d9d6122
208 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
209 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
210 #define T38 0x4bdecfa9
211 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
212 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
213 #define T41 0x289b7ec6
214 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
215 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
216 #define T44 0x04881d05
217 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
218 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
219 #define T47 0x1fa27cf8
220 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
221 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
222 #define T50 0x432aff97
223 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
224 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
225 #define T53 0x655b59c3
226 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
227 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
228 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
229 #define T57 0x6fa87e4f
230 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
231 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
232 #define T60 0x4e0811a1
233 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
234 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
235 #define T63 0x2ad7d2bb
236 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
237
238
239 static void
240 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
241 {
242 md5_word_t
243 a = pms->abcd[0], b = pms->abcd[1],
244 c = pms->abcd[2], d = pms->abcd[3];
245 md5_word_t t;
246 #if BYTE_ORDER > 0
247 /* Define storage only for big-endian CPUs. */
248 md5_word_t X[16];
249 #else
250 /* Define storage for little-endian or both types of CPUs. */
251 md5_word_t xbuf[16];
252 const md5_word_t *X;
253 #endif
254
255 {
256 #if BYTE_ORDER == 0
257 /*
258 * Determine dynamically whether this is a big-endian or
259 * little-endian machine, since we can use a more efficient
260 * algorithm on the latter.
261 */
262 static const int w = 1;
263
264 if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
265 #endif
266 #if BYTE_ORDER <= 0 /* little-endian */
267 {
268 /*
269 * On little-endian machines, we can process properly aligned
270 * data without copying it.
271 */
272 if (!((data - (const md5_byte_t *)0) & 3)) {
273 /* data are properly aligned */
274 X = (const md5_word_t *)data;
275 } else {
276 /* not aligned */
277 memcpy(xbuf, data, 64);
278 X = xbuf;
279 }
280 }
281 #endif
282 #if BYTE_ORDER == 0
283 else /* dynamic big-endian */
284 #endif
285 #if BYTE_ORDER >= 0 /* big-endian */
286 {
287 /*
288 * On big-endian machines, we must arrange the bytes in the
289 * right order.
290 */
291 const md5_byte_t *xp = data;
292 int i;
293
294 # if BYTE_ORDER == 0
295 X = xbuf; /* (dynamic only) */
296 # else
297 # define xbuf X /* (static only) */
298 # endif
299 for (i = 0; i < 16; ++i, xp += 4)
300 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
301 }
302 #endif
303 }
304
305 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
306
307 /* Round 1. */
308 /* Let [abcd k s i] denote the operation
309 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
310 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
311 #define SET(a, b, c, d, k, s, Ti)\
312 t = a + F(b,c,d) + X[k] + Ti;\
313 a = ROTATE_LEFT(t, s) + b
314 /* Do the following 16 operations. */
315 SET(a, b, c, d, 0, 7, T1);
316 SET(d, a, b, c, 1, 12, T2);
317 SET(c, d, a, b, 2, 17, T3);
318 SET(b, c, d, a, 3, 22, T4);
319 SET(a, b, c, d, 4, 7, T5);
320 SET(d, a, b, c, 5, 12, T6);
321 SET(c, d, a, b, 6, 17, T7);
322 SET(b, c, d, a, 7, 22, T8);
323 SET(a, b, c, d, 8, 7, T9);
324 SET(d, a, b, c, 9, 12, T10);
325 SET(c, d, a, b, 10, 17, T11);
326 SET(b, c, d, a, 11, 22, T12);
327 SET(a, b, c, d, 12, 7, T13);
328 SET(d, a, b, c, 13, 12, T14);
329 SET(c, d, a, b, 14, 17, T15);
330 SET(b, c, d, a, 15, 22, T16);
331 #undef SET
332
333 /* Round 2. */
334 /* Let [abcd k s i] denote the operation
335 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
336 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
337 #define SET(a, b, c, d, k, s, Ti)\
338 t = a + G(b,c,d) + X[k] + Ti;\
339 a = ROTATE_LEFT(t, s) + b
340 /* Do the following 16 operations. */
341 SET(a, b, c, d, 1, 5, T17);
342 SET(d, a, b, c, 6, 9, T18);
343 SET(c, d, a, b, 11, 14, T19);
344 SET(b, c, d, a, 0, 20, T20);
345 SET(a, b, c, d, 5, 5, T21);
346 SET(d, a, b, c, 10, 9, T22);
347 SET(c, d, a, b, 15, 14, T23);
348 SET(b, c, d, a, 4, 20, T24);
349 SET(a, b, c, d, 9, 5, T25);
350 SET(d, a, b, c, 14, 9, T26);
351 SET(c, d, a, b, 3, 14, T27);
352 SET(b, c, d, a, 8, 20, T28);
353 SET(a, b, c, d, 13, 5, T29);
354 SET(d, a, b, c, 2, 9, T30);
355 SET(c, d, a, b, 7, 14, T31);
356 SET(b, c, d, a, 12, 20, T32);
357 #undef SET
358
359 /* Round 3. */
360 /* Let [abcd k s t] denote the operation
361 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
362 #define H(x, y, z) ((x) ^ (y) ^ (z))
363 #define SET(a, b, c, d, k, s, Ti)\
364 t = a + H(b,c,d) + X[k] + Ti;\
365 a = ROTATE_LEFT(t, s) + b
366 /* Do the following 16 operations. */
367 SET(a, b, c, d, 5, 4, T33);
368 SET(d, a, b, c, 8, 11, T34);
369 SET(c, d, a, b, 11, 16, T35);
370 SET(b, c, d, a, 14, 23, T36);
371 SET(a, b, c, d, 1, 4, T37);
372 SET(d, a, b, c, 4, 11, T38);
373 SET(c, d, a, b, 7, 16, T39);
374 SET(b, c, d, a, 10, 23, T40);
375 SET(a, b, c, d, 13, 4, T41);
376 SET(d, a, b, c, 0, 11, T42);
377 SET(c, d, a, b, 3, 16, T43);
378 SET(b, c, d, a, 6, 23, T44);
379 SET(a, b, c, d, 9, 4, T45);
380 SET(d, a, b, c, 12, 11, T46);
381 SET(c, d, a, b, 15, 16, T47);
382 SET(b, c, d, a, 2, 23, T48);
383 #undef SET
384
385 /* Round 4. */
386 /* Let [abcd k s t] denote the operation
387 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
388 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
389 #define SET(a, b, c, d, k, s, Ti)\
390 t = a + I(b,c,d) + X[k] + Ti;\
391 a = ROTATE_LEFT(t, s) + b
392 /* Do the following 16 operations. */
393 SET(a, b, c, d, 0, 6, T49);
394 SET(d, a, b, c, 7, 10, T50);
395 SET(c, d, a, b, 14, 15, T51);
396 SET(b, c, d, a, 5, 21, T52);
397 SET(a, b, c, d, 12, 6, T53);
398 SET(d, a, b, c, 3, 10, T54);
399 SET(c, d, a, b, 10, 15, T55);
400 SET(b, c, d, a, 1, 21, T56);
401 SET(a, b, c, d, 8, 6, T57);
402 SET(d, a, b, c, 15, 10, T58);
403 SET(c, d, a, b, 6, 15, T59);
404 SET(b, c, d, a, 13, 21, T60);
405 SET(a, b, c, d, 4, 6, T61);
406 SET(d, a, b, c, 11, 10, T62);
407 SET(c, d, a, b, 2, 15, T63);
408 SET(b, c, d, a, 9, 21, T64);
409 #undef SET
410
411 /* Then perform the following additions. (That is increment each
412 of the four registers by the value it had before this block
413 was started.) */
414 pms->abcd[0] += a;
415 pms->abcd[1] += b;
416 pms->abcd[2] += c;
417 pms->abcd[3] += d;
418 }
419
420 void
421 md5_init(md5_state_t *pms)
422 {
423 pms->count[0] = pms->count[1] = 0;
424 pms->abcd[0] = 0x67452301;
425 pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
426 pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
427 pms->abcd[3] = 0x10325476;
428 }
429
430 void
431 md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
432 {
433 const md5_byte_t *p = data;
434 int left = nbytes;
435 int offset = (pms->count[0] >> 3) & 63;
436 md5_word_t nbits = (md5_word_t)(nbytes << 3);
437
438 if (nbytes <= 0)
439 return;
440
441 /* Update the message length. */
442 pms->count[1] += nbytes >> 29;
443 pms->count[0] += nbits;
444 if (pms->count[0] < nbits)
445 pms->count[1]++;
446
447 /* Process an initial partial block. */
448 if (offset) {
449 int copy = (offset + nbytes > 64 ? 64 - offset: nbytes);
450
451 memcpy(pms->buf + offset, p, copy);
452 if (offset + copy < 64)
453 return;
454 p += copy;
455 left -= copy;
456 md5_process(pms, pms->buf);
457 }
458
459 /* Process full blocks. */
460 for (; left >= 64; p += 64, left -= 64)
461 md5_process(pms, p);
462
463 /* Process a final partial block. */
464 if (left)
465 memcpy(pms->buf, p, left);
466 }
467
468 void
469 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
470 {
471 static const md5_byte_t pad[64] = {
472 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
473 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
474 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
475 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
476 };
477 md5_byte_t data[8];
478 int i;
479
480 /* Save the length before padding. */
481 for (i = 0; i < 8; ++i)
482 data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
483 /* Pad to 56 bytes mod 64. */
484 md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
485 /* Append the length. */
486 md5_append(pms, data, 8);
487 for (i = 0; i < 16; ++i)
488 digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
489 }
490 `}
491
492 redef class String
493 # returns the md5 digest of the receiver string
494 # algorithm implemented by L. Peter Deutsch <ghost@aladdin.com>
495 fun md5: String import String.to_cstring, NativeString.to_s `{
496 md5_state_t state;
497 md5_byte_t digest[16]; /* result */
498 char *hex_output = malloc(33*sizeof(char));
499 int di;
500 char *in_text;
501
502 in_text = String_to_cstring(recv);
503
504 md5_init(&state);
505 md5_append(&state, (const md5_byte_t *)in_text, strlen(in_text));
506 md5_finish(&state, digest);
507
508 for (di = 0; di < 16; ++di)
509 sprintf(hex_output + di * 2, "%02x", digest[di]);
510 hex_output[32] = '\0';
511
512 return NativeString_to_s(hex_output);
513 `}
514 end