1 /*
2  * libEtPan! -- a mail stuff library
3  *
4  * Copyright (C) 2001, 2005 - DINH Viet Hoa
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the libEtPan! project nor the names of its
16  *    contributors may be used to endorse or promote products derived
17  *    from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #	include <config.h>
34 #endif
35 
36 #include "mailimap_extension.h"
37 
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 
42 #include "clist.h"
43 #include "annotatemore.h"
44 #include "acl.h"
45 #include "uidplus.h"
46 #include "quota.h"
47 #include "namespace.h"
48 #include "xlist.h"
49 #include "xgmlabels.h"
50 #include "xgmmsgid.h"
51 #include "xgmthrid.h"
52 #include "mailimap_id.h"
53 #include "enable.h"
54 #include "condstore.h"
55 #include "qresync.h"
56 #include "mailimap_sort.h"
57 
58 /*
59   the list of registered extensions (struct mailimap_extension_api *)
60 
61   the list of extension is kept as a simple clist.
62 */
63 
64 static clist * mailimap_extension_list = NULL;
65 
66 static struct mailimap_extension_api * internal_extension_list[] = {
67   &mailimap_extension_annotatemore,
68   &mailimap_extension_acl,
69   &mailimap_extension_uidplus,
70   &mailimap_extension_quota,
71   &mailimap_extension_namespace,
72   &mailimap_extension_xlist,
73   &mailimap_extension_xgmlabels,
74   &mailimap_extension_xgmmsgid,
75   &mailimap_extension_xgmthrid,
76   &mailimap_extension_id,
77   &mailimap_extension_enable,
78   &mailimap_extension_condstore,
79   &mailimap_extension_qresync,
80   &mailimap_extension_sort
81 };
82 
83 LIBETPAN_EXPORT
84 int
mailimap_extension_register(struct mailimap_extension_api * extension)85 mailimap_extension_register(struct mailimap_extension_api * extension)
86 {
87   if (mailimap_extension_list == NULL) {
88     mailimap_extension_list = clist_new();
89     if (mailimap_extension_list == NULL)
90       return MAILIMAP_ERROR_MEMORY;
91   }
92 
93   return clist_append(mailimap_extension_list, extension);
94 }
95 
96 LIBETPAN_EXPORT
97 void
mailimap_extension_unregister_all(void)98 mailimap_extension_unregister_all(void)
99 {
100   clist_free(mailimap_extension_list);
101   mailimap_extension_list = NULL;
102 }
103 
104 LIBETPAN_EXPORT
105 int
mailimap_extension_data_parse(int calling_parser,mailstream * fd,MMAPString * buffer,struct mailimap_parser_context * parser_ctx,size_t * indx,struct mailimap_extension_data ** result,size_t progr_rate,progress_function * progr_fun)106 mailimap_extension_data_parse(int calling_parser,
107         mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx,
108         size_t * indx, struct mailimap_extension_data ** result,
109         size_t progr_rate,
110         progress_function * progr_fun)
111 {
112   clistiter * cur;
113   int r;
114   unsigned int i;
115 
116   for(i = 0 ; i < sizeof(internal_extension_list) / sizeof(* internal_extension_list) ; i ++) {
117     struct mailimap_extension_api * ext;
118 
119     ext = internal_extension_list[i];
120     r = ext->ext_parser(calling_parser, fd, buffer, parser_ctx, indx, result,
121         progr_rate, progr_fun);
122     if (r != MAILIMAP_ERROR_PARSE)
123       return r;
124   }
125 
126   if (mailimap_extension_list == NULL)
127     return MAILIMAP_ERROR_PARSE;
128 
129   for (cur = clist_begin(mailimap_extension_list);
130         cur != NULL; cur = clist_next(cur)) {
131     struct mailimap_extension_api * ext;
132 
133     ext = clist_content(cur);
134     r = ext->ext_parser(calling_parser, fd, buffer, parser_ctx, indx, result,
135         progr_rate, progr_fun);
136     if (r != MAILIMAP_ERROR_PARSE)
137       return r;
138   }
139 
140   return MAILIMAP_ERROR_PARSE;
141 }
142 
143 LIBETPAN_EXPORT
144 struct mailimap_extension_data *
mailimap_extension_data_new(struct mailimap_extension_api * extension,int type,void * data)145 mailimap_extension_data_new(struct mailimap_extension_api * extension,
146         int type, void * data)
147 {
148   struct mailimap_extension_data * ext_data;
149 
150   ext_data = malloc(sizeof(* ext_data));
151   if (ext_data == NULL)
152     return NULL;
153 
154   ext_data->ext_extension = extension;
155   ext_data->ext_type = type;
156   ext_data->ext_data = data;
157 
158   return ext_data;
159 }
160 
161 LIBETPAN_EXPORT
162 void
mailimap_extension_data_free(struct mailimap_extension_data * data)163 mailimap_extension_data_free(struct
164         mailimap_extension_data * data)
165 {
166   if (data == NULL)
167     return;
168 
169   if (data->ext_extension != NULL && data->ext_data != NULL)
170     /* ext_free() includes free(data) */
171     data->ext_extension->ext_free(data);
172   else
173     free(data);
174 }
175 
mailimap_extension_data_store(mailimap * session,struct mailimap_extension_data ** ext_data)176 void mailimap_extension_data_store(mailimap * session,
177     struct mailimap_extension_data ** ext_data)
178 {
179   int r;
180 
181   if (session->imap_response_info) {
182     r = clist_append(session->imap_response_info->rsp_extension_list,
183         * ext_data);
184     if (r == 0)
185 	    * ext_data = NULL;
186     else {
187 	/* TODO must handle error case */
188     }
189   }
190 }
191 
192 LIBETPAN_EXPORT
mailimap_has_extension(mailimap * session,const char * extension_name)193 int mailimap_has_extension(mailimap * session, const char * extension_name)
194 {
195   if (session->imap_connection_info != NULL) {
196     if (session->imap_connection_info->imap_capability != NULL) {
197       clist * list;
198       clistiter * cur;
199 
200       list = session->imap_connection_info->imap_capability->cap_list;
201       for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
202         struct mailimap_capability * cap;
203 
204         cap = clist_content(cur);
205         if (cap->cap_type != MAILIMAP_CAPABILITY_NAME)
206           continue;
207 
208         if (strcasecmp(cap->cap_data.cap_name, extension_name) == 0)
209           return 1;
210       }
211     }
212   }
213 
214   return 0;
215 }
216 
217 LIBETPAN_EXPORT
mailimap_has_authentication(mailimap * session,const char * authentication_name)218 int mailimap_has_authentication(mailimap * session, const char * authentication_name)
219 {
220   if (session->imap_connection_info != NULL) {
221     if (session->imap_connection_info->imap_capability != NULL) {
222       clist * list;
223       clistiter * cur;
224 
225       list = session->imap_connection_info->imap_capability->cap_list;
226       for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
227         struct mailimap_capability * cap;
228 
229         cap = clist_content(cur);
230         if (cap->cap_type != MAILIMAP_CAPABILITY_AUTH_TYPE)
231           continue;
232 
233         if (strcasecmp(cap->cap_data.cap_name, authentication_name) == 0)
234           return 1;
235 
236       }
237     }
238   }
239 
240   return 0;
241 }
242