chiark / gitweb /
Debianization and various other fixes.
[ezmlm] / makehash.c
1 /*Id:$*/
2 /*Name:$*/
3
4 #include "stralloc.h"
5 #include "surf.h"
6 #include "uint32.h"
7 #include "makehash.h"
8
9 typedef struct {
10   uint32 seed[32];
11   uint32 sum[8];
12   uint32 out[8];
13   uint32 in[12];
14   int todo;
15 } surfpcs;
16
17 #define SURFPCS_LEN 32
18
19 static void surfpcs_init(s,k)
20 surfpcs *s;
21 uint32 k[32];
22 {
23   int i;
24   for (i = 0;i < 32;++i) s->seed[i] = k[i];
25   for (i = 0;i < 8;++i) s->sum[i] = 0;
26   for (i = 0;i < 12;++i) s->in[i] = 0;
27   s->todo = 0;
28 }
29
30 static uint32 littleendian[8] = {
31   50462976, 117835012, 185207048, 252579084,
32   319951120, 387323156, 454695192, 522067228
33 } ;
34 #define end ((unsigned char *) littleendian)
35
36 #define data ((unsigned char *) s->in)
37 #define outdata ((unsigned char *) s->out)
38
39 static void surfpcs_addlc(s,x,n)
40         /* modified from Dan's surfpcs_add by skipping ' ' & '\t' and */
41         /* case-independence */
42 surfpcs *s;
43 unsigned char *x;
44 unsigned int n;
45 {
46   register unsigned char ch;
47   int i;
48   while (n--) {
49     ch = *x++;
50     if (ch == ' ' || ch == '\t') continue;
51     if (ch >= 'A' && ch <= 'Z')
52       data[end[s->todo++]] = ch - 'A' + 'a';
53     else
54       data[end[s->todo++]] = ch;
55     if (s->todo == 32) {
56       s->todo = 0;
57       if (!++s->in[8])
58         if (!++s->in[9])
59           if (!++s->in[10])
60             ++s->in[11];
61       surf(s->out,s->in,s->seed);
62       for (i = 0;i < 8;++i)
63         s->sum[i] += s->out[i];
64     }
65   }
66 }
67
68 static void surfpcs_out(s,h)
69 surfpcs *s;
70 unsigned char h[32];
71 {
72   int i;
73   surfpcs_addlc(s,".",1);
74   while (s->todo) surfpcs_addlc(s,"",1);
75   for (i = 0;i < 8;++i) s->in[i] = s->sum[i];
76   for (;i < 12;++i) s->in[i] = 0;
77   surf(s->out,s->in,s->seed);
78   for (i = 0;i < 32;++i) h[i] = outdata[end[i]];
79 }
80
81 void makehash(indata,inlen,hash)
82 char *indata;
83 unsigned int inlen;
84 char *hash;
85         /* makes hash[COOKIE=20] from stralloc *indata, ignoring case and */
86         /* SPACE/TAB */
87 {
88   unsigned char h[32];
89   surfpcs s;
90   uint32 seed[32];
91   int i;
92
93   for (i = 0;i < 32;++i) seed[i] = 0;
94   surfpcs_init(&s,seed);
95   surfpcs_addlc(&s,indata,inlen);
96   surfpcs_out(&s,h);
97   for (i = 0;i < 20;++i)
98     hash[i] = 'a' + (h[i] & 15);
99 }
100
101 static stralloc dummy = {0};
102
103 void mkauthhash(s,len,h)
104 char *s; unsigned int len; char *h;
105 /* This is a string that should be the same for all messages from a given   */
106 /* author. Doesn't have to be the real rfc822 address. We look for a '@'    */
107 /* and grab everything up to the next '>', ' ', or ';'. We go back the same */
108 /* way, then take everything up to the '@' or the first '-'. The latter     */
109 /* avoids problems with posters that band their addresses.                  */
110 {
111   unsigned int i,j,k,l;
112   register char ch;
113
114   j = k = l = 0;
115   i = byte_rchr(s,len,'@');
116   if (i < len) {                /* if not then i=sa->len, j=k=l=0 */
117     j = i;
118     while (++j < len) {         /* if not found, then j=sa->len */
119       ch = s[j];
120       if (ch == '>' || ch == ' ' || ch == ';') break;
121     }
122     k = i;
123     while (k > 0) {             /* k <= i */
124       ch = s[--k];
125       if (ch == '<' || ch == ' ' || ch == ';') break;
126     }
127     l = k;                      /* k <= l <= i; */
128     while (l < i && s[l] != '-') ++l;
129     if (!stralloc_copyb(&dummy,s + k, l - k)) die_nomem();
130     if (!stralloc_catb(&dummy,s + i, j - i)) die_nomem();
131     makehash(dummy.s,dummy.len,h);
132   } else                        /* use entire line if no '@' found */
133     makehash(s,len,h);
134 }
135
136