initial NAMESPACE implementation
Showing
1 changed file
with
210 additions
and
0 deletions
imap4d/namespace.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #include "imap4d.h" | ||
19 | |||
20 | /*FIXME: should be global? */ | ||
21 | typedef int (*nsfp_t) __P((void *closure, int ns, char *path, int delim)); | ||
22 | |||
23 | struct namespace_t | ||
24 | { | ||
25 | int subdir_c; | ||
26 | char **subdir_v; | ||
27 | }; | ||
28 | |||
29 | struct namespace_t namespace[NS_MAX]; | ||
30 | |||
31 | /* Note: str is not supposed to be NULL */ | ||
32 | int | ||
33 | set_namespace(int i, char *str) | ||
34 | { | ||
35 | char *p, *save; | ||
36 | struct namespace_t ns; | ||
37 | |||
38 | /* first, estimate the number of items in subdir_v array: */ | ||
39 | ns.subdir_c = 1; | ||
40 | for (p = strchr(str, ':'); p && *p; p = strchr(p+1, ':')) | ||
41 | ns.subdir_c++; | ||
42 | |||
43 | /* Now allocate the memory */ | ||
44 | ns.subdir_v = calloc(ns.subdir_c, sizeof(ns.subdir_v[0])); | ||
45 | |||
46 | /* Fill in the array */ | ||
47 | if (ns.subdir_c == 1) | ||
48 | { | ||
49 | ns.subdir_v[0] = util_normalize_path(strdup(str), "/"); | ||
50 | } | ||
51 | else | ||
52 | { | ||
53 | ns.subdir_c = 0; | ||
54 | for (p = strtok_r(str, ":", &save); p; p = strtok_r(NULL, ":", &save)) | ||
55 | { | ||
56 | ns.subdir_v[ns.subdir_c++] = util_normalize_path(strdup(p), "/"); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | namespace[i] = ns; | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static char * | ||
66 | printable_pathname(char *str) | ||
67 | { | ||
68 | if (strncmp(str, homedir, strlen(homedir)) == 0) | ||
69 | { | ||
70 | str += strlen(homedir); | ||
71 | if (str[0] == '/') | ||
72 | str++; | ||
73 | } | ||
74 | return str; | ||
75 | } | ||
76 | |||
77 | static int | ||
78 | print_namespace(int n) | ||
79 | { | ||
80 | int i; | ||
81 | |||
82 | if (namespace[n].subdir_c == 0) | ||
83 | { | ||
84 | util_send("NIL"); | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | util_send("("); | ||
89 | for (i = 0; i < namespace[n].subdir_c; i++) | ||
90 | { | ||
91 | util_send("(\"%s\" \"/\")", printable_pathname(namespace[n].subdir_v[i])); | ||
92 | } | ||
93 | util_send(")"); | ||
94 | } | ||
95 | |||
96 | int | ||
97 | namespace_enumerate(int ns, nsfp_t f, void *closure) | ||
98 | { | ||
99 | int i, rc; | ||
100 | |||
101 | for (i = 0; i < namespace[ns].subdir_c; i++) | ||
102 | if (rc = (*f)(closure, ns, namespace[ns].subdir_v[i], '/')) | ||
103 | return rc; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | int | ||
108 | namespace_enumerate_all(nsfp_t f, void *closure) | ||
109 | { | ||
110 | return namespace_enumerate(NS_PRIVATE, f, closure) | ||
111 | || namespace_enumerate(NS_OTHER, f, closure) | ||
112 | || namespace_enumerate(NS_SHARED, f, closure); | ||
113 | } | ||
114 | |||
115 | int | ||
116 | imap4d_namespace(struct imap4d_command *command, char *arg) | ||
117 | { | ||
118 | if (! (command->states & state)) | ||
119 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
120 | if (*arg) | ||
121 | return util_finish (command, RESP_BAD, "Too many arguments"); | ||
122 | |||
123 | util_send("* NAMESPACE "); | ||
124 | |||
125 | print_namespace(NS_PRIVATE); | ||
126 | util_send(" "); | ||
127 | print_namespace(NS_OTHER); | ||
128 | util_send(" "); | ||
129 | print_namespace(NS_SHARED); | ||
130 | util_send("\r\n"); | ||
131 | |||
132 | return util_finish (command, RESP_OK, "Completed"); | ||
133 | } | ||
134 | |||
135 | |||
136 | struct namespace_info | ||
137 | { | ||
138 | char *name; | ||
139 | int namelen; | ||
140 | int ns; | ||
141 | int exact; | ||
142 | }; | ||
143 | |||
144 | static int | ||
145 | check_namespace (void *closure, int ns, char *path, int delim) | ||
146 | { | ||
147 | struct namespace_info *p = (struct namespace_info *)closure; | ||
148 | int len = strlen(path); | ||
149 | if ((len == 0 && p->namelen == len) | ||
150 | || (len > 0 && strncmp(path, p->name, strlen(path)) == 0)) | ||
151 | { | ||
152 | p->ns = ns; | ||
153 | p->exact = len == p->namelen; | ||
154 | return 1; | ||
155 | } | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int | ||
160 | risky_pattern(const char *pattern, int delim) | ||
161 | { | ||
162 | for (; *pattern && *pattern != delim; pattern++) | ||
163 | { | ||
164 | if (*pattern == '%' || *pattern == '*') | ||
165 | return 1; | ||
166 | } | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | char * | ||
171 | namespace_checkfullpath (char *name, const char *pattern, const char *delim) | ||
172 | { | ||
173 | struct namespace_info info; | ||
174 | char *path = util_getfullpath(name, delim); | ||
175 | |||
176 | if (!path) | ||
177 | return path; | ||
178 | |||
179 | util_normalize_path(path, "/"); | ||
180 | |||
181 | info.name = path; | ||
182 | info.namelen = strlen(path); | ||
183 | if (!namespace_enumerate_all(check_namespace, &info)) | ||
184 | { | ||
185 | free(path); | ||
186 | return NULL; | ||
187 | } | ||
188 | |||
189 | if (pattern && | ||
190 | info.ns == NS_OTHER && info.exact && risky_pattern(pattern, '/')) | ||
191 | { | ||
192 | free(path); | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | return path; | ||
197 | } | ||
198 | |||
199 | char * | ||
200 | namespace_getfullpath (char *name, const char *delim) | ||
201 | { | ||
202 | return namespace_checkfullpath (name, NULL, delim); | ||
203 | } | ||
204 | |||
205 | |||
206 | int | ||
207 | namespace_init(char *path) | ||
208 | { | ||
209 | set_namespace(NS_PRIVATE, path); | ||
210 | } |
-
Please register or sign in to post a comment