* Split cmd_user() and cmd_pass() into frontend/backend functions
[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 <string.h>
9 #include "tools.h"
10
11 #define TRUE  1
12 #define FALSE 0
13
14 typedef unsigned char byte;           /* Byte type */
15 static byte dtable[256];              /* base64 encode / decode table */
16
17
18 char *safestrncpy(char *dest, const char *src, size_t n)
19 {
20   if (dest == NULL || src == NULL)
21     {
22       fprintf(stderr, "safestrncpy: NULL argument\n");
23       abort();
24     }
25   strncpy(dest, src, n);
26   dest[n - 1] = 0;
27   return dest;
28 }
29
30
31 /*
32  * num_parms()  -  discover number of parameters...
33  */
34 int num_parms(char *source)
35 {
36         int a;
37         int count = 1;
38
39         for (a=0; a<strlen(source); ++a) 
40                 if (source[a]=='|') ++count;
41         return(count);
42 }
43
44 /*
45  * extract()  -  a smarter string tokenizer
46  */
47 void extract_token(char *dest, char *source, int parmnum, char separator)
48 {
49         int i;
50         int len;
51         int curr_parm;
52
53         strcpy(dest,"");
54         len = 0;
55         curr_parm = 0;
56
57         if (strlen(source)==0) {
58                 return;
59                 }
60
61         for (i=0; i<strlen(source); ++i) {
62                 if (source[i]==separator) {
63                         ++curr_parm;
64                 }
65                 else if (curr_parm == parmnum) {
66                         dest[len+1] = 0;
67                         dest[len++] = source[i];
68                 }
69         }
70 }
71
72 /*
73  * extract_int()  -  extract an int parm w/o supplying a buffer
74  */
75 int extract_int(char *source, int parmnum)
76 {
77         char buf[256];
78         
79         extract_token(buf, source, parmnum, '|');
80         return(atoi(buf));
81 }
82
83 /*
84  * extract_long()  -  extract an long parm w/o supplying a buffer
85  */
86 long extract_long(char *source, long int parmnum)
87 {
88         char buf[256];
89         
90         extract_token(buf, source, parmnum, '|');
91         return(atol(buf));
92 }
93
94
95
96 /*
97  * decode_base64() and encode_base64() are adaptations of code by
98  * John Walker, found in full in the file "base64.c" included with this
99  * distribution.  The difference between those functions and these is that
100  * these are intended to encode/decode small string buffers, and those are
101  * intended to encode/decode entire MIME parts.
102  */
103
104 void encode_base64(char *dest, char *source)
105 {
106     int i, hiteof = FALSE;
107     int spos = 0;
108     int dpos = 0;
109
110     /*  Fill dtable with character encodings.  */
111
112     for (i = 0; i < 26; i++) {
113         dtable[i] = 'A' + i;
114         dtable[26 + i] = 'a' + i;
115     }
116     for (i = 0; i < 10; i++) {
117         dtable[52 + i] = '0' + i;
118     }
119     dtable[62] = '+';
120     dtable[63] = '/';
121
122     while (!hiteof) {
123         byte igroup[3], ogroup[4];
124         int c, n;
125
126         igroup[0] = igroup[1] = igroup[2] = 0;
127         for (n = 0; n < 3; n++) {
128             c = source[spos++];
129             if (c == 0) {
130                 hiteof = TRUE;
131                 break;
132             }
133             igroup[n] = (byte) c;
134         }
135         if (n > 0) {
136             ogroup[0] = dtable[igroup[0] >> 2];
137             ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
138             ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
139             ogroup[3] = dtable[igroup[2] & 0x3F];
140
141             /* Replace characters in output stream with "=" pad
142                characters if fewer than three characters were
143                read from the end of the input stream. */
144
145             if (n < 3) {
146                 ogroup[3] = '=';
147                 if (n < 2) {
148                     ogroup[2] = '=';
149                 }
150             }
151             for (i = 0; i < 4; i++) {
152                 dest[dpos++] = ogroup[i];
153                 dest[dpos] = 0;
154             }
155         }
156     }
157 }
158
159
160
161 void decode_base64(char *dest, char *source)
162 {
163     int i;
164     int dpos = 0;
165     int spos = 0;
166
167     for (i = 0; i < 255; i++) {
168         dtable[i] = 0x80;
169     }
170     for (i = 'A'; i <= 'Z'; i++) {
171         dtable[i] = 0 + (i - 'A');
172     }
173     for (i = 'a'; i <= 'z'; i++) {
174         dtable[i] = 26 + (i - 'a');
175     }
176     for (i = '0'; i <= '9'; i++) {
177         dtable[i] = 52 + (i - '0');
178     }
179     dtable['+'] = 62;
180     dtable['/'] = 63;
181     dtable['='] = 0;
182
183     /*CONSTANTCONDITION*/
184     while (TRUE) {
185         byte a[4], b[4], o[3];
186
187         for (i = 0; i < 4; i++) {
188             int c = source[spos++];
189
190             if (c == 0) {
191                 if (i > 0) {
192                     return;
193                 }
194                 return;
195             }
196             if (dtable[c] & 0x80) {
197                 /* Ignoring errors: discard invalid character. */
198                 i--;
199                 continue;
200             }
201             a[i] = (byte) c;
202             b[i] = (byte) dtable[c];
203         }
204         o[0] = (b[0] << 2) | (b[1] >> 4);
205         o[1] = (b[1] << 4) | (b[2] >> 2);
206         o[2] = (b[2] << 6) | b[3];
207         i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
208         if (i>=1) dest[dpos++] = o[0];
209         if (i>=2) dest[dpos++] = o[1];
210         if (i>=3) dest[dpos++] = o[2];
211         dest[dpos] = 0;
212         if (i < 3) {
213             return;
214         }
215     }
216 }