1 /**********************************************************************
2  * token.h                                               September 1999
3  * Horms                                             horms@verge.net.au
4  *
5  * Token to encapsulate a byte string
6  *
7  * perdition
8  * Mail retrieval proxy server
9  * Copyright (C) 1999-2005  Horms
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of the
14  * License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  **********************************************************************/
26 
27 #ifndef TOKEN_BLUM
28 #define TOKEN_BLUM
29 
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <vanessa_socket.h>
38 
39 #include "log.h"
40 #include "str.h"
41 #include "perdition_types.h"
42 
43 #define BUFFER_SIZE (size_t)1024
44 
45 #define TOKEN_DESTROY (void (*)(const void *))token_destroy
46 
47 typedef struct{
48   size_t n;
49   char *buf;
50   flag_t flag;
51 }token_t;
52 
53 /*
54  * Flags for Tokens
55  */
56 #define TOKEN_NONE        (flag_t) 0x00   /* No flag (NULL state) */
57 #define TOKEN_EOL         (flag_t) 0x01   /* Token is at the end of a line */
58 #define TOKEN_DONT_CARE   (flag_t) 0x03   /* Don't care what token is.
59 					     Used for comparisons */
60 
61 /*
62  * Flags for tokeniser
63  */
64 /* #define TOKEN_EOL, defined above */
65 #define TOKEN_POP3            (flag_t) 0x02
66 #define TOKEN_ACAP_ATOM       TOKEN_POP3
67 #define TOKEN_IMAP4           (flag_t) 0x04
68 #define TOKEN_MANAGESIEVE     TOKEN_IMAP4
69 #define TOKEN_IMAP4_LITERAL   (flag_t) 0x08
70 #define TOKEN_ACAP_LITERAL    TOKEN_IMAP4_LITERAL
71 
72 #define TOKEN_NO_STRIP    (unsigned char) '\0'
73 
74 token_t *create_token(void);
75 
76 
77 /**********************************************************************
78  * token_create
79  * create an empty token
80  * pre: none
81  * post: token is created, and values are initialised
82  * return: allocated token_t
83  *         NULL on error
84  *
85  * 8 bit clean
86  **********************************************************************/
87 
88 token_t *token_create(void);
89 
90 
91 /**********************************************************************
92  * token_assign
93  * place bytes into a token
94  * pre: t: token to place bytes in
95  *      buf: buffer to use
96  *      n: number of bytes in buffer
97  *      flags: flags for token as per token.h
98  * post: if n!=0 then buf is used as the buffer in t
99  *       (no copying)
100  *       if n==0 the buffer in t is set to NULL
101  *       the flag in t is set
102  * return: none
103  *
104  * 8 bit clean
105  **********************************************************************/
106 
107 void token_assign(
108   token_t *t,
109   char * buf,
110   const size_t n,
111   const flag_t flag
112 );
113 
114 
115 /**********************************************************************
116  * token_unassign
117  * make a token empty
118  * useful if you want to destroy a token but not what it contains
119  * pre: t: token to unassign values of
120  * post: values in t are reinitialised, but buffer is not destroyed
121  * return: none
122  *
123  * 8 bit clean
124  **********************************************************************/
125 
126 void token_unassign(token_t *t);
127 
128 
129 /**********************************************************************
130  * token_destroy
131  * pre: t pointer to a token
132  * post: if the token is null no nothing
133  *       if buf is non-NULL then free it
134  *       free the token
135  * return: none
136  *
137  * 8 bit clean
138  **********************************************************************/
139 
140 void token_destroy(token_t **t);
141 
142 
143 /**********************************************************************
144  * token_write
145  * write a token to fd
146  * pre: io: io_t to write to
147  *      token: token to write
148  * post: contents of token is written to fd using
149  *       vanessa_socket_pipe_write_bytes
150  * return: -1 on error
151  *         0 otherwise
152  *
153  * 8 bit clean
154  **********************************************************************/
155 
156 int token_write(io_t *io, const token_t *t);
157 
158 
159 /**********************************************************************
160  * token_flush
161  * Flush internal buffers used to read tokens.
162  * pre: none
163  * post: internal buffers are flushed
164  * return: none
165  **********************************************************************/
166 
167 void token_flush(void);
168 
169 
170 /**********************************************************************
171  * token_read
172  * read a token in from fd
173  * pre: io: io_t to read from
174  *      literal_buf: buffer to store bytes read from server in
175  *      n: pointer to size_t containing the size of literal_buf
176  *      flag: If logical or of TOKEN_EOL then all characters
177  *            up to a '\n' will be read as a token. That is the token may
178  *            have spaces.
179  *            If logical or of TOKEN_IMAP4 then spaces inside
180  *            quotes will be treated as literals rather than token
181  *            delimiters.
182  *            If logical or of TOKEN_IMAP4_LITERAL then m bytes
183  *            will be read as a single token.
184  *      m: Bytes to read if flag is TOKEN_IMAP4_LITERAL
185  *      log_str: logging tag for connection logging
186  * post: Token is read from fd into token
187  *       ' ' will terminate a token
188  *       '\r' is ignored
189  *       '\n' will terminate a token and set the eol element to 1
190  *       All other characters are considered to be a part of the token
191  *       If literal_buf is not NULL, and n is not NULL and *n is not 0
192  *       Bytes read from fd are copied to literal_buf, this includes
193  *       ' ', '\r' and '\n'.
194  * return: token
195  *         NULL on error
196  * Note: if a token larger than BUFFER_SIZE is read then only
197  *       BUFFER_SIZE will be read and the remainder will be
198  *       left (to be handled by an subsequent call to token_read).
199  *       The same applies to *n if literal_buf is being filled.
200  *
201  * 8 bit clean
202  **********************************************************************/
203 
204 token_t *token_read(
205   io_t *io,
206   char *literal_buf,
207   size_t *n,
208   flag_t flag,
209   size_t m,
210   const char *log_str
211 );
212 
213 
214 /**********************************************************************
215  * token_is_eol
216  * Check if the token is at the end of a line
217  * pre: t: token to check eol flag of
218  * post: none
219  * return 1 if the token is at the end of a line
220  *        0 otherwise
221  **********************************************************************/
222 
223 #define token_is_eol(_t) ((_t)->flag&TOKEN_EOL?1:0)
224 
225 
226 /**********************************************************************
227  * token_buf
228  * Get the buffer of a token
229  * pre: t: token to get the buffer of
230  * post: none
231  * return: buffer of the token
232  **********************************************************************/
233 
234 #define token_buf(_t) ((_t)->buf)
235 
236 
237 /**********************************************************************
238  * token_len
239  * Get the length of a token
240  * pre: t: token to get the length of
241  * post: none
242  * return: length of the token
243  **********************************************************************/
244 
245 #define token_len(_t) ((_t)->n)
246 
247 
248 /**********************************************************************
249  * token_cmp
250  * compare two tokens
251  * pre: a: token to compare
252  *      b: token to compare
253  * post: none
254  * return: 1 is they are the same
255  *         0 otherwise
256  * flag field will be ignored if either token has eol set to TOKEN_DONT_CARE
257  *
258  * Not 8 bit clean as it is case insensitive using toupper
259  **********************************************************************/
260 
261 int token_cmp(const token_t *a, const token_t *b);
262 
263 
264 /**********************************************************************
265  * token_is_null
266  * test if a token is null, that is has an empty payload
267  * pre: t: token to test
268  * post: none
269  * return 1 if token is null
270  *        0 otherwise
271  * t->flag is ignored
272  *
273  * 8 bit clean
274  **********************************************************************/
275 
276 #define token_is_null(_t) ((_t)->n?0:1)
277 
278 
279 /**********************************************************************
280  * token_to_string
281  * dump the buffer in a token into a \0 terminated string
282  * string will be dynamically allocated
283  * pre: t: token to dump to a string
284  *      strip: Character to strip from first and last character of
285  *             string if it is present. Ignored if TOKEN_NO_STRIP
286  *
287  * post: a string is allocated and the contents of it's buffer plus
288  *       a trailing '\0' is placed in the string
289  * return: the string
290  *         NULL on error
291  *
292  * Not 8 bit clean
293  **********************************************************************/
294 
295 char *token_to_string(const token_t *t, const unsigned char strip);
296 
297 /**********************************************************************
298  * token_casecmp_string
299  * Compare a token with a null-terminated string
300  * pre: t: token
301  *      str: string
302  * return: 1 on match
303  *         0 otherwise
304  *
305  * Not 8 bit clean
306  **********************************************************************/
307 
308 int token_casecmp_string(const token_t *t, const char *str);
309 
310 #endif
311