]> code.citadel.org Git - citadel.git/blob - citadel/tools.c
* Another minor stoopid little time display fix
[citadel.git] / citadel / tools.c
1 /*
2  * tools.c -- Miscellaneous routines used by both the client and server.
3  * $Id$
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <ctype.h>
9 #include <string.h>
10 #include <sys/time.h>
11 #include "tools.h"
12
13 #define TRUE  1
14 #define FALSE 0
15
16 typedef unsigned char byte;           /* Byte type */
17 static byte dtable[256];              /* base64 encode / decode table */
18
19
20 char *safestrncpy(char *dest, const char *src, size_t n)
21 {
22   if (dest == NULL || src == NULL)
23     {
24       fprintf(stderr, "safestrncpy: NULL argument\n");
25       abort();
26     }
27   strncpy(dest, src, n);
28   dest[n - 1] = 0;
29   return dest;
30 }
31
32
33 /*
34  * num_tokens()  -  discover number of parameters/tokens in a string
35  */
36 int num_tokens(char *source, char tok) {
37         int a;
38         int count = 1;
39
40         for (a=0; a<strlen(source); ++a) {
41                 if (source[a]==tok) ++count;
42         }
43         return(count);
44 }
45
46 /*
47  * extract_token()  -  a smarter string tokenizer
48  */
49 void extract_token(char *dest, char *source, int parmnum, char separator) 
50 {
51         int i;
52         int len;
53         int curr_parm;
54
55         strcpy(dest,"");
56         len = 0;
57         curr_parm = 0;
58
59         if (strlen(source)==0) {
60                 return;
61                 }
62
63         for (i=0; i<strlen(source); ++i) {
64                 if (source[i]==separator) {
65                         ++curr_parm;
66                 }
67                 else if (curr_parm == parmnum) {
68                         dest[len+1] = 0;
69                         dest[len++] = source[i];
70                 }
71         }
72 }
73
74
75
76 /*
77  * remove_token()  -  a tokenizer that kills, maims, and destroys
78  */
79 void remove_token(char *source, int parmnum, char separator)
80 {
81         int i;
82         int len;
83         int curr_parm;
84         int start, end;
85
86         len = 0;
87         curr_parm = 0;
88         start = (-1);
89         end = (-1);
90
91         if (strlen(source)==0) {
92                 return;
93                 }
94
95         for (i=0; i<strlen(source); ++i) {
96                 if ( (start < 0) && (curr_parm == parmnum) ) {
97                         start = i;
98                 }
99
100                 if ( (end < 0) && (curr_parm == (parmnum+1)) ) {
101                         end = i;
102                 }
103
104                 if (source[i]==separator) {
105                         ++curr_parm;
106                 }
107         }
108
109         if (end < 0) end = strlen(source);
110
111         printf("%d .. %d\n", start, end);
112
113         strcpy(&source[start], &source[end]);
114 }
115
116
117
118
119 /*
120  * extract_int()  -  extract an int parm w/o supplying a buffer
121  */
122 int extract_int(char *source, int parmnum)
123 {
124         char buf[256];
125         
126         extract_token(buf, source, parmnum, '|');
127         return(atoi(buf));
128 }
129
130 /*
131  * extract_long()  -  extract an long parm w/o supplying a buffer
132  */
133 long extract_long(char *source, long int parmnum)
134 {
135         char buf[256];
136         
137         extract_token(buf, source, parmnum, '|');
138         return(atol(buf));
139 }
140
141
142
143 /*
144  * decode_base64() and encode_base64() are adaptations of code by
145  * John Walker, found in full in the file "base64.c" included with this
146  * distribution.  The difference between those functions and these is that
147  * these are intended to encode/decode small string buffers, and those are
148  * intended to encode/decode entire MIME parts.
149  */
150
151 void encode_base64(char *dest, char *source)
152 {
153     int i, hiteof = FALSE;
154     int spos = 0;
155     int dpos = 0;
156
157     /*  Fill dtable with character encodings.  */
158
159     for (i = 0; i < 26; i++) {
160         dtable[i] = 'A' + i;
161         dtable[26 + i] = 'a' + i;
162     }
163     for (i = 0; i < 10; i++) {
164         dtable[52 + i] = '0' + i;
165     }
166     dtable[62] = '+';
167     dtable[63] = '/';
168
169     while (!hiteof) {
170         byte igroup[3], ogroup[4];
171         int c, n;
172
173         igroup[0] = igroup[1] = igroup[2] = 0;
174         for (n = 0; n < 3; n++) {
175             c = source[spos++];
176             if (c == 0) {
177                 hiteof = TRUE;
178                 break;
179             }
180             igroup[n] = (byte) c;
181         }
182         if (n > 0) {
183             ogroup[0] = dtable[igroup[0] >> 2];
184             ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
185             ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
186             ogroup[3] = dtable[igroup[2] & 0x3F];
187
188             /* Replace characters in output stream with "=" pad
189                characters if fewer than three characters were
190                read from the end of the input stream. */
191
192             if (n < 3) {
193                 ogroup[3] = '=';
194                 if (n < 2) {
195                     ogroup[2] = '=';
196                 }
197             }
198             for (i = 0; i < 4; i++) {
199                 dest[dpos++] = ogroup[i];
200                 dest[dpos] = 0;
201             }
202         }
203     }
204 }
205
206
207
208 void decode_base64(char *dest, char *source)
209 {
210     int i;
211     int dpos = 0;
212     int spos = 0;
213
214     for (i = 0; i < 255; i++) {
215         dtable[i] = 0x80;
216     }
217     for (i = 'A'; i <= 'Z'; i++) {
218         dtable[i] = 0 + (i - 'A');
219     }
220     for (i = 'a'; i <= 'z'; i++) {
221         dtable[i] = 26 + (i - 'a');
222     }
223     for (i = '0'; i <= '9'; i++) {
224         dtable[i] = 52 + (i - '0');
225     }
226     dtable['+'] = 62;
227     dtable['/'] = 63;
228     dtable['='] = 0;
229
230     /*CONSTANTCONDITION*/
231     while (TRUE) {
232         byte a[4], b[4], o[3];
233
234         for (i = 0; i < 4; i++) {
235             int c = source[spos++];
236
237             if (c == 0) {
238                 if (i > 0) {
239                     return;
240                 }
241                 return;
242             }
243             if (dtable[c] & 0x80) {
244                 /* Ignoring errors: discard invalid character. */
245                 i--;
246                 continue;
247             }
248             a[i] = (byte) c;
249             b[i] = (byte) dtable[c];
250         }
251         o[0] = (b[0] << 2) | (b[1] >> 4);
252         o[1] = (b[1] << 4) | (b[2] >> 2);
253         o[2] = (b[2] << 6) | b[3];
254         i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
255         if (i>=1) dest[dpos++] = o[0];
256         if (i>=2) dest[dpos++] = o[1];
257         if (i>=3) dest[dpos++] = o[2];
258         dest[dpos] = 0;
259         if (i < 3) {
260             return;
261         }
262     }
263 }
264
265
266
267 /*
268  * Strip leading and trailing spaces from a string
269  */
270 void striplt(char *buf)
271 {
272         while ((strlen(buf) > 0) && (buf[0] == 32))
273                 strcpy(buf, &buf[1]);
274         while (buf[strlen(buf) - 1] == 32)
275                 buf[strlen(buf) - 1] = 0;
276 }
277
278
279
280
281
282 /* 
283  * Return the number of occurances of character ch in string st
284  */ 
285 int haschar(char *st, int ch)
286 {
287         int a, b;
288         b = 0;
289         for (a = 0; a < strlen(st); ++a)
290                 if (st[a] == ch)
291                         ++b;
292         return (b);
293 }
294
295
296
297
298 /*
299  * Compare two strings, insensitive to case, punctuation, and non-alnum chars
300  */
301 int collapsed_strcmp(char *s1, char *s2) {
302         char *c1, *c2;
303         int i, ret, pos;
304
305         c1 = malloc(strlen(s1)+1);
306         c2 = malloc(strlen(s2)+1);
307         c1[0] = 0;
308         c2[0] = 0;
309
310         pos = 0;
311         for (i=0; i<strlen(s1); ++i) {
312                 if (isalnum(s1[i])) {
313                         c1[pos] = tolower(s1[i]);
314                         c1[++pos] = 0;
315                 }
316         }
317
318         pos = 0;
319         for (i=0; i<strlen(s2); ++i) {
320                 if (isalnum(s2[i])) {
321                         c2[pos] = tolower(s2[i]);
322                         c2[++pos] = 0;
323                 }
324         }
325
326         ret = strcmp(c1, c2);
327         free(c1);
328         free(c2);
329         return(ret);
330 }
331
332
333
334 /*
335  * Format a date/time stamp for output 
336  */
337 void fmt_date(char *buf, time_t thetime) {
338         struct tm *tm;
339         int hour;
340
341         char *ascmonths[] = {
342                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
343                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
344         };
345
346         strcpy(buf, "");
347         tm = localtime(&thetime);
348
349         hour = tm->tm_hour;
350         if (hour == 0)  hour = 12;
351         else if (hour > 12) hour = hour - 12;
352
353         sprintf(buf, "%s %d %4d %d:%02d%s",
354                 ascmonths[tm->tm_mon],
355                 tm->tm_mday,
356                 tm->tm_year + 1900,
357                 hour,
358                 tm->tm_min,
359                 ( (tm->tm_hour >= 12) ? "pm" : "am" )
360         );
361 }
362
363
364
365
366
367