Mercurial > dovecot > core-2.2
annotate src/lib-storage/index/index-fetch-section.c @ 395:8d3bfd8bc032 HEAD
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
headers larger than 32kB we now scan the header data twice instead of saving
anything to memory.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 09 Oct 2002 19:04:39 +0300 |
parents | d037915978ca |
children | f3ab97771ed8 |
rev | line source |
---|---|
0 | 1 /* Copyright (C) 2002 Timo Sirainen */ |
2 | |
3 #include "lib.h" | |
4 #include "temp-string.h" | |
5 #include "iobuffer.h" | |
6 #include "rfc822-tokenize.h" | |
12
a4423c83b2b0
moved lib-imap/imap-message-send.* into lib-mail/message-send.*
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
7 #include "message-send.h" |
0 | 8 #include "index-storage.h" |
9 #include "index-fetch.h" | |
10 | |
11 #include <ctype.h> | |
12 #include <unistd.h> | |
13 | |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
14 /* For FETCH[HEADER.FIELDS*] we need to modify the header data before sending |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
15 it. We can either save it in memory and then send it, or we can parse it |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
16 twice, first calculating the size and then send it. This value specifies |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
17 the maximum amount of memory we allow to allocate before using |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
18 double-parsing. */ |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
19 #define MAX_HEADER_BUFFER_SIZE (32*1024) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
20 |
0 | 21 ImapCacheField index_fetch_body_get_cache(const char *section) |
22 { | |
23 if (*section >= '0' && *section <= '9') | |
24 return IMAP_CACHE_MESSAGE_PART | IMAP_CACHE_MESSAGE_OPEN; | |
25 | |
26 if (*section == '\0' || strcasecmp(section, "TEXT") == 0) { | |
27 /* no IMAP_CACHE_MESSAGE_BODY_SIZE, so that we don't | |
28 uselessly check it when we want to read partial data */ | |
29 return IMAP_CACHE_MESSAGE_OPEN; | |
30 } | |
31 | |
32 if (strncasecmp(section, "HEADER", 6) == 0 || | |
33 strcasecmp(section, "MIME") == 0) | |
34 return IMAP_CACHE_MESSAGE_HDR_SIZE | IMAP_CACHE_MESSAGE_OPEN; | |
35 | |
36 /* error */ | |
37 return 0; | |
38 } | |
39 | |
40 /* fetch BODY[] or BODY[TEXT] */ | |
41 static int fetch_body(MailIndexRecord *rec, MailFetchBodyData *sect, | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
42 FetchContext *ctx, const char *prefix, int fetch_header) |
0 | 43 { |
44 MessageSize size; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
45 IOBuffer *inbuf; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
46 const char *str; |
0 | 47 |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
48 if (!imap_msgcache_get_rfc822_partial(ctx->cache, sect->skip, |
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
49 sect->max_size, fetch_header, |
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
50 &size, &inbuf)) { |
0 | 51 i_error("Couldn't get BODY[] for UID %u (index %s)", |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
52 rec->uid, ctx->index->filepath); |
0 | 53 return FALSE; |
54 } | |
55 | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
56 str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
57 prefix, size.virtual_size); |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
58 if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
59 return FALSE; |
0 | 60 |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
61 return message_send(ctx->outbuf, inbuf, &size, 0, sect->max_size); |
0 | 62 } |
63 | |
64 static char *const *get_fields_array(const char *fields) | |
65 { | |
66 char **field_list, **field; | |
67 | |
68 while (*fields == ' ') | |
69 fields++; | |
70 if (*fields == '(') | |
71 fields++; | |
72 | |
73 field_list = (char **) t_strsplit(fields, " )"); | |
74 | |
75 /* array ends at ")" element */ | |
76 for (field = field_list; *field != NULL; field++) { | |
77 if (strcasecmp(*field, ")") == 0) | |
78 *field = NULL; | |
79 } | |
80 | |
81 return field_list; | |
82 } | |
83 | |
184 | 84 static int header_match(char *const *fields, const char *name, size_t size) |
0 | 85 { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
86 const char *field, *name_start, *name_end; |
0 | 87 |
369
d037915978ca
message_parse_header() now calls the function with empty name/value at end
Timo Sirainen <tss@iki.fi>
parents:
326
diff
changeset
|
88 if (size == 0) |
d037915978ca
message_parse_header() now calls the function with empty name/value at end
Timo Sirainen <tss@iki.fi>
parents:
326
diff
changeset
|
89 return FALSE; |
0 | 90 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
91 name_start = name; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
92 name_end = name + size; |
0 | 93 |
94 for (; *fields != NULL; fields++) { | |
95 field = *fields; | |
96 if (*field == '\0') | |
97 continue; | |
98 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
99 for (name = name_start; name != name_end; name++) { |
0 | 100 /* field has been uppercased long time ago while |
101 parsing FETCH command */ | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
102 if (i_toupper(*name) != *field) |
0 | 103 break; |
104 | |
105 field++; | |
106 if (*field == '\0') { | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
107 if (name+1 == name_end) |
0 | 108 return TRUE; |
109 break; | |
110 } | |
111 } | |
112 } | |
113 | |
114 return FALSE; | |
115 } | |
116 | |
184 | 117 static int header_match_not(char *const *fields, const char *name, size_t size) |
0 | 118 { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
119 return !header_match(fields, name, size); |
0 | 120 } |
121 | |
122 static int header_match_mime(char *const *fields __attr_unused__, | |
184 | 123 const char *name, size_t size) |
0 | 124 { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
125 if (size > 8 && strncasecmp(name, "Content-", 8) == 0) |
0 | 126 return TRUE; |
127 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
128 if (size == 12 && strncasecmp(name, "Mime-Version", 13) == 0) |
0 | 129 return TRUE; |
130 | |
131 return FALSE; | |
132 } | |
133 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
134 typedef struct { |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
135 TempString *dest; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
136 IOBuffer *outbuf; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
137 uoff_t dest_size; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
138 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
139 uoff_t skip, max_size; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
140 char *const *fields; |
184 | 141 int (*match_func) (char *const *, const char *, size_t); |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
142 } FetchHeaderFieldContext; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
143 |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
144 static int fetch_header_append(FetchHeaderFieldContext *ctx, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
145 const char *str, size_t size) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
146 { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
147 if (ctx->skip > 0) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
148 if (ctx->skip >= size) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
149 ctx->skip -= size; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
150 return TRUE; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
151 } |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
152 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
153 str += ctx->skip; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
154 size -= ctx->skip; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
155 ctx->skip = 0; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
156 } |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
157 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
158 if (ctx->dest_size + size > ctx->max_size) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
159 i_assert(ctx->dest_size <= ctx->max_size); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
160 size = ctx->max_size - ctx->dest_size; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
161 } |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
162 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
163 if (ctx->dest != NULL) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
164 t_string_append_n(ctx->dest, str, size); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
165 ctx->dest_size += size; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
166 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
167 if (ctx->outbuf != NULL) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
168 if (io_buffer_send(ctx->outbuf, str, size) < 0) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
169 return FALSE; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
170 } |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
171 return ctx->dest_size < ctx->max_size; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
172 } |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
173 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
174 static void fetch_header_field(MessagePart *part __attr_unused__, |
184 | 175 const char *name, size_t name_len, |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
176 const char *value __attr_unused__, |
184 | 177 size_t value_len __attr_unused__, |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
178 void *context) |
0 | 179 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
180 FetchHeaderFieldContext *ctx = context; |
152
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
181 const char *field_start, *field_end, *cr, *p; |
0 | 182 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
183 /* see if we want this field */ |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
184 if (!ctx->match_func(ctx->fields, name, name_len)) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
185 return; |
0 | 186 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
187 /* add the field, inserting CRs when needed. FIXME: is this too |
152
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
188 kludgy? we assume name continues with ": value".. */ |
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
189 field_start = name; |
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
190 field_end = value + value_len; |
0 | 191 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
192 cr = NULL; |
152
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
193 for (p = field_start; p != field_end; p++) { |
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
194 if (*p == '\r') |
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
195 cr = p; |
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
196 else if (*p == '\n' && cr != p-1) { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
197 /* missing CR */ |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
198 if (!fetch_header_append(ctx, field_start, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
199 (size_t) (p-field_start))) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
200 return; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
201 if (!fetch_header_append(ctx, "\r\n", 2)) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
202 return; |
0 | 203 |
152
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
204 field_start = p+1; |
0 | 205 } |
206 } | |
207 | |
152
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
208 if (field_start != field_end) { |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
209 if (!fetch_header_append(ctx, field_start, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
210 (size_t) (field_end-field_start))) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
211 return; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
212 } |
152
7e1f18c5d708
FETCH BODY[HEADER.FIELDS ...] wasn't working
Timo Sirainen <tss@iki.fi>
parents:
111
diff
changeset
|
213 |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
214 (void)fetch_header_append(ctx, "\r\n", 2); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
215 } |
0 | 216 |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
217 static int fetch_header_fields(IOBuffer *inbuf, const char *section, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
218 FetchHeaderFieldContext *ctx) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
219 { |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
220 if (strncasecmp(section, "HEADER.FIELDS ", 14) == 0) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
221 ctx->fields = get_fields_array(section + 14); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
222 ctx->match_func = header_match; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
223 } else if (strncasecmp(section, "HEADER.FIELDS.NOT ", 18) == 0) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
224 ctx->fields = get_fields_array(section + 18); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
225 ctx->match_func = header_match_not; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
226 } else if (strcasecmp(section, "MIME") == 0) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
227 /* Mime-Version + Content-* fields */ |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
228 ctx->match_func = header_match_mime; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
229 } else { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
230 /* invalid section given by user - FIXME: tell user about it */ |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
231 return FALSE; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
232 } |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
233 |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
234 ctx->dest_size = 0; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
235 message_parse_header(NULL, inbuf, NULL, fetch_header_field, ctx); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
236 |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
237 i_assert(ctx->dest_size <= ctx->max_size); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
238 i_assert(ctx->dest == NULL || ctx->dest->len == ctx->dest_size); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
239 return TRUE; |
0 | 240 } |
241 | |
242 /* fetch wanted headers from given data */ | |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
243 static int fetch_header_from(IOBuffer *inbuf, IOBuffer *outbuf, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
244 const char *prefix, MessageSize *size, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
245 const char *section, MailFetchBodyData *sect) |
0 | 246 { |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
247 FetchHeaderFieldContext ctx; |
0 | 248 const char *str; |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
249 uoff_t start_offset; |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
250 int failed; |
0 | 251 |
252 /* HEADER, MIME, HEADER.FIELDS (list), HEADER.FIELDS.NOT (list) */ | |
253 | |
254 if (strcasecmp(section, "HEADER") == 0) { | |
255 /* all headers */ | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
256 str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
257 prefix, size->virtual_size); |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
258 if (io_buffer_send(outbuf, str, strlen(str)) < 0) |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
259 return FALSE; |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
260 return message_send(outbuf, inbuf, size, |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
261 sect->skip, sect->max_size); |
0 | 262 } |
263 | |
264 /* partial headers - copy the wanted fields into temporary memory. | |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
265 Insert missing CRs on the way. If the header is too large, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
266 calculate the size first and then send the data directly to |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
267 output buffer. */ |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
268 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
269 memset(&ctx, 0, sizeof(ctx)); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
270 ctx.skip = sect->skip; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
271 ctx.max_size = sect->max_size; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
272 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
273 failed = FALSE; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
274 start_offset = inbuf->offset; |
184 | 275 |
0 | 276 t_push(); |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
277 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
278 /* first pass, we need at least the size */ |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
279 if (size->virtual_size > MAX_HEADER_BUFFER_SIZE && |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
280 sect->max_size > MAX_HEADER_BUFFER_SIZE) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
281 if (!fetch_header_fields(inbuf, section, &ctx)) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
282 failed = TRUE; |
0 | 283 |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
284 i_assert(ctx.dest_size <= size->virtual_size); |
0 | 285 } else { |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
286 ctx.dest = t_string_new(size->virtual_size < 4096 ? |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
287 size->virtual_size : 4096); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
288 if (!fetch_header_fields(inbuf, section, &ctx)) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
289 failed = TRUE; |
0 | 290 } |
291 | |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
292 if (!failed) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
293 str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
294 prefix, ctx.dest_size); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
295 if (io_buffer_send(outbuf, str, strlen(str)) < 0) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
296 failed = TRUE; |
0 | 297 } |
298 | |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
299 if (!failed) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
300 if (ctx.dest == NULL) { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
301 /* second pass, write the data to output buffer */ |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
302 uoff_t first_size = ctx.dest_size; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
303 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
304 ctx.outbuf = outbuf; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
305 if (!io_buffer_seek(inbuf, start_offset)) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
306 failed = TRUE; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
307 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
308 if (!failed && |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
309 !fetch_header_fields(inbuf, section, &ctx)) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
310 failed = TRUE; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
311 |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
312 i_assert(first_size == ctx.dest_size); |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
313 } else { |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
314 if (io_buffer_send(outbuf, ctx.dest->str, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
315 ctx.dest->len) < 0) |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
316 failed = TRUE; |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
317 } |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
318 } |
0 | 319 |
320 t_pop(); | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
321 return !failed; |
0 | 322 } |
323 | |
324 /* fetch BODY[HEADER...] */ | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
325 static int fetch_header(MailFetchBodyData *sect, FetchContext *ctx, |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
326 const char *prefix) |
0 | 327 { |
328 MessageSize hdr_size; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
329 IOBuffer *inbuf; |
0 | 330 |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
331 if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, &hdr_size, NULL)) |
0 | 332 return FALSE; |
333 | |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
334 return fetch_header_from(inbuf, ctx->outbuf, prefix, &hdr_size, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
335 sect->section, sect); |
0 | 336 } |
337 | |
338 /* Find MessagePart for section (eg. 1.3.4) */ | |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
339 static MessagePart *part_find(MailFetchBodyData *sect, FetchContext *ctx, |
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
340 const char **section) |
0 | 341 { |
342 MessagePart *part; | |
343 const char *path; | |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
12
diff
changeset
|
344 unsigned int num; |
0 | 345 |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
346 part = imap_msgcache_get_parts(ctx->cache); |
0 | 347 |
348 path = sect->section; | |
349 while (*path >= '0' && *path <= '9' && part != NULL) { | |
350 /* get part number */ | |
351 num = 0; | |
352 while (*path != '\0' && *path != '.') { | |
353 if (*path < '0' || *path > '9') | |
354 return NULL; | |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
12
diff
changeset
|
355 num = num*10 + (*path - '0'); |
0 | 356 path++; |
357 } | |
358 | |
359 if (*path == '.') | |
360 path++; | |
361 | |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
362 if (part->flags & MESSAGE_PART_FLAG_MULTIPART) { |
0 | 363 /* find the part */ |
364 part = part->children; | |
365 for (; num > 1 && part != NULL; num--) | |
366 part = part->next; | |
367 } else { | |
368 /* only 1 allowed with non-multipart messages */ | |
369 if (num != 1) | |
370 return NULL; | |
371 } | |
372 } | |
373 | |
374 *section = path; | |
375 return part; | |
376 } | |
377 | |
378 /* fetch BODY[1.2] or BODY[1.2.TEXT] */ | |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
379 static int fetch_part_body(MessagePart *part, MailFetchBodyData *sect, |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
380 FetchContext *ctx, const char *prefix) |
0 | 381 { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
382 IOBuffer *inbuf; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
383 const char *str; |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
12
diff
changeset
|
384 uoff_t skip_pos; |
0 | 385 |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
386 if (!imap_msgcache_get_data(ctx->cache, &inbuf)) |
0 | 387 return FALSE; |
388 | |
389 /* jump to beginning of wanted data */ | |
105
31034993473c
there was no need for MessagePart->pos.virtual_pos, so removed it.
Timo Sirainen <tss@iki.fi>
parents:
50
diff
changeset
|
390 skip_pos = part->physical_pos + part->header_size.physical_size; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
391 io_buffer_skip(inbuf, skip_pos); |
0 | 392 |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
393 str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
394 prefix, part->body_size.virtual_size); |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
395 if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
396 return FALSE; |
0 | 397 |
398 /* FIXME: potential performance problem with big messages: | |
399 FETCH BODY[1]<100000..1024>, hopefully no clients do this */ | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
400 return message_send(ctx->outbuf, inbuf, &part->body_size, |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
401 sect->skip, sect->max_size); |
0 | 402 } |
403 | |
404 /* fetch BODY[1.2.MIME|HEADER...] */ | |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
405 static int fetch_part_header(MessagePart *part, const char *section, |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
406 MailFetchBodyData *sect, FetchContext *ctx, |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
407 const char *prefix) |
0 | 408 { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
409 IOBuffer *inbuf; |
0 | 410 |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
411 if (!imap_msgcache_get_data(ctx->cache, &inbuf)) |
0 | 412 return FALSE; |
413 | |
105
31034993473c
there was no need for MessagePart->pos.virtual_pos, so removed it.
Timo Sirainen <tss@iki.fi>
parents:
50
diff
changeset
|
414 io_buffer_skip(inbuf, part->physical_pos); |
395
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
415 return fetch_header_from(inbuf, ctx->outbuf, prefix, &part->header_size, |
8d3bfd8bc032
FETCH BODY[HEADER.FIELDS*] is handled now better for huge headers. For
Timo Sirainen <tss@iki.fi>
parents:
369
diff
changeset
|
416 section, sect); |
0 | 417 } |
418 | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
419 static int fetch_part(MailFetchBodyData *sect, FetchContext *ctx, |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
420 const char *prefix) |
0 | 421 { |
422 MessagePart *part; | |
423 const char *section; | |
424 | |
106
5fe3e04ca8d9
Added support for caching of MessagePart data. This is useful for fetching
Timo Sirainen <tss@iki.fi>
parents:
105
diff
changeset
|
425 part = part_find(sect, ctx, §ion); |
0 | 426 if (part == NULL) |
427 return FALSE; | |
428 | |
429 if (*section == '\0' || strcasecmp(section, "TEXT") == 0) | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
430 return fetch_part_body(part, sect, ctx, prefix); |
0 | 431 |
432 if (strncasecmp(section, "HEADER", 6) == 0) | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
433 return fetch_part_header(part, section, sect, ctx, prefix); |
0 | 434 if (strcasecmp(section, "MIME") == 0) |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
435 return fetch_part_header(part, section, sect, ctx, prefix); |
0 | 436 |
437 return FALSE; | |
438 } | |
439 | |
326 | 440 int index_fetch_body_section(MailIndexRecord *rec, MailFetchBodyData *sect, |
441 FetchContext *ctx) | |
0 | 442 { |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
443 const char *prefix; |
0 | 444 |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
445 prefix = !sect->skip_set ? |
227 | 446 t_strdup_printf(" BODY[%s]", sect->section) : |
447 t_strdup_printf(" BODY[%s]<%"PRIuUOFF_T">", | |
184 | 448 sect->section, sect->skip); |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
449 if (ctx->first) { |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
450 prefix++; ctx->first = FALSE; |
0 | 451 } |
452 | |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
453 if (*sect->section == '\0') |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
454 return fetch_body(rec, sect, ctx, prefix, TRUE); |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
455 if (strcasecmp(sect->section, "TEXT") == 0) |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
456 return fetch_body(rec, sect, ctx, prefix, FALSE); |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
457 if (strncasecmp(sect->section, "HEADER", 6) == 0) |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
458 return fetch_header(sect, ctx, prefix); |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
459 if (*sect->section >= '0' && *sect->section <= '9') |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
460 return fetch_part(sect, ctx, prefix); |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
461 |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
462 /* FIXME: point the error to user */ |
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
463 return FALSE; |
0 | 464 } |