Mercurial > dovecot > core-2.2
annotate src/lib-storage/index/index-search.c @ 160:ff05b320482c HEAD
Bigger changes.. full_virtual_size was removed from index record and
MessagePart caching is now forced. Also added per-message flags, including
binary flags which can be used to check if CRs need to be inserted into
message data.
Added mbox-rewrite support which can be used to write out mbox file with
updated flags. This still has the problem of being able to read changed
custom flags, that'll require another bigger change.
There's also several other mostly mbox related fixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 06 Sep 2002 16:43:58 +0300 |
parents | 2f67de235489 |
children | 4a7ab9e94f25 |
rev | line source |
---|---|
0 | 1 /* Copyright (C) 2002 Timo Sirainen */ |
2 | |
3 #include "lib.h" | |
4 #include "iobuffer.h" | |
5 #include "mmap-util.h" | |
6 #include "rfc822-tokenize.h" | |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
7 #include "imap-date.h" |
0 | 8 #include "index-storage.h" |
160
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
9 #include "mail-index-util.h" |
0 | 10 #include "mail-search.h" |
11 | |
12 #include <stdlib.h> | |
13 #include <ctype.h> | |
14 | |
15 #define ARG_SET_RESULT(arg, res) \ | |
16 STMT_START { \ | |
17 (arg)->result = !(arg)->not ? (res) : -(res); \ | |
18 } STMT_END | |
19 | |
20 typedef struct { | |
21 IndexMailbox *ibox; | |
22 MailIndexRecord *rec; | |
23 unsigned int seq; | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
24 } SearchIndexContext; |
0 | 25 |
26 typedef struct { | |
27 MailSearchArg *args; | |
28 int custom_header; | |
29 | |
30 const char *name, *value; | |
31 unsigned int name_len, value_len; | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
32 } SearchHeaderContext; |
0 | 33 |
34 typedef struct { | |
35 MailSearchArg *args; | |
36 const char *msg; | |
37 size_t size; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
38 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
39 unsigned int max_searchword_len; |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
40 } SearchTextContext; |
0 | 41 |
42 static int msgset_contains(const char *set, unsigned int match_num, | |
43 unsigned int max_num) | |
44 { | |
45 unsigned int num, num2; | |
46 | |
47 while (*set != '\0') { | |
48 if (*set == '*') { | |
49 set++; | |
50 num = max_num; | |
51 } else { | |
52 num = 0; | |
53 while (*set >= '0' && *set <= '9') { | |
54 num = num*10 + (*set-'0'); | |
55 set++; | |
56 } | |
57 } | |
58 | |
59 if (*set == ',' || *set == '\0') { | |
60 if (num == match_num) | |
61 return TRUE; | |
62 if (*set == '\0') | |
63 return FALSE; | |
64 } else if (*set == ':') { | |
109
27fd7817b226
specifying messageset/uidset in SEARCH broke it
Timo Sirainen <tss@iki.fi>
parents:
66
diff
changeset
|
65 set++; |
27fd7817b226
specifying messageset/uidset in SEARCH broke it
Timo Sirainen <tss@iki.fi>
parents:
66
diff
changeset
|
66 |
0 | 67 if (*set == '*') { |
68 set++; | |
69 | |
70 if (match_num >= num && num <= max_num) | |
71 return TRUE; | |
72 } else { | |
73 num2 = 0; | |
74 while (*set >= '0' && *set <= '9') { | |
75 num2 = num2*10 + (*set-'0'); | |
76 set++; | |
77 } | |
78 | |
79 if (match_num >= num && match_num <= num2) | |
80 return TRUE; | |
81 } | |
82 | |
83 if (*set != ',') | |
84 return FALSE; | |
85 } | |
86 | |
87 set++; | |
88 } | |
89 | |
90 return FALSE; | |
91 } | |
92 | |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
46
diff
changeset
|
93 static uoff_t str_to_uoff_t(const char *str) |
46 | 94 { |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
46
diff
changeset
|
95 uoff_t num; |
46 | 96 |
97 num = 0; | |
98 while (*str != '\0') { | |
99 if (*str < '0' || *str > '9') | |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
46
diff
changeset
|
100 return 0; |
46 | 101 |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
46
diff
changeset
|
102 num = num*10 + (*str - '0'); |
46 | 103 } |
104 | |
105 return num; | |
106 } | |
107 | |
0 | 108 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ |
109 static int search_arg_match_index(IndexMailbox *ibox, MailIndexRecord *rec, | |
110 unsigned int seq, MailSearchArgType type, | |
111 const char *value) | |
112 { | |
113 time_t t; | |
160
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
114 uoff_t size; |
0 | 115 |
116 switch (type) { | |
117 case SEARCH_ALL: | |
118 return TRUE; | |
119 case SEARCH_SET: | |
120 return msgset_contains(value, seq, ibox->synced_messages_count); | |
121 case SEARCH_UID: | |
122 return msgset_contains(value, rec->uid, | |
123 ibox->synced_messages_count); | |
124 | |
125 /* flags */ | |
126 case SEARCH_ANSWERED: | |
127 return rec->msg_flags & MAIL_ANSWERED; | |
128 case SEARCH_DELETED: | |
129 return rec->msg_flags & MAIL_DELETED; | |
130 case SEARCH_DRAFT: | |
131 return rec->msg_flags & MAIL_DRAFT; | |
132 case SEARCH_FLAGGED: | |
133 return rec->msg_flags & MAIL_FLAGGED; | |
134 case SEARCH_SEEN: | |
135 return rec->msg_flags & MAIL_SEEN; | |
136 case SEARCH_RECENT: | |
137 return rec->uid >= ibox->index->first_recent_uid; | |
138 case SEARCH_KEYWORD: | |
139 return FALSE; | |
140 | |
141 /* dates */ | |
142 case SEARCH_BEFORE: | |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
143 if (!imap_parse_date(value, &t)) |
0 | 144 return FALSE; |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
145 return rec->internal_date < t; |
0 | 146 case SEARCH_ON: |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
147 if (!imap_parse_date(value, &t)) |
0 | 148 return FALSE; |
149 return rec->internal_date >= t && | |
150 rec->internal_date < t + 3600*24; | |
151 case SEARCH_SINCE: | |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
152 if (!imap_parse_date(value, &t)) |
0 | 153 return FALSE; |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
154 return rec->internal_date >= t; |
0 | 155 |
156 case SEARCH_SENTBEFORE: | |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
157 if (!imap_parse_date(value, &t)) |
0 | 158 return FALSE; |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
159 return rec->sent_date < t; |
0 | 160 case SEARCH_SENTON: |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
161 if (!imap_parse_date(value, &t)) |
0 | 162 return FALSE; |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
163 return rec->sent_date >= t && rec->sent_date < t + 3600*24; |
0 | 164 case SEARCH_SENTSINCE: |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
165 if (!imap_parse_date(value, &t)) |
0 | 166 return FALSE; |
119
2f67de235489
Whops, we were using RFC822 dates everywhere instead of IMAP dates.
Timo Sirainen <tss@iki.fi>
parents:
109
diff
changeset
|
167 return rec->sent_date >= t; |
0 | 168 |
160
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
169 /* sizes, only with fastscanning */ |
0 | 170 case SEARCH_SMALLER: |
160
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
171 if (!mail_index_get_virtual_size(ibox->index, rec, TRUE, &size)) |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
172 return -1; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
173 return size < str_to_uoff_t(value); |
0 | 174 case SEARCH_LARGER: |
160
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
175 if (!mail_index_get_virtual_size(ibox->index, rec, TRUE, &size)) |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
176 return -1; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
177 return size > str_to_uoff_t(value); |
0 | 178 |
179 default: | |
180 return -1; | |
181 } | |
182 } | |
183 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
184 static void search_index_arg(MailSearchArg *arg, void *context) |
0 | 185 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
186 SearchIndexContext *ctx = context; |
0 | 187 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
188 switch (search_arg_match_index(ctx->ibox, ctx->rec, ctx->seq, |
0 | 189 arg->type, arg->value.str)) { |
190 case -1: | |
191 /* unknown */ | |
192 break; | |
193 case 0: | |
194 ARG_SET_RESULT(arg, -1); | |
195 break; | |
196 default: | |
197 ARG_SET_RESULT(arg, 1); | |
198 break; | |
199 } | |
200 } | |
201 | |
202 static int match_field(MailIndex *index, MailIndexRecord *rec, | |
203 MailField field, const char *value) | |
204 { | |
205 const char *field_value; | |
206 unsigned int i, value_len; | |
207 | |
208 field_value = index->lookup_field(index, rec, field); | |
209 if (field_value == NULL) | |
210 return -1; | |
211 | |
212 /* note: value is already uppercased */ | |
213 value_len = strlen(value); | |
214 for (i = 0; field_value[i] != '\0'; i++) { | |
215 if (value[0] == i_toupper(field_value[i]) && | |
216 strncasecmp(value, field_value+i, value_len) == 0) | |
217 return 1; | |
218 } | |
219 | |
220 return 0; | |
221 } | |
222 | |
223 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ | |
224 static int search_arg_match_cached(MailIndex *index, MailIndexRecord *rec, | |
225 MailSearchArgType type, const char *value) | |
226 { | |
227 switch (type) { | |
228 case SEARCH_FROM: | |
229 return match_field(index, rec, FIELD_TYPE_FROM, value); | |
230 case SEARCH_TO: | |
231 return match_field(index, rec, FIELD_TYPE_TO, value); | |
232 case SEARCH_CC: | |
233 return match_field(index, rec, FIELD_TYPE_CC, value); | |
234 case SEARCH_BCC: | |
235 return match_field(index, rec, FIELD_TYPE_BCC, value); | |
236 case SEARCH_SUBJECT: | |
237 return match_field(index, rec, FIELD_TYPE_SUBJECT, value); | |
238 default: | |
239 return -1; | |
240 } | |
241 } | |
242 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
243 static void search_cached_arg(MailSearchArg *arg, void *context) |
0 | 244 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
245 SearchIndexContext *ctx = context; |
0 | 246 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
247 switch (search_arg_match_cached(ctx->ibox->index, ctx->rec, |
0 | 248 arg->type, arg->value.str)) { |
249 case -1: | |
250 /* unknown */ | |
251 break; | |
252 case 0: | |
253 ARG_SET_RESULT(arg, -1); | |
254 break; | |
255 default: | |
256 ARG_SET_RESULT(arg, 1); | |
257 break; | |
258 } | |
259 } | |
260 | |
160
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
261 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
262 static int search_arg_match_slow(MailIndex *index, MailIndexRecord *rec, |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
263 MailSearchArgType type, const char *value) |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
264 { |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
265 uoff_t size; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
266 |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
267 switch (type) { |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
268 /* sizes, only with fastscanning */ |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
269 case SEARCH_SMALLER: |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
270 if (!mail_index_get_virtual_size(index, rec, FALSE, &size)) |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
271 return -1; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
272 return size < str_to_uoff_t(value); |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
273 case SEARCH_LARGER: |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
274 if (!mail_index_get_virtual_size(index, rec, FALSE, &size)) |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
275 return -1; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
276 return size > str_to_uoff_t(value); |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
277 |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
278 default: |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
279 return -1; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
280 } |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
281 } |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
282 |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
283 static void search_slow_arg(MailSearchArg *arg, void *context) |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
284 { |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
285 SearchIndexContext *ctx = context; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
286 |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
287 switch (search_arg_match_slow(ctx->ibox->index, ctx->rec, |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
288 arg->type, arg->value.str)) { |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
289 case -1: |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
290 /* unknown */ |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
291 break; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
292 case 0: |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
293 ARG_SET_RESULT(arg, -1); |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
294 break; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
295 default: |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
296 ARG_SET_RESULT(arg, 1); |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
297 break; |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
298 } |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
299 } |
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
300 |
0 | 301 /* needle must be uppercased */ |
302 static int header_value_match(const char *haystack, unsigned int haystack_len, | |
303 const char *needle) | |
304 { | |
305 const char *n; | |
306 unsigned int i, j, needle_len, max; | |
307 | |
308 if (*needle == '\0') | |
309 return TRUE; | |
310 | |
311 needle_len = strlen(needle); | |
312 if (haystack_len < needle_len) | |
313 return FALSE; | |
314 | |
315 max = haystack_len - needle_len; | |
316 for (i = 0; i <= max; i++) { | |
317 if (needle[0] != i_toupper(haystack[i])) | |
318 continue; | |
319 | |
320 for (j = i, n = needle; j < haystack_len; j++) { | |
321 if (haystack[j] == '\r') { | |
322 if (j+1 != haystack_len) | |
323 j++; | |
324 } | |
325 | |
326 if (haystack[j] == '\n' && j+1 < haystack_len && | |
327 IS_LWSP(haystack[j+1])) { | |
328 /* long header continuation */ | |
329 j++; | |
330 } | |
331 | |
332 if (*n++ != i_toupper(haystack[j])) | |
333 break; | |
334 | |
335 if (*n == '\0') | |
336 return 1; | |
337 } | |
338 } | |
339 | |
340 return -1; | |
341 } | |
342 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
343 static void search_header_arg(MailSearchArg *arg, void *context) |
0 | 344 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
345 SearchHeaderContext *ctx = context; |
0 | 346 const char *value; |
347 unsigned int len; | |
348 int ret; | |
349 | |
350 /* first check that the field name matches to argument. */ | |
351 switch (arg->type) { | |
352 case SEARCH_FROM: | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
353 if (ctx->name_len != 4 || |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
354 strncasecmp(ctx->name, "From", 4) != 0) |
0 | 355 return; |
356 value = arg->value.str; | |
357 break; | |
358 case SEARCH_TO: | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
359 if (ctx->name_len != 2 || |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
360 strncasecmp(ctx->name, "To", 2) != 0) |
0 | 361 return; |
362 value = arg->value.str; | |
363 break; | |
364 case SEARCH_CC: | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
365 if (ctx->name_len != 2 || |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
366 strncasecmp(ctx->name, "Cc", 2) != 0) |
0 | 367 return; |
368 value = arg->value.str; | |
369 break; | |
370 case SEARCH_BCC: | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
371 if (ctx->name_len != 3 || |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
372 strncasecmp(ctx->name, "Bcc", 3) != 0) |
0 | 373 return; |
374 value = arg->value.str; | |
375 break; | |
376 case SEARCH_SUBJECT: | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
377 if (ctx->name_len != 7 || |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
378 strncasecmp(ctx->name, "Subject", 7) != 0) |
0 | 379 return; |
380 value = arg->value.str; | |
381 break; | |
382 case SEARCH_HEADER: | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
383 ctx->custom_header = TRUE; |
0 | 384 |
385 len = strlen(arg->value.str); | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
386 if (ctx->name_len != len || |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
387 strncasecmp(ctx->name, arg->value.str, len) != 0) |
0 | 388 return; |
389 | |
390 value = arg->hdr_value; | |
391 default: | |
392 return; | |
393 } | |
394 | |
395 /* then check if the value matches */ | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
396 ret = header_value_match(ctx->value, ctx->value_len, value); |
0 | 397 ARG_SET_RESULT(arg, ret); |
398 } | |
399 | |
400 static void search_header(MessagePart *part __attr_unused__, | |
401 const char *name, unsigned int name_len, | |
402 const char *value, unsigned int value_len, | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
403 void *context) |
0 | 404 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
405 SearchHeaderContext *ctx = context; |
0 | 406 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
407 if (ctx->custom_header || |
0 | 408 (name_len == 4 && strncasecmp(name, "From", 4) == 0) || |
409 (name_len == 2 && strncasecmp(name, "To", 2) == 0) || | |
410 (name_len == 2 && strncasecmp(name, "Cc", 2) == 0) || | |
411 (name_len == 3 && strncasecmp(name, "Bcc", 3) == 0) || | |
412 (name_len == 7 && strncasecmp(name, "Subject", 7) == 0)) { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
413 ctx->name = name; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
414 ctx->value = value; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
415 ctx->name_len = name_len; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
416 ctx->value_len = value_len; |
0 | 417 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
418 ctx->custom_header = FALSE; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
419 mail_search_args_foreach(ctx->args, search_header_arg, ctx); |
0 | 420 } |
421 } | |
422 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
423 static void search_text(MailSearchArg *arg, SearchTextContext *ctx) |
0 | 424 { |
425 const char *p; | |
426 unsigned int i, len, max; | |
427 | |
428 if (arg->result != 0) | |
429 return; | |
430 | |
431 len = strlen(arg->value.str); | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
432 if (len > ctx->max_searchword_len) |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
433 ctx->max_searchword_len = len; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
434 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
435 if (ctx->size >= len) { |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
436 max = ctx->size-len; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
437 for (i = 0, p = ctx->msg; i <= max; i++, p++) { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
438 if (i_toupper(*p) == arg->value.str[0] && |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
439 strncasecmp(p, arg->value.str, len) == 0) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
440 /* match */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
441 ARG_SET_RESULT(arg, 1); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
442 return; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
443 } |
0 | 444 } |
445 } | |
446 } | |
447 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
448 static void search_text_header(MailSearchArg *arg, void *context) |
0 | 449 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
450 SearchTextContext *ctx = context; |
0 | 451 |
452 if (arg->type == SEARCH_TEXT) | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
453 search_text(arg, ctx); |
0 | 454 } |
455 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
456 static void search_text_body(MailSearchArg *arg, void *context) |
0 | 457 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
458 SearchTextContext *ctx = context; |
0 | 459 |
460 if (arg->type == SEARCH_TEXT || arg->type == SEARCH_BODY) | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
461 search_text(arg, ctx); |
0 | 462 } |
463 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
464 static void search_text_set_unmatched(MailSearchArg *arg, |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
465 void *context __attr_unused__) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
466 { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
467 if (arg->type == SEARCH_TEXT || arg->type == SEARCH_BODY) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
468 ARG_SET_RESULT(arg, -1); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
469 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
470 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
471 static void search_arg_match_data(IOBuffer *inbuf, unsigned int max_size, |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
472 MailSearchArg *args, |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
473 MailSearchForeachFunc search_func) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
474 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
475 SearchTextContext ctx; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
476 unsigned int size; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
477 int ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
478 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
479 memset(&ctx, 0, sizeof(ctx)); |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
480 ctx.args = args; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
481 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
482 /* do this in blocks: read data, compare it for all search words, skip |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
483 for block size - (strlen(largest_searchword)-1) and continue. */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
484 while (max_size > 0 && |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
485 (ret = io_buffer_read_max(inbuf, max_size)) > 0) { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
486 ctx.msg = io_buffer_get_data(inbuf, &size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
487 if (size > 0) { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
488 ctx.size = max_size < size ? max_size : size; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
489 max_size -= ctx.size; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
490 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
491 mail_search_args_foreach(args, search_func, &ctx); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
492 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
493 if (ctx.max_searchword_len < size) |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
494 size -= ctx.max_searchword_len-1; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
495 io_buffer_skip(inbuf, size); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
496 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
497 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
498 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
499 |
0 | 500 static int search_arg_match_text(IndexMailbox *ibox, MailIndexRecord *rec, |
501 MailSearchArg *args) | |
502 { | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
503 IOBuffer *inbuf; |
0 | 504 int have_headers, have_body, have_text; |
505 | |
506 /* first check what we need to use */ | |
507 mail_search_args_analyze(args, &have_headers, &have_body, &have_text); | |
508 if (!have_headers && !have_body && !have_text) | |
509 return TRUE; | |
510 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
511 inbuf = ibox->index->open_mail(ibox->index, rec); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
512 if (inbuf == NULL) |
0 | 513 return FALSE; |
514 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
515 if (have_headers) { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
516 SearchHeaderContext ctx; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
517 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
518 memset(&ctx, 0, sizeof(ctx)); |
0 | 519 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
520 /* header checks */ |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
521 ctx.custom_header = TRUE; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
522 ctx.args = args; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
523 message_parse_header(NULL, inbuf, NULL, search_header, &ctx); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
524 } |
0 | 525 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
526 if (have_text) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
527 if (inbuf->offset != 0) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
528 /* need to rewind back to beginning of headers */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
529 if (!io_buffer_seek(inbuf, 0)) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
530 i_error("io_buffer_seek() failed: %m"); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
531 return FALSE; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
532 } |
0 | 533 } |
534 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
535 search_arg_match_data(inbuf, rec->header_size, |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
536 args, search_text_header); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
537 } |
0 | 538 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
539 if (have_text || have_body) { |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
46
diff
changeset
|
540 if (inbuf->offset != rec->header_size) { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
541 /* skip over headers */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
542 i_assert(inbuf->offset == 0); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
543 io_buffer_skip(inbuf, rec->header_size); |
0 | 544 } |
545 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
546 search_arg_match_data(inbuf, UINT_MAX, args, search_text_body); |
0 | 547 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
548 /* set the rest as unmatched */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
549 mail_search_args_foreach(args, search_text_set_unmatched, NULL); |
0 | 550 } |
551 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
552 (void)close(inbuf->fd); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
553 io_buffer_destroy(inbuf); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
554 return TRUE; |
0 | 555 } |
556 | |
557 static void seq_update(const char *set, unsigned int *first_seq, | |
558 unsigned int *last_seq, unsigned int max_value) | |
559 { | |
560 unsigned int seq; | |
561 | |
562 while (*set != '\0') { | |
563 if (*set == '*') { | |
564 seq = max_value; | |
565 set++; | |
566 } else { | |
567 seq = 0; | |
568 while (*set >= '0' && *set <= '9') { | |
569 seq = seq*10 + (*set-'0'); | |
570 set++; | |
571 } | |
572 } | |
573 | |
574 if (seq != 0) { | |
575 if (*first_seq == 0 || seq < *first_seq) | |
576 *first_seq = seq; | |
577 if (*last_seq == 0 || seq > *last_seq) | |
578 *last_seq = seq; | |
579 } | |
580 | |
46 | 581 set++; |
0 | 582 } |
583 } | |
584 | |
585 static void search_get_sequid(IndexMailbox *ibox, MailSearchArg *args, | |
586 unsigned int *first_seq, unsigned int *last_seq, | |
587 unsigned int *first_uid, unsigned int *last_uid) | |
588 { | |
589 for (; args != NULL; args = args->next) { | |
590 if (args->type == SEARCH_OR || args->type == SEARCH_SUB) { | |
591 search_get_sequid(ibox, args->value.subargs, | |
592 first_seq, last_seq, | |
593 first_uid, last_uid); | |
594 } if (args->type == SEARCH_SET) { | |
595 seq_update(args->value.str, first_seq, last_seq, | |
596 ibox->synced_messages_count); | |
597 } else if (args->type == SEARCH_UID) { | |
598 seq_update(args->value.str, first_uid, last_uid, | |
599 ibox->index->header->next_uid-1); | |
600 } else if (args->type == SEARCH_ALL) { | |
601 /* go through everything */ | |
602 *first_seq = 1; | |
603 *last_seq = ibox->synced_messages_count; | |
604 return; | |
605 } | |
606 } | |
607 } | |
608 | |
609 static void search_get_sequences(IndexMailbox *ibox, MailSearchArg *args, | |
610 unsigned int *first_seq, | |
611 unsigned int *last_seq) | |
612 { | |
613 MailIndexRecord *rec; | |
614 unsigned int seq, first_uid, last_uid; | |
615 | |
616 *first_seq = *last_seq = 0; | |
617 first_uid = last_uid = 0; | |
618 | |
619 search_get_sequid(ibox, args, first_seq, last_seq, | |
620 &first_uid, &last_uid); | |
621 | |
51 | 622 /* seq_update() should make sure that these can't happen */ |
66 | 623 i_assert(*first_seq <= *last_seq); |
624 i_assert(first_uid <= last_uid); | |
51 | 625 |
0 | 626 if (first_uid != 0 && (*first_seq != 1 || |
627 *last_seq != ibox->synced_messages_count)) { | |
628 /* UIDs were used - see if they affect the sequences */ | |
629 rec = ibox->index->lookup_uid_range(ibox->index, | |
630 first_uid, last_uid); | |
631 if (rec != NULL) { | |
632 /* update lower UID */ | |
633 seq = ibox->index->get_sequence(ibox->index, rec); | |
634 if (seq < *first_seq) | |
635 *first_seq = seq; | |
636 | |
637 /* update higher UID .. except we don't really | |
638 know it and it'd be uselessly slow to find it. | |
639 use a kludgy method which might limit the | |
640 sequences. */ | |
641 seq += last_uid-first_uid; | |
642 if (seq >= ibox->synced_messages_count) | |
643 seq = ibox->synced_messages_count; | |
644 | |
645 if (seq > *last_seq) | |
646 *last_seq = seq; | |
647 } | |
648 } | |
649 | |
650 if (*first_seq == 0) | |
651 *first_seq = 1; | |
652 if (*last_seq == 0) | |
653 *last_seq = ibox->synced_messages_count; | |
51 | 654 |
66 | 655 i_assert(*first_seq <= *last_seq); |
0 | 656 } |
657 | |
658 static void search_messages(IndexMailbox *ibox, MailSearchArg *args, | |
659 IOBuffer *outbuf, int uid_result) | |
660 { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
661 SearchIndexContext ctx; |
0 | 662 MailIndexRecord *rec; |
663 unsigned int first_seq, last_seq, seq; | |
664 char num[MAX_INT_STRLEN+10]; | |
665 | |
51 | 666 if (ibox->synced_messages_count == 0) |
667 return; | |
668 | |
0 | 669 /* see if we can limit the records we look at */ |
670 search_get_sequences(ibox, args, &first_seq, &last_seq); | |
671 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
672 ctx.ibox = ibox; |
0 | 673 rec = ibox->index->lookup(ibox->index, first_seq); |
674 for (seq = first_seq; rec != NULL && seq <= last_seq; seq++) { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
675 ctx.rec = rec; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
676 ctx.seq = seq; |
0 | 677 |
678 mail_search_args_reset(args); | |
679 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
680 mail_search_args_foreach(args, search_index_arg, &ctx); |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
681 mail_search_args_foreach(args, search_cached_arg, &ctx); |
160
ff05b320482c
Bigger changes.. full_virtual_size was removed from index record and
Timo Sirainen <tss@iki.fi>
parents:
119
diff
changeset
|
682 mail_search_args_foreach(args, search_slow_arg, &ctx); |
0 | 683 |
684 if (search_arg_match_text(ibox, rec, args) && | |
685 args->result == 1) { | |
686 i_snprintf(num, sizeof(num), " %u", | |
687 uid_result ? rec->uid : seq); | |
688 io_buffer_send(outbuf, num, strlen(num)); | |
689 } | |
690 rec = ibox->index->next(ibox->index, rec); | |
691 } | |
692 } | |
693 | |
694 int index_storage_search(Mailbox *box, MailSearchArg *args, | |
695 IOBuffer *outbuf, int uid_result) | |
696 { | |
697 IndexMailbox *ibox = (IndexMailbox *) box; | |
698 | |
699 if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_SHARED)) | |
51 | 700 return mail_storage_set_index_error(ibox); |
701 | |
702 io_buffer_send(outbuf, "* SEARCH", 8); | |
703 search_messages(ibox, args, outbuf, uid_result); | |
704 io_buffer_send(outbuf, "\r\n", 2); | |
0 | 705 |
51 | 706 if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK)) |
707 return mail_storage_set_index_error(ibox); | |
0 | 708 |
51 | 709 return TRUE; |
0 | 710 } |