1 /* $Id: dktrace.c,v 1.6 2005/07/14 22:56:25 ted46045 Exp $ */
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 // added by nhatier for compilation under MSVC
6 #ifdef _MSC_VER
7 #include <string.h>
8   #define strncasecmp strnicmp
9   #define strcasecmp stricmp
10   #define snprintf _snprintf
11 #else
12   #ifndef _STRINGS_H
13     #include <strings.h>
14   #endif
15   #ifndef _STRING_H
16     #include <string.h>
17   #endif
18 #endif
19 // end added by nhatier
20 #include "dktrace.h"
21 
22 //dk_init() is a macro now in dktrace.h
23 
24 static  int *
getPointer(DK_TRACE * dkp,DK_TRACE_TYPE type)25 getPointer(DK_TRACE *dkp, DK_TRACE_TYPE type)
26 {
27   switch (type) {
28   case DKT_RAW_HEADER: return dkp->ccounts_h;
29   case DKT_CANON_HEADER: return dkp->ccounts_H;
30   case DKT_RAW_BODY: return dkp->ccounts_b;
31   case DKT_CANON_BODY: return dkp->ccounts_B;
32   default: return 0;
33   }
34 }
35 
36 //Modified version of dkparselist()
dkt_parselist(char * list,char * letters,char * values[])37 static int dkt_parselist(char *list, char *letters, char *values[])
38 {
39   char key;
40   int i;
41   char *value;
42 
43   /* start with all args unset */
44   for (i = 0; letters[i]; i++)
45   {
46     values[i] = NULL;
47   }
48   key = 0;
49   while (*list)
50   {
51     if ((*list == ' ')||(*list == '\t')||(*list == '\r')||(*list == '\n'))
52     {
53       list++;
54     }
55     else if (*list == '=')
56     {
57       char *ws;
58 
59       ++list;
60       value = list;
61       ws = list;
62       while (1)
63       {
64         /* copy up to null or semicolon, deleting whitespace as we go */
65         *ws = *list;
66         if ((*list == ' ')||(*list == '\t')||(*list == '\r')||(*list == '\n'))
67         {
68           /* ignore */
69         }
70         else if (!*list)
71         {
72           break;
73         }
74         else if (*list == ';')
75         {
76           *ws = '\0';
77           list++;
78           break;
79         }
80         else
81         {
82           ws++;
83         }
84         list++;
85       }
86       if (!key)
87       {
88         return 0; //No key
89       }
90       /* if we find a matching letter, remember the value */
91       for (i = 0; letters[i]; i++)
92       {
93         if (key == letters[i])
94         {
95           if (values[i])
96           {
97             return 0; /* no duplicate keys. TC23 */
98           }
99           values[i] = value;
100         }
101       }
102       key = 0;
103     }
104     else
105     {
106       if (key)
107       {
108         return 0; /* they already gave us a key. TC24 */
109       }
110       key = *list++;
111     }
112   }
113   return 1;
114 }
115 
116 extern  void
dkt_add(DK_TRACE * dkp,DK_TRACE_TYPE type,const unsigned char * data,int dataLength)117 dkt_add(DK_TRACE *dkp, DK_TRACE_TYPE type, const unsigned char *data, int dataLength)
118 {
119   int *ip;
120   ip = getPointer(dkp, type);
121   if (!ip) return;
122 
123   while (dataLength-- > 0) ip[*data++]++;
124 }
125 
126 //useful for building table directly
127 extern  void
dkt_quickadd(DK_TRACE * dkp,DK_TRACE_TYPE type,int index,int count)128 dkt_quickadd(DK_TRACE *dkp, DK_TRACE_TYPE type, int index, int count)
129 {
130   int *ip;
131   ip = getPointer(dkp, type);
132   if (!ip) return;
133   if ((index < 256) && (index >= 0))
134     ip[index] = ip[index] + count;
135 }
136 
137 //reverse of dkt_quickadd, reads data from table and returns the int count
138 extern  int
dkt_getcount(DK_TRACE * dkp,DK_TRACE_TYPE type,int index,int count)139 dkt_getcount(DK_TRACE *dkp, DK_TRACE_TYPE type, int index, int count)
140 {
141   int *ip;
142   ip = getPointer(dkp, type);
143   if (!ip) return 0;
144   if ((index < 256) && (index >= 0))
145     return ip[index];
146   return 0;
147 }
148 
149 
150 /*
151 * Fills in DK_TRACE *diff_table with the differences between
152 * *dka (before) and *dkb (after), (after - before = diff)
153 */
154 extern int
dkt_diff(DK_TRACE * dka,DK_TRACE * dkb,DK_TRACE_TYPE type,DK_TRACE * diff_table)155 dkt_diff(DK_TRACE *dka, DK_TRACE  *dkb, DK_TRACE_TYPE type, DK_TRACE *diff_table)
156 {
157   int *inputa, *inputb, *output;
158   int i;
159   inputa = getPointer(dka,type);
160   if (!inputa)
161     return 0;
162   inputb = getPointer(dkb,type);
163   if (!inputb)
164     return 0;
165   output = getPointer(diff_table,type);
166   if (!output)
167     return 0;
168 
169   for (i = 0; i < 256; i++)
170   {
171     output[i] = (inputb[i] - inputa[i]);
172   }
173   return 1;
174 }
175 
176 /*
177  * Generate the tag=value; data for a particular trace type
178  * returns length of generated C string including ending '\0'
179  */
180 
181 extern  int
dkt_generate(DK_TRACE * dkp,DK_TRACE_TYPE type,char * buffer,int maxBufferSize)182 dkt_generate(DK_TRACE *dkp, DK_TRACE_TYPE type, char* buffer, int maxBufferSize)
183 {
184   int *ip;
185   char  *cp;
186   int ix;
187   int len;
188   int highest;
189 
190   if (maxBufferSize < 20) return 0; /* Getting too close, you lose */
191   cp = buffer;
192   ip = getPointer(dkp, type);
193   if (!ip) return 0;
194   *buffer++ = (char) type; --maxBufferSize;
195   *buffer++ = '='; --maxBufferSize;
196 
197   /* Only produce as many entries as needed, rather than the full 256 */
198 
199   for (ix=0, highest=0; ix < 256; ++ix) {
200     if (ip[ix] != 0) highest = ix;
201   }
202 
203   for (ix=0; ix <= highest; ++ix) {
204     if (ip[ix] != 0) {
205       len = snprintf(buffer, maxBufferSize, "%d", ip[ix]);
206       buffer += len;
207       maxBufferSize -= len;
208     }
209     if (maxBufferSize < 10) return 0; /* Getting too close, you lose */
210     *buffer++ = ':'; --maxBufferSize;
211   }
212 
213 /* Finish up the tag with a semi-colon and turn it into a C string */
214   --buffer;
215   *buffer++ = ';'; //replace last ':'
216   *buffer++ = '\0'; --maxBufferSize;
217   return buffer - cp;
218 }
219 
220 //converts a header to to a DK_TRACE table
dkt_hdrtotrace(char * ptr,DK_TRACE * store)221 extern int dkt_hdrtotrace(char *ptr, DK_TRACE *store)
222 {
223   char *values[4];  // hHbB
224   int idx;
225   int delim_count;
226   char *sptr,*eptr;
227   DK_TRACE_TYPE dk_trace_tag[4] =
228   {
229     DKT_RAW_HEADER,
230     DKT_CANON_HEADER,
231     DKT_RAW_BODY,
232     DKT_CANON_BODY
233   };
234   int *ip;
235 
236   if ((strncasecmp(ptr, "DomainKey-Trace:", 16)) || !store || (!dkt_parselist(ptr + 16,"hHbB", values)))
237   {
238     return 0;
239   }
240   for (idx = 0; idx < 4; idx++)
241   {
242     if (!values[idx])
243       continue;
244     ip = getPointer(store, dk_trace_tag[idx]);
245     if (!ip) return 0;
246     sptr = values[idx];
247     for (delim_count = 0; ((delim_count < 256) && (*sptr != '\0')); sptr++)
248     {
249       if (*sptr == ':')
250       {
251         delim_count++;
252         continue;
253       }
254       //find the end of the int
255       for (eptr = sptr + 1; ((*eptr != ':')&&(*eptr != '\0')); eptr++);
256       if (*eptr == '\0') //if end of values for key finish up
257       {
258         ip[delim_count] = atoi(sptr);
259         break;
260       }
261       *eptr = '\0';
262       ip[delim_count] = atoi(sptr);
263       delim_count++;
264       sptr = eptr;
265     }
266   }
267   return 1;
268 }
269