1 /*
2 
3  Copyright (c) 2009-2012 NFG Net Facilities Group BV support@nfg.nl
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later
9  version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include "dbmail.h"
22 #include "dm_capa.h"
23 
24 #define THIS_MODULE "CAPA"
25 
26 /*
27  */
28 
29 #define T Capa_T
30 
31 #define MAX_CAPASIZE 1024
32 
33 struct T {
34 	Mempool_T pool;
35 	const char capabilities[MAX_CAPASIZE];
36 	List_T max_set;
37 	List_T current_set;
38 	gboolean dirty;
39 };
40 
capa_search(List_T set,const char * c)41 static List_T capa_search(List_T set, const char *c)
42 {
43 	List_T found = NULL;
44 	List_T first = p_list_first(set);
45 	String_T S;
46 	char *s;
47 	while (first) {
48 		S = p_list_data(first);
49 		s = (char *)p_string_str(S);
50 		if (strcasecmp(s, c)==0) {
51 			found = first;
52 			break;
53 		}
54 		first = p_list_next(first);
55 	}
56 	return found;
57 }
58 
capa_update(T A)59 static void capa_update(T A)
60 {
61 	if (! A->dirty)
62 		return;
63 
64 	String_T t = p_string_new(A->pool, "");
65 	List_T L = p_list_first(A->current_set);
66 	while (L) {
67 		String_T S = p_list_data(L);
68 		char *s = (char *)p_string_str(S);
69 		p_string_append(t, s);
70 		L = p_list_next(L);
71 		if (L)
72 			p_string_append(t, " ");
73 	}
74 	strncpy((char *)A->capabilities, p_string_str(t), MAX_CAPASIZE-1);
75 	p_string_free(t, TRUE);
76 	t = NULL;
77 	A->dirty = FALSE;
78 }
79 
Capa_new(Mempool_T pool)80 T Capa_new(Mempool_T pool)
81 {
82 	Field_T val;
83         char maxcapa[MAX_CAPASIZE];
84 	T A;
85 	A = mempool_pop(pool, sizeof(*A));
86 	A->pool = pool;
87 	char **v, **h;
88 
89 	memset(&maxcapa,0,sizeof(maxcapa));
90 
91 	GETCONFIGVALUE("capability", "IMAP", val);
92 	if (strlen(val) > 0)
93 		strncpy((char *)maxcapa, val, MAX_CAPASIZE-1);
94 	else
95 		strncpy((char *)maxcapa, IMAP_CAPABILITY_STRING, MAX_CAPASIZE-1);
96 
97 	A->max_set = p_list_new(A->pool);
98 	A->current_set = p_list_new(A->pool);
99 
100 	h = v = g_strsplit(maxcapa, " ", -1);
101 	while (*v) {
102 		String_T S = p_string_new(A->pool, *v++);
103 		A->max_set = p_list_append(A->max_set, S);
104 		A->current_set = p_list_append(A->current_set, S);
105 		assert(A->current_set);
106 	}
107 
108 	g_strfreev(h);
109 
110 	A->dirty = TRUE;
111 	return A;
112 }
113 
Capa_as_string(T A)114 const gchar * Capa_as_string(T A)
115 {
116 	capa_update(A);
117 	return A->capabilities;
118 }
119 
Capa_match(T A,const char * c)120 gboolean Capa_match(T A, const char *c)
121 {
122 	return capa_search(A->current_set, c)?TRUE:FALSE;
123 }
124 
Capa_add(T A,const char * c)125 void Capa_add(T A, const char *c)
126 {
127 	List_T element = capa_search(A->max_set, c);
128 	if (element) {
129 		A->current_set = p_list_append(A->current_set,
130 				p_list_data(element));
131 		assert(A->current_set);
132 		A->dirty = TRUE;
133 	}
134 }
135 
Capa_remove(T A,const char * c)136 void Capa_remove(T A, const char * c)
137 {
138 	List_T element = capa_search(A->current_set, c);
139 	if (element) {
140 		A->current_set = p_list_remove(A->current_set, element);
141 		p_list_free(&element);
142 		assert(A->current_set);
143 		A->dirty = TRUE;
144 	}
145 }
146 
Capa_free(T * A)147 void Capa_free(T *A)
148 {
149 	Mempool_T pool;
150 	T c = *A;
151 	List_T curr, first;
152 
153 	first = p_list_first(c->current_set);
154 	p_list_free(&first);
155 
156 	first = p_list_first(c->max_set);
157 	curr = first;
158 	while (curr) {
159 		String_T data = p_list_data(curr);
160 		p_string_free(data, TRUE);
161 		curr = p_list_next(curr);
162 	}
163 	p_list_free(&first);
164 
165 	pool = c->pool;
166 	mempool_push(pool, c, sizeof(*c));
167 	c = NULL;
168 }
169 
170