|
|
1 # ifndef FUNCDEF
2 # define INCLUDE_CTYPE
3 # include "kfun.h"
4 # include "parse.h"
5 # endif
6
7
8 # ifdef FUNCDEF
9 FUNCDEF("crypt", kf_crypt, pt_crypt)
10 # else
11 char pt_crypt[] = { C_TYPECHECKED | C_STATIC | C_KFUN_VARARGS, T_STRING, 2,
12 T_STRING | T_VARARGS, T_STRING };
13
14 /*
15 * NAME: kfun->crypt()
16 * DESCRIPTION: encrypt a string
17 */
18 int kf_crypt(f, nargs)
19 register frame *f;
20 int nargs;
21 {
22 static char salts[] =
23 "0123456789./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
24 char salt[3], *p;
25
26 if (nargs == 2 && f->sp->u.string->len >= 2) {
27 /* fixed salt */
28 salt[0] = f->sp->u.string->text[0];
29 salt[1] = f->sp->u.string->text[1];
30 } else {
31 /* random salt */
32 salt[0] = salts[P_random() % 64];
33 salt[1] = salts[P_random() % 64];
34 }
35 salt[2] = '\0';
36 if (nargs == 2) {
37 str_del((f->sp++)->u.string);
38 }
39
40 i_add_ticks(f, 400);
41 p = P_crypt(f->sp->u.string->text, salt);
42 str_del(f->sp->u.string);
43 PUT_STR(f->sp, str_new(p, (long) strlen(p)));
44 return 0;
45 }
46 # endif
47
48
49 # ifdef FUNCDEF
50 FUNCDEF("ctime", kf_ctime, pt_ctime)
51 # else
52 char pt_ctime[] = { C_TYPECHECKED | C_STATIC, T_STRING, 1, T_INT };
53
54 /*
55 * NAME: kfun->ctime()
56 * DESCRIPTION: convert a time value to a string
57 */
58 int kf_ctime(f)
59 frame *f;
60 {
61 char buf[26];
62
63 i_add_ticks(f, 5);
64 P_ctime(buf, f->sp->u.number);
65 PUT_STRVAL(f->sp, str_new(buf, 24L));
66
67 return 0;
68 }
69 # endif
70
71
72 # ifdef FUNCDEF
73 FUNCDEF("explode", kf_explode, pt_explode)
74 # else
75 char pt_explode[] = { C_TYPECHECKED | C_STATIC, T_STRING | (1 << REFSHIFT), 2,
76 T_STRING, T_STRING };
77
78 /*
79 * NAME: kfun->explode()
80 * DESCRIPTION: explode a string
81 */
82 int kf_explode(f)
83 register frame *f;
84 {
85 register unsigned int len, slen, size;
86 register char *p, *s;
87 register value *v;
88 array *a;
89
90 p = f->sp[1].u.string->text;
91 len = f->sp[1].u.string->len;
92 s = f->sp->u.string->text;
93 slen = f->sp->u.string->len;
94
95 if (len == 0) {
96 /*
97 * exploding "" always gives an empty array
98 */
99 a = arr_new(f->data, 0L);
100 } else if (slen == 0) {
101 /*
102 * the sepatator is ""; split string into single characters
103 */
104 a = arr_new(f->data, (long) len);
105 for (v = a->elts; len > 0; v++, --len) {
106 PUT_STRVAL(v, str_new(p, 1L));
107 p++;
108 }
109 } else {
110 /*
111 * split up the string with the separator
112 */
113 size = 1;
114 if (len >= slen && memcmp(p, s, slen) == 0) {
115 /* skip leading separator */
116 p += slen;
117 len -= slen;
118 }
119 while (len > slen) {
120 if (memcmp(p, s, slen) == 0) {
121 /* separator found */
122 p += slen;
123 len -= slen;
124 size++;
125 } else {
126 /* next char */
127 p++;
128 --len;
129 }
130 }
131
132 a = arr_new(f->data, (long) size);
133 v = a->elts;
134
135 p = f->sp[1].u.string->text;
136 len = f->sp[1].u.string->len;
137 size = 0;
138 if (len > slen && memcmp(p, s, slen) == 0) {
139 /* skip leading separator */
140 p += slen;
141 len -= slen;
142 }
143 while (len > slen) {
144 if (memcmp(p, s, slen) == 0) {
145 /* separator found */
146 PUT_STRVAL(v, str_new(p - size, (long) size));
147 v++;
148 p += slen;
149 len -= slen;
150 size = 0;
151 } else {
152 /* next char */
153 p++;
154 --len;
155 size++;
156 }
157 }
158 if (len != slen || memcmp(p, s, slen) != 0) {
159 /* remainder isn't a sepatator */
160 size += len;
161 p += len;
162 }
163 /* final array element */
164 PUT_STRVAL(v, str_new(p - size, (long) size));
165 }
166
167 str_del((f->sp++)->u.string);
168 str_del(f->sp->u.string);
169 PUT_ARRVAL(f->sp, a);
170 i_add_ticks(f, (Int) 2 * a->size);
171
172 return 0;
173 }
174 # endif
175
176
177 # ifdef FUNCDEF
178 FUNCDEF("implode", kf_implode, pt_implode)
179 # else
180 char pt_implode[] = { C_TYPECHECKED | C_STATIC, T_STRING, 2,
181 T_STRING | (1 << REFSHIFT), T_STRING };
182
183 /*
184 * NAME: kfun->implode()
185 * DESCRIPTION: implode an array
186 */
187 int kf_implode(f)
188 register frame *f;
189 {
190 register long len;
191 register unsigned int i, slen;
192 register char *p, *s;
193 register value *v;
194 string *str;
195
196 s = f->sp->u.string->text;
197 slen = f->sp->u.string->len;
198
199 /* first, determine the size of the imploded string */
200 i = f->sp[1].u.array->size;
201 i_add_ticks(f, i);
202 if (i != 0) {
203 len = (i - 1) * (long) slen; /* size of all separators */
204 for (v = d_get_elts(f->sp[1].u.array); i > 0; v++, --i) {
205 if (v->type != T_STRING) {
206 /* not a (string *) */
207 return 1;
208 }
209 len += v->u.string->len;
210 }
211 str = str_new((char *) NULL, len);
212
213 /* create the imploded string */
214 p = str->text;
215 for (i = f->sp[1].u.array->size, v -= i; i > 1; --i, v++) {
216 /* copy array part */
217 memcpy(p, v->u.string->text, v->u.string->len);
218 p += v->u.string->len;
219 /* copy separator */
220 memcpy(p, s, slen);
221 p += slen;
222 }
223 /* copy final array part */
224 memcpy(p, v->u.string->text, v->u.string->len);
225 } else {
226 /* zero size array gives zero size string */
227 str = str_new((char *) NULL, 0L);
228 }
229
230 str_del((f->sp++)->u.string);
231 arr_del(f->sp->u.array);
232 PUT_STRVAL(f->sp, str);
233 return 0;
234 }
235 # endif
236
237
238 # ifdef FUNCDEF
239 FUNCDEF("random", kf_random, pt_random)
240 # else
241 char pt_random[] = { C_TYPECHECKED | C_STATIC, T_INT, 1, T_INT };
242
243 /*
244 * NAME: kfun->random()
245 * DESCRIPTION: return a random number
246 */
247 int kf_random(f)
248 register frame *f;
249 {
250 i_add_ticks(f, 1);
251 PUT_INT(f->sp, (f->sp->u.number > 0) ? P_random() % f->sp->u.number : 0);
252 return 0;
253 }
254 # endif
255
256
257 # ifdef FUNCDEF
258 FUNCDEF("sscanf", kf_sscanf, pt_sscanf)
259 # else
260 char pt_sscanf[] = { C_TYPECHECKED | C_STATIC | C_KFUN_VARARGS, T_INT, 3,
261 T_STRING, T_STRING, T_LVALUE | T_ELLIPSIS };
262
263 /*
264 * NAME: match
265 * DESCRIPTION: match a string possibly including %%, up to the next %[sdfc] or
266 * the end of the string
267 */
268 static bool match(f, s, flenp, slenp)
269 register char *f, *s;
270 unsigned int *flenp, *slenp;
271 {
272 register char *p;
273 register unsigned int flen, slen;
274
275 flen = *flenp;
276 slen = *slenp;
277
278 while (flen > 0) {
279 /* look for first % */
280 p = (char *) memchr(f, '%', flen);
281
282 if (p == (char *) NULL) {
283 /* no remaining % */
284 if (memcmp(f, s, flen) == 0) {
285 *slenp -= slen - flen;
286 return TRUE;
287 } else {
288 return FALSE; /* no match */
289 }
290 }
291
292 if (p[1] == '%') {
293 /* %% */
294 if (memcmp(f, s, ++p - f) == 0) {
295 /* matched up to and including the first % */
296 s += p - f;
297 slen -= p - f;
298 flen -= ++p - f;
299 f = p;
300 } else {
301 return FALSE; /* no match */
302 }
303 } else if (memcmp(f, s, p - f) == 0) {
304 /* matched up to the first % */
305 *flenp -= flen - (p - f);
306 *slenp -= slen - (p - f);
307 return TRUE;
308 } else {
309 return FALSE; /* no match */
310 }
311 }
312
313 *slenp -= slen;
314 return TRUE;
315 }
316
317 /*
318 * NAME: kfun->sscanf()
319 * DESCRIPTION: scan a string
320 */
321 int kf_sscanf(f, nargs)
322 register frame *f;
323 int nargs;
324 {
325 register unsigned int flen, slen, size;
326 register char *format, *x;
327 unsigned int fl, sl;
328 int matches;
329 char *s;
330 Int i;
331 xfloat flt;
332 bool skip;
333
334 if (nargs > MAX_LOCALS + 2) {
335 return 4;
336 }
337 s = f->sp[nargs - 1].u.string->text;
338 slen = f->sp[nargs - 1].u.string->len;
339 nargs -= 2;
340 format = f->sp[nargs].u.string->text;
341 flen = f->sp[nargs].u.string->len;
342 i_reverse(f, nargs);
343
344 i_add_ticks(f, 8 * nargs);
345 matches = 0;
346
347 while (flen > 0) {
348 if (format[0] != '%' || format[1] == '%') {
349 /* match initial part */
350 fl = flen;
351 sl = slen;
352 if (!match(format, s, &fl, &sl) || fl == flen) {
353 goto no_match;
354 }
355 format += fl;
356 flen -= fl;
357 s += sl;
358 slen -= sl;
359 }
360
361 /* skip first % */
362 format++;
363 --flen;
364
365 /*
366 * check for %*
367 */
368 if (*format == '*') {
369 /* no assignment */
370 format++;
371 --flen;
372 skip = TRUE;
373 } else {
374 skip = FALSE;
375 }
376
377 --flen;
378 switch (*format++) {
379 case 's':
380 /* %s */
381 if (format[0] == '%' && format[1] != '%') {
382 switch ((format[1] == '*') ? format[2] : format[1]) {
383 case 'd':
384 /*
385 * %s%d
386 */
387 size = slen;
388 x = s;
389 while (!isdigit(*x)) {
390 if (slen == 0) {
391 goto no_match;
392 }
393 if (x[0] == '-' && isdigit(x[1])) {
394 break;
395 }
396 x++;
397 --slen;
398 }
399 size -= slen;
400 break;
401
402 case 'f':
403 /*
404 * %s%f
405 */
406 size = slen;
407 x = s;
408 while (!isdigit(*x)) {
409 if (slen == 0) {
410 goto no_match;
411 }
412 if ((x[0] == '-' || x[0] == '.') && isdigit(x[1])) {
413 break;
414 }
415 x++;
416 --slen;
417 }
418 size -= slen;
419 break;
420
421 default:
422 error("Bad sscanf format string");
423 }
424 } else {
425 /*
426 * %s followed by non-%
427 */
428 if (flen == 0) {
429 /* match whole string */
430 size = slen;
431 x = s + slen;
432 slen = 0;
433 } else {
434 /* get # of chars to match after string */
435 for (x = format, size = 0; (x - format) != flen;
436 x++, size++) {
437 x = (char *) memchr(x, '%', flen - (x - format));
438 if (x == (char *) NULL) {
439 x = format + flen;
440 break;
441 } else if (x[1] != '%') {
442 break;
443 }
444 }
445 size = (x - format) - size;
446
447 x = s;
448 for (;;) {
449 sl = slen - (x - s);
450 if (sl < size) {
451 goto no_match;
452 }
453 x = (char *) memchr(x, format[0], sl - size + 1);
454 if (x == (char *) NULL) {
455 goto no_match;
456 }
457 fl = flen;
458 if (match(format, x, &fl, &sl)) {
459 format += fl;
460 flen -= fl;
461 size = x - s;
462 x += sl;
463 slen -= size + sl;
464 break;
465 }
466 x++;
467 }
468 }
469 }
470
471 if (!skip) {
472 if (nargs == 0) {
473 error("No lvalue for %%s");
474 }
475 --nargs;
476 PUSH_STRVAL(f, str_new(s, (long) size));
477 i_store(f);
478 f->sp->u.string->ref--;
479 f->sp += 2;
480 }
481 s = x;
482 break;
483
484 case 'd':
485 /* %d */
486 x = s;
487 i = strtol(s, &s, 10);
488 if (s == x) {
489 goto no_match;
490 }
491 slen -= (s - x);
492
493 if (!skip) {
494 if (nargs == 0) {
495 error("No lvalue for %%d");
496 }
497 --nargs;
498 PUSH_INTVAL(f, i);
499 i_store(f);
500 f->sp += 2;
501 }
502 break;
503
504 case 'f':
505 /* %f */
506 x = s;
507 if (!flt_atof(&s, &flt) || s == x) {
508 goto no_match;
509 }
510 slen -= (s - x);
511
512 if (!skip) {
513 if (nargs == 0) {
514 error("No lvalue for %%f");
515 }
516 --nargs;
517 PUSH_FLTVAL(f, flt);
518 i_store(f);
519 f->sp += 2;
520 }
521 break;
522
523 case 'c':
524 /* %c */
525 if (slen == 0) {
526 goto no_match;
527 }
528 if (!skip) {
529 if (nargs == 0) {
530 error("No lvalue for %%c");
531 }
532 --nargs;
533 PUSH_INTVAL(f, UCHAR(*s));
534 i_store(f);
535 f->sp += 2;
536 }
537 s++;
538 --slen;
539 break;
540
541 default:
542 error("Bad sscanf format string");
543 }
544 matches++;
545 }
546
547 no_match:
548 if (nargs > 0) {
549 i_pop(f, nargs); /* pop superfluous arguments */
550 }
551 str_del((f->sp++)->u.string);
552 str_del(f->sp->u.string);
553 PUT_INTVAL(f->sp, matches);
554 return 0;
555 }
556 # endif
557
558
559 # ifdef FUNCDEF
560 FUNCDEF("parse_string", kf_parse_string, pt_parse_string)
561 # else
562 char pt_parse_string[] = { C_TYPECHECKED | C_STATIC | C_KFUN_VARARGS,
563 T_MIXED | (1 << REFSHIFT), 3,
564 T_STRING, T_STRING | T_VARARGS, T_INT };
565
566 /*
567 * NAME: kfun->parse_string()
568 * DESCRIPTION: parse a string
569 */
570 int kf_parse_string(f, nargs)
571 register frame *f;
572 int nargs;
573 {
574 Int maxalt;
575 array *a;
576
577 if (nargs > 2) {
578 maxalt = (f->sp++)->u.number + 1;
579 if (maxalt <= 0) {
580 return 3;
581 }
582 } else {
583 maxalt = 1; /* default: just one valid parse tree */
584 }
585
586 if (OBJR(f->oindex)->flags & O_SPECIAL) {
587 error("parse_string() from special purpose object");
588 }
589
590 a = ps_parse_string(f, f->sp[1].u.string, f->sp->u.string, maxalt);
591 str_del((f->sp++)->u.string);
592 str_del(f->sp->u.string);
593
594 if (a != (array *) NULL) {
595 /* return parse tree */
596 PUT_ARRVAL(f->sp, a);
597 } else {
598 /* parsing failed */
599 *f->sp = nil_value;
600 }
601 return 0;
602 }
603 # endif
604
605
606 # ifdef FUNCDEF
607 FUNCDEF("hash_crc16", kf_hash_crc16, pt_hash_crc16)
608 # else
609 char pt_hash_crc16[] = { C_TYPECHECKED | C_STATIC | C_KFUN_VARARGS, T_INT, 2,
610 T_STRING, T_STRING | T_ELLIPSIS };
611
612 /*
613 * NAME: kfun->hash_crc16()
614 * DESCRIPTION: Compute a 16 bit cyclic redundancy code for a string.
615 * Based on "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS",
616 * by Ross N. Williams.
617 *
618 * Name: "CRC-16/CCITT" (supposedly)
619 * Width: 16
620 * Poly: 1021 (X^16 + X^12 + X^5 + 1)
621 * Init: FFFF
622 * RefIn: False
623 * RefOut: False
624 * XorOut: 0000
625 * Check: 29B1
626 */
627 int kf_hash_crc16(f, nargs)
628 register frame *f;
629 int nargs;
630 {
631 static unsigned short crctab[] = {
632 0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xa550, 0xc660, 0xe770,
633 0x0881, 0x2991, 0x4aa1, 0x6bb1, 0x8cc1, 0xadd1, 0xcee1, 0xeff1,
634 0x3112, 0x1002, 0x7332, 0x5222, 0xb552, 0x9442, 0xf772, 0xd662,
635 0x3993, 0x1883, 0x7bb3, 0x5aa3, 0xbdd3, 0x9cc3, 0xfff3, 0xdee3,
636 0x6224, 0x4334, 0x2004, 0x0114, 0xe664, 0xc774, 0xa444, 0x8554,
637 0x6aa5, 0x4bb5, 0x2885, 0x0995, 0xeee5, 0xcff5, 0xacc5, 0x8dd5,
638 0x5336, 0x7226, 0x1116, 0x3006, 0xd776, 0xf666, 0x9556, 0xb446,
639 0x5bb7, 0x7aa7, 0x1997, 0x3887, 0xdff7, 0xfee7, 0x9dd7, 0xbcc7,
640 0xc448, 0xe558, 0x8668, 0xa778, 0x4008, 0x6118, 0x0228, 0x2338,
641 0xccc9, 0xedd9, 0x8ee9, 0xaff9, 0x4889, 0x6999, 0x0aa9, 0x2bb9,
642 0xf55a, 0xd44a, 0xb77a, 0x966a, 0x711a, 0x500a, 0x333a, 0x122a,
643 0xfddb, 0xdccb, 0xbffb, 0x9eeb, 0x799b, 0x588b, 0x3bbb, 0x1aab,
644 0xa66c, 0x877c, 0xe44c, 0xc55c, 0x222c, 0x033c, 0x600c, 0x411c,
645 0xaeed, 0x8ffd, 0xeccd, 0xcddd, 0x2aad, 0x0bbd, 0x688d, 0x499d,
646 0x977e, 0xb66e, 0xd55e, 0xf44e, 0x133e, 0x322e, 0x511e, 0x700e,
647 0x9fff, 0xbeef, 0xdddf, 0xfccf, 0x1bbf, 0x3aaf, 0x599f, 0x788f,
648 0x8891, 0xa981, 0xcab1, 0xeba1, 0x0cd1, 0x2dc1, 0x4ef1, 0x6fe1,
649 0x8010, 0xa100, 0xc230, 0xe320, 0x0450, 0x2540, 0x4670, 0x6760,
650 0xb983, 0x9893, 0xfba3, 0xdab3, 0x3dc3, 0x1cd3, 0x7fe3, 0x5ef3,
651 0xb102, 0x9012, 0xf322, 0xd232, 0x3542, 0x1452, 0x7762, 0x5672,
652 0xeab5, 0xcba5, 0xa895, 0x8985, 0x6ef5, 0x4fe5, 0x2cd5, 0x0dc5,
653 0xe234, 0xc324, 0xa014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544,
654 0xdba7, 0xfab7, 0x9987, 0xb897, 0x5fe7, 0x7ef7, 0x1dc7, 0x3cd7,
655 0xd326, 0xf236, 0x9106, 0xb016, 0x5766, 0x7676, 0x1546, 0x3456,
656 0x4cd9, 0x6dc9, 0x0ef9, 0x2fe9, 0xc899, 0xe989, 0x8ab9, 0xaba9,
657 0x4458, 0x6548, 0x0678, 0x2768, 0xc018, 0xe108, 0x8238, 0xa328,
658 0x7dcb, 0x5cdb, 0x3feb, 0x1efb, 0xf98b, 0xd89b, 0xbbab, 0x9abb,
659 0x754a, 0x545a, 0x376a, 0x167a, 0xf10a, 0xd01a, 0xb32a, 0x923a,
660 0x2efd, 0x0fed, 0x6cdd, 0x4dcd, 0xaabd, 0x8bad, 0xe89d, 0xc98d,
661 0x267c, 0x076c, 0x645c, 0x454c, 0xa23c, 0x832c, 0xe01c, 0xc10c,
662 0x1fef, 0x3eff, 0x5dcf, 0x7cdf, 0x9baf, 0xbabf, 0xd98f, 0xf89f,
663 0x176e, 0x367e, 0x554e, 0x745e, 0x932e, 0xb23e, 0xd10e, 0xf01e
664 };
665 register unsigned short crc;
666 register int i;
667 register ssizet len;
668 register char *p;
669 register Int cost;
670
671 cost = 0;
672 for (i = nargs; --i >= 0; ) {
673 cost += f->sp[i].u.string->len;
674 }
675 cost = 3 * nargs + (cost >> 2);
676 if (!f->rlim->noticks && f->rlim->ticks <= cost) {
677 f->rlim->ticks = 0;
678 error("Out of ticks");
679 }
680 i_add_ticks(f, cost);
681
682 crc = 0xffff;
683 for (i = nargs; --i >= 0; ) {
684 p = f->sp[i].u.string->text;
685 for (len = f->sp[i].u.string->len; len != 0; --len) {
686 crc = (crc >> 8) ^ crctab[UCHAR(crc ^ *p++)];
687 }
688 str_del(f->sp[i].u.string);
689 }
690 crc = (crc >> 8) + (crc << 8);
691
692 f->sp += nargs - 1;
693 PUT_INTVAL(f->sp, crc);
694 return 0;
695 }
696 # endif
697
698
699 # ifdef FUNCDEF
700 FUNCDEF("hash_md5", kf_hash_md5, pt_hash_md5)
701 # else
702 char pt_hash_md5[] = { C_TYPECHECKED | C_STATIC | C_KFUN_VARARGS, T_STRING, 2,
703 T_STRING, T_STRING | T_ELLIPSIS };
704
705 # define ROTL(x, s) ((x << s) | (x >> (32 - s)))
706 # define R1(a, b, c, d, Mj, s, ti) (a += ((b & c) | (~b & d)) + Mj + ti, \
707 a = b + ROTL(a, s))
708 # define R2(a, b, c, d, Mj, s, ti) (a += ((b & d) | (c & ~d)) + Mj + ti, \
709 a = b + ROTL(a, s))
710 # define R3(a, b, c, d, Mj, s, ti) (a += (b ^ c ^ d) + Mj + ti, \
711 a = b + ROTL(a, s))
712 # define R4(a, b, c, d, Mj, s, ti) (a += (c ^ (b | ~d)) + Mj + ti, \
713 a = b + ROTL(a, s))
714
715 /*
716 * NAME: md5_block()
717 * DESCRIPTION: add another 512 bit block to the message digest
718 */
719 static void md5_block(ABCD, block)
720 Uint *ABCD;
721 register char *block;
722 {
723 Uint M[16];
724 register int i, j;
725 register Uint a, b, c, d;
726
727 for (i = j = 0; i < 16; i++, j += 4) {
728 M[i] = UCHAR(block[j + 0]) | (UCHAR(block[j + 1]) << 8) |
729 (UCHAR(block[j + 2]) << 16) | (UCHAR(block[j + 3]) << 24);
730 }
731
732 a = ABCD[0];
733 b = ABCD[1];
734 c = ABCD[2];
735 d = ABCD[3];
736
737 R1(a, b, c, d, M[ 0], 7, 0xd76aa478);
738 R1(d, a, b, c, M[ 1], 12, 0xe8c7b756);
739 R1(c, d, a, b, M[ 2], 17, 0x242070db);
740 R1(b, c, d, a, M[ 3], 22, 0xc1bdceee);
741 R1(a, b, c, d, M[ 4], 7, 0xf57c0faf);
742 R1(d, a, b, c, M[ 5], 12, 0x4787c62a);
743 R1(c, d, a, b, M[ 6], 17, 0xa8304613);
744 R1(b, c, d, a, M[ 7], 22, 0xfd469501);
745 R1(a, b, c, d, M[ 8], 7, 0x698098d8);
746 R1(d, a, b, c, M[ 9], 12, 0x8b44f7af);
747 R1(c, d, a, b, M[10], 17, 0xffff5bb1);
748 R1(b, c, d, a, M[11], 22, 0x895cd7be);
749 R1(a, b, c, d, M[12], 7, 0x6b901122);
750 R1(d, a, b, c, M[13], 12, 0xfd987193);
751 R1(c, d, a, b, M[14], 17, 0xa679438e);
752 R1(b, c, d, a, M[15], 22, 0x49b40821);
753
754 R2(a, b, c, d, M[ 1], 5, 0xf61e2562);
755 R2(d, a, b, c, M[ 6], 9, 0xc040b340);
756 R2(c, d, a, b, M[11], 14, 0x265e5a51);
757 R2(b, c, d, a, M[ 0], 20, 0xe9b6c7aa);
758 R2(a, b, c, d, M[ 5], 5, 0xd62f105d);
759 R2(d, a, b, c, M[10], 9, 0x02441453);
760 R2(c, d, a, b, M[15], 14, 0xd8a1e681);
761 R2(b, c, d, a, M[ 4], 20, 0xe7d3fbc8);
762 R2(a, b, c, d, M[ 9], 5, 0x21e1cde6);
763 R2(d, a, b, c, M[14], 9, 0xc33707d6);
764 R2(c, d, a, b, M[ 3], 14, 0xf4d50d87);
765 R2(b, c, d, a, M[ 8], 20, 0x455a14ed);
766 R2(a, b, c, d, M[13], 5, 0xa9e3e905);
767 R2(d, a, b, c, M[ 2], 9, 0xfcefa3f8);
768 R2(c, d, a, b, M[ 7], 14, 0x676f02d9);
769 R2(b, c, d, a, M[12], 20, 0x8d2a4c8a);
770
771 R3(a, b, c, d, M[ 5], 4, 0xfffa3942);
772 R3(d, a, b, c, M[ 8], 11, 0x8771f681);
773 R3(c, d, a, b, M[11], 16, 0x6d9d6122);
774 R3(b, c, d, a, M[14], 23, 0xfde5380c);
775 R3(a, b, c, d, M[ 1], 4, 0xa4beea44);
776 R3(d, a, b, c, M[ 4], 11, 0x4bdecfa9);
777 R3(c, d, a, b, M[ 7], 16, 0xf6bb4b60);
778 R3(b, c, d, a, M[10], 23, 0xbebfbc70);
779 R3(a, b, c, d, M[13], 4, 0x289b7ec6);
780 R3(d, a, b, c, M[ 0], 11, 0xeaa127fa);
781 R3(c, d, a, b, M[ 3], 16, 0xd4ef3085);
782 R3(b, c, d, a, M[ 6], 23, 0x04881d05);
783 R3(a, b, c, d, M[ 9], 4, 0xd9d4d039);
784 R3(d, a, b, c, M[12], 11, 0xe6db99e5);
785 R3(c, d, a, b, M[15], 16, 0x1fa27cf8);
786 R3(b, c, d, a, M[ 2], 23, 0xc4ac5665);
787
788 R4(a, b, c, d, M[ 0], 6, 0xf4292244);
789 R4(d, a, b, c, M[ 7], 10, 0x432aff97);
790 R4(c, d, a, b, M[14], 15, 0xab9423a7);
791 R4(b, c, d, a, M[ 5], 21, 0xfc93a039);
792 R4(a, b, c, d, M[12], 6, 0x655b59c3);
793 R4(d, a, b, c, M[ 3], 10, 0x8f0ccc92);
794 R4(c, d, a, b, M[10], 15, 0xffeff47d);
795 R4(b, c, d, a, M[ 1], 21, 0x85845dd1);
796 R4(a, b, c, d, M[ 8], 6, 0x6fa87e4f);
797 R4(d, a, b, c, M[15], 10, 0xfe2ce6e0);
798 R4(c, d, a, b, M[ 6], 15, 0xa3014314);
799 R4(b, c, d, a, M[13], 21, 0x4e0811a1);
800 R4(a, b, c, d, M[ 4], 6, 0xf7537e82);
801 R4(d, a, b, c, M[11], 10, 0xbd3af235);
802 R4(c, d, a, b, M[ 2], 15, 0x2ad7d2bb);
803 R4(b, c, d, a, M[ 9], 21, 0xeb86d391);
804
805 ABCD[0] += a;
806 ABCD[1] += b;
807 ABCD[2] += c;
808 ABCD[3] += d;
809 }
810
811 /*
812 * NAME: kfun->hash_md5()
813 * DESCRIPTION: Compute MD5 message digest. See "Applied Cryptography" by
814 * Bruce Schneier, Second Edition, p. 436-441.
815 */
816 int kf_hash_md5(f, nargs)
817 register frame *f;
818 int nargs;
819 {
820 char buffer[64];
821 Uint cv[4];
822 register int i;
823 register ssizet len;
824 register unsigned short bufsz;
825 register char *p;
826 register Int cost;
827 register Uint length;
828
829 cost = 3 * nargs + 64;
830 for (i = nargs; --i >= 0; ) {
831 cost += f->sp[i].u.string->len;
832 }
833 if (!f->rlim->noticks && f->rlim->ticks <= cost) {
834 f->rlim->ticks = 0;
835 error("Out of ticks");
836 }
837 i_add_ticks(f, cost);
838
839 /*
840 * These constants must apparently be little-endianized, though AC2 does
841 * not explicitly say so.
842 */
843 cv[0] = 0x67452301;
844 cv[1] = 0xefcdab89;
845 cv[2] = 0x98badcfe;
846 cv[3] = 0x10325476;
847 length = 0;
848 bufsz = 0;
849
850 for (i = nargs; --i >= 0; ) {
851 len = f->sp[i].u.string->len;
852 if (len != 0) {
853 length += len;
854 p = f->sp[i].u.string->text;
855 if (bufsz != 0) {
856 register unsigned short size;
857
858 /* fill buffer and digest */
859 size = 64 - bufsz;
860 if (size > len) {
861 size = len;
862 }
863 memcpy(buffer + bufsz, p, size);
864 p += size;
865 len -= size;
866 bufsz += size;
867
868 if (bufsz == 64) {
869 md5_block(cv, buffer);
870 bufsz = 0;
871 }
872 }
873
874 while (len >= 64) {
875 /* digest directly from string */
876 md5_block(cv, p);
877 p += 64;
878 len -= 64;
879 }
880
881 if (len != 0) {
882 /* put remainder in buffer */
883 memcpy(buffer, p, bufsz = len);
884 }
885 }
886 str_del(f->sp[i].u.string);
887 }
888
889 /* append padding and digest final block(s) */
890 buffer[bufsz++] = 0x80;
891 if (bufsz > 56) {
892 memset(buffer + bufsz, '\0', 64 - bufsz);
893 md5_block(cv, buffer);
894 bufsz = 0;
895 }
896 memset(buffer + bufsz, '\0', 64 - bufsz);
897 buffer[56] = length << 3;
898 buffer[57] = length >> 5;
899 buffer[58] = length >> 13;
900 buffer[59] = length >> 21;
901 buffer[60] = length >> 29;
902 md5_block(cv, buffer);
903
904 for (bufsz = i = 0; i < 4; bufsz += 4, i++) {
905 buffer[bufsz + 0] = cv[i];
906 buffer[bufsz + 1] = cv[i] >> 8;
907 buffer[bufsz + 2] = cv[i] >> 16;
908 buffer[bufsz + 3] = cv[i] >> 24;
909 }
910 f->sp += nargs - 1;
911 PUT_STR(f->sp, str_new(buffer, 16L));
912 return 0;
913 }
914 # endif
915
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.