header.c header0.h rfc822.c
collpase everything in header.c
Showing
6 changed files
with
3 additions
and
591 deletions
mailbox/header.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include "config.h" | ||
21 | #endif | ||
22 | |||
23 | #include <header0.h> | ||
24 | #include <string.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <errno.h> | ||
27 | |||
28 | int | ||
29 | header_init (header_t *ph, const char *blurb, size_t len, | ||
30 | int flag, void *owner) | ||
31 | { | ||
32 | if (flag != MU_HEADER_RFC822) | ||
33 | return ENOTSUP; | ||
34 | return rfc822_init (ph, blurb, len, owner); | ||
35 | } | ||
36 | |||
37 | void | ||
38 | header_destroy (header_t *ph, void *owner) | ||
39 | { | ||
40 | if (ph && *ph) | ||
41 | (*ph)->_destroy (ph, owner); | ||
42 | } | ||
43 | |||
44 | /* stub functions */ | ||
45 | int | ||
46 | header_set_value (header_t h, const char *fn, const char *fb, size_t n, | ||
47 | int replace) | ||
48 | { | ||
49 | if (h == NULL || h->_set_value == NULL) | ||
50 | return EINVAL; | ||
51 | return h->_set_value (h, fn, fb, n, replace); | ||
52 | } | ||
53 | |||
54 | int | ||
55 | header_get_value (header_t h, const char *fn, char *fb, | ||
56 | size_t len, size_t *n) | ||
57 | { | ||
58 | if (h == NULL || h->_get_value == NULL ) | ||
59 | return EINVAL; | ||
60 | return h->_get_value (h, fn, fb, len, n); | ||
61 | } | ||
62 | |||
63 | int | ||
64 | header_entry_name (header_t h, size_t num, char *buf, size_t len, size_t *n) | ||
65 | { | ||
66 | if (h == NULL || h->_entry_name == NULL) | ||
67 | return EINVAL; | ||
68 | |||
69 | return h->_entry_name (h, num, buf, len, n); | ||
70 | } | ||
71 | |||
72 | int | ||
73 | header_entry_value (header_t h, size_t num, char *buf, size_t len, size_t *n) | ||
74 | { | ||
75 | if (h == NULL || h->_entry_value == NULL) | ||
76 | return EINVAL; | ||
77 | |||
78 | return h->_entry_value (h, num, buf, len, n); | ||
79 | } | ||
80 | |||
81 | int | ||
82 | header_entry_count (header_t h, size_t *num) | ||
83 | { | ||
84 | if (h == NULL || h->_entry_count) | ||
85 | return EINVAL; | ||
86 | return h->_entry_count (h, num); | ||
87 | } | ||
88 | |||
89 | int | ||
90 | header_get_istream (header_t h, istream_t *pis) | ||
91 | { | ||
92 | if (h == NULL || pis == NULL || h->_get_istream == NULL) | ||
93 | return EINVAL; | ||
94 | return h->_get_istream (h, pis); | ||
95 | } | ||
96 | |||
97 | int | ||
98 | header_get_ostream (header_t h, ostream_t *pos) | ||
99 | { | ||
100 | if (h == NULL || pos == NULL || h->_get_ostream == NULL) | ||
101 | return EINVAL; | ||
102 | return h->_get_ostream (h, pos); | ||
103 | } |
... | @@ -33,8 +33,6 @@ | ... | @@ -33,8 +33,6 @@ |
33 | extern "C" { | 33 | extern "C" { |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #define MU_HEADER_RFC822 0 | ||
37 | |||
38 | #define MU_HEADER_UNIX_FROM "From " | 36 | #define MU_HEADER_UNIX_FROM "From " |
39 | #define MU_HEADER_RETURN_PATH "Return-Path" | 37 | #define MU_HEADER_RETURN_PATH "Return-Path" |
40 | #define MU_HEADER_RECEIVED "Received" | 38 | #define MU_HEADER_RECEIVED "Received" |
... | @@ -69,7 +67,7 @@ struct _header; | ... | @@ -69,7 +67,7 @@ struct _header; |
69 | typedef struct _header * header_t; | 67 | typedef struct _header * header_t; |
70 | 68 | ||
71 | extern int header_init __P ((header_t *, const char *blurb, | 69 | extern int header_init __P ((header_t *, const char *blurb, |
72 | size_t ln, int flag, void *owner)); | 70 | size_t ln, void *owner)); |
73 | extern void header_destroy __P ((header_t *, void *owner)); | 71 | extern void header_destroy __P ((header_t *, void *owner)); |
74 | 72 | ||
75 | extern int header_set_value __P ((header_t, const char *fn, | 73 | extern int header_set_value __P ((header_t, const char *fn, | ... | ... |
mailbox/header0.h
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Library General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifndef _HEADER0_H | ||
19 | #define _HEADER0_H | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | #include <header.h> | ||
23 | #include <io0.h> | ||
24 | |||
25 | #ifndef __P | ||
26 | #ifdef __STDC__ | ||
27 | #define __P(args) args | ||
28 | #else | ||
29 | #define __P(args) () | ||
30 | #endif | ||
31 | #endif /*__P */ | ||
32 | |||
33 | #ifdef _cpluscplus | ||
34 | extern "C" { | ||
35 | #endif | ||
36 | |||
37 | struct _hdr | ||
38 | { | ||
39 | char *fn; | ||
40 | char *fn_end; | ||
41 | char *fv; | ||
42 | char *fv_end; | ||
43 | }; | ||
44 | typedef struct _hdr *hdr_t; | ||
45 | |||
46 | struct _header | ||
47 | { | ||
48 | size_t num; | ||
49 | /* Data */ | ||
50 | void *data; | ||
51 | /* streams */ | ||
52 | istream_t is; | ||
53 | ostream_t os; | ||
54 | |||
55 | /* owner ? */ | ||
56 | void *owner; | ||
57 | int ref_count; | ||
58 | |||
59 | /* Functions */ | ||
60 | int (*_init) __P ((header_t *, const char *, size_t, void *owner)); | ||
61 | void (*_destroy) __P ((header_t *, void *owner)); | ||
62 | int (*_set_value) __P ((header_t, const char *fn, const char *fv, | ||
63 | size_t n, int replace)); | ||
64 | int (*_get_value) __P ((header_t, const char *fn, char *fv, | ||
65 | size_t len, size_t *n)); | ||
66 | int (*_entry_count) __P ((header_t, size_t *)); | ||
67 | int (*_entry_name) __P ((header_t, size_t num, char *buf, | ||
68 | size_t buflen, size_t *nwritten)); | ||
69 | int (*_entry_value) __P ((header_t, size_t num, char *buf, | ||
70 | size_t buflen, size_t *nwritten)); | ||
71 | int (*_get_istream) __P ((header_t h, istream_t *is)); | ||
72 | int (*_get_ostream) __P ((header_t h, ostream_t *os)); | ||
73 | int (*_parse) __P ((header_t, const char *blurb, size_t len)); | ||
74 | }; | ||
75 | |||
76 | /* rfc822 */ | ||
77 | extern int rfc822_init __P ((header_t *ph, const char *blurb, | ||
78 | size_t len, void *owner)); | ||
79 | extern void rfc822_destroy __P ((header_t *ph, void *owner)); | ||
80 | |||
81 | #ifdef _cpluscplus | ||
82 | } | ||
83 | #endif | ||
84 | |||
85 | #endif /* HEADER0_H */ |
... | @@ -1318,8 +1318,7 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1318,8 +1318,7 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1318 | } | 1318 | } |
1319 | 1319 | ||
1320 | /* set the header */ | 1320 | /* set the header */ |
1321 | if ((status = header_init (&header, pbuf, | 1321 | if ((status = header_init (&header, pbuf, offset, mum)) != 0 || |
1322 | offset, MU_HEADER_RFC822, mum)) != 0 || | ||
1323 | (status = message_set_header (msg, header, mum)) != 0) | 1322 | (status = message_set_header (msg, header, mum)) != 0) |
1324 | { | 1323 | { |
1325 | free (pbuf); | 1324 | free (pbuf); | ... | ... |
... | @@ -74,7 +74,7 @@ int message_clone (message_t omsg, message_t *pmsg) | ... | @@ -74,7 +74,7 @@ int message_clone (message_t omsg, message_t *pmsg) |
74 | } while (nread > 0); | 74 | } while (nread > 0); |
75 | 75 | ||
76 | 76 | ||
77 | status = header_init (&header, pbuf, offset, MU_HEADER_RFC822, NULL); | 77 | status = header_init (&header, pbuf, offset, NULL); |
78 | if (status != 0) | 78 | if (status != 0) |
79 | { | 79 | { |
80 | free (pbuf); | 80 | free (pbuf); | ... | ... |
mailbox/rfc822.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include "config.h" | ||
21 | #endif | ||
22 | |||
23 | #include <header0.h> | ||
24 | #include <string.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <errno.h> | ||
27 | |||
28 | static int rfc822_parse (header_t h, const char *blurb, size_t len); | ||
29 | static int rfc822_set_value (header_t h, const char *fn, const char *fb, | ||
30 | size_t n, int replace); | ||
31 | static int rfc822_get_value (header_t h, const char *fn, char *fb, | ||
32 | size_t len, size_t *n); | ||
33 | static int rfc822_entry_count (header_t, size_t *num); | ||
34 | static int rfc822_entry_name (header_t h, size_t num, char *buf, | ||
35 | size_t buflen, size_t *total); | ||
36 | static int rfc822_entry_value (header_t h, size_t num, char *buf, | ||
37 | size_t buflen, size_t *total); | ||
38 | static int rfc822_get_istream (header_t h, istream_t *pis); | ||
39 | static int rfc822_get_ostream (header_t h, ostream_t *pos); | ||
40 | static int rfc822_read (istream_t is, char *buf, size_t buflen, | ||
41 | off_t off, ssize_t *pnread); | ||
42 | |||
43 | struct _rfc822 | ||
44 | { | ||
45 | char *blurb; | ||
46 | size_t blurb_len; | ||
47 | size_t hdr_count; | ||
48 | struct _hdr *hdr; | ||
49 | }; | ||
50 | |||
51 | typedef struct _rfc822 * rfc822_t; | ||
52 | |||
53 | |||
54 | int | ||
55 | rfc822_init (header_t *ph, const char *blurb, size_t len, void *owner) | ||
56 | { | ||
57 | header_t h; | ||
58 | int status; | ||
59 | h = calloc (1, sizeof (*h)); | ||
60 | if (h == NULL) | ||
61 | return ENOMEM; | ||
62 | h->owner = owner; | ||
63 | h->_init = rfc822_init; | ||
64 | h->_destroy = rfc822_destroy; | ||
65 | h->_parse = rfc822_parse; | ||
66 | h->_get_value = rfc822_get_value; | ||
67 | h->_set_value = rfc822_set_value; | ||
68 | h->_entry_count = rfc822_entry_count; | ||
69 | h->_entry_name = rfc822_entry_name; | ||
70 | h->_entry_value = rfc822_entry_value; | ||
71 | h->_get_istream = rfc822_get_istream; | ||
72 | h->_get_ostream = rfc822_get_ostream; | ||
73 | |||
74 | status = h->_parse (h, blurb, len); | ||
75 | if (status != 0) | ||
76 | free (h); | ||
77 | *ph = h; | ||
78 | return status; | ||
79 | } | ||
80 | |||
81 | void | ||
82 | rfc822_destroy (header_t *ph, void *owner) | ||
83 | { | ||
84 | if (ph && *ph) | ||
85 | { | ||
86 | header_t h = *ph; | ||
87 | |||
88 | /* if destroy is call always decremente */ | ||
89 | h->ref_count--; | ||
90 | |||
91 | /* can we destroy ? */ | ||
92 | if ((h->owner && h->owner == owner) || | ||
93 | (h->owner == NULL && h->ref_count <= 0)) | ||
94 | { | ||
95 | /* io */ | ||
96 | istream_destroy (&(h->is), owner); | ||
97 | ostream_destroy (&(h->os), owner); | ||
98 | |||
99 | if (h->data) | ||
100 | { | ||
101 | rfc822_t rfc = (rfc822_t)h->data; | ||
102 | free (rfc->hdr); | ||
103 | free (rfc->blurb); | ||
104 | free (rfc); | ||
105 | } | ||
106 | free (h); | ||
107 | } | ||
108 | *ph = NULL; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Parsing is done in a rather simple fashion. | ||
114 | * meaning we just consider an entry to be | ||
115 | * a field-name an a field-value. So they | ||
116 | * maybe duplicate of field-name like "Received" | ||
117 | * they are just put in the array, see _get_value() | ||
118 | * on how to handle the case. | ||
119 | */ | ||
120 | static int | ||
121 | rfc822_parse (header_t h, const char *blurb, size_t len) | ||
122 | { | ||
123 | rfc822_t rfc; | ||
124 | char *header_end; | ||
125 | char *header_start; | ||
126 | char *header_start2; | ||
127 | struct _hdr *hdr; | ||
128 | |||
129 | if (h == NULL || blurb == NULL || len == 0) | ||
130 | return EINVAL; | ||
131 | |||
132 | rfc = calloc (1, sizeof (*rfc)); | ||
133 | if (rfc == NULL) | ||
134 | return ENOMEM; | ||
135 | |||
136 | rfc->blurb = calloc (1, len); | ||
137 | if (rfc->blurb == NULL) | ||
138 | { | ||
139 | free (rfc); | ||
140 | return ENOMEM; | ||
141 | } | ||
142 | rfc->blurb_len = len; | ||
143 | memcpy (rfc->blurb, blurb, len); | ||
144 | |||
145 | for (header_start = rfc->blurb;; header_start = ++header_end) | ||
146 | { | ||
147 | /* get a header, a header is : | ||
148 | * field-name ':' ' ' field-value '\r' '\n' | ||
149 | * [ (' ' | '\t') field-value '\r' '\n' ] | ||
150 | */ | ||
151 | for (header_start2 = header_start;;header_start2 = ++header_end) | ||
152 | { | ||
153 | header_end = memchr (header_start2, '\n', len); | ||
154 | if (header_end == NULL) | ||
155 | break; | ||
156 | else | ||
157 | { | ||
158 | len -= (header_end - header_start2 + 1); | ||
159 | if (len == 0) | ||
160 | { | ||
161 | header_end = NULL; | ||
162 | break; | ||
163 | } | ||
164 | if (header_end[1] != ' ' | ||
165 | && header_end[1] != '\t') | ||
166 | break; /* new header break the inner for */ | ||
167 | } | ||
168 | /* *header_end = ' '; smash LF */ | ||
169 | } | ||
170 | |||
171 | if (header_end == NULL) | ||
172 | break; /* bail out */ | ||
173 | |||
174 | hdr = realloc (rfc->hdr, (rfc->hdr_count + 1) * sizeof (*hdr)); | ||
175 | if (hdr == NULL) | ||
176 | { | ||
177 | free (rfc->blurb); | ||
178 | free (rfc->hdr); | ||
179 | free (rfc); | ||
180 | return ENOMEM; | ||
181 | } | ||
182 | rfc->hdr = hdr; | ||
183 | rfc->hdr_count++; | ||
184 | /* Treats unix "From " specially */ | ||
185 | if ((header_end - header_start >= 5) | ||
186 | && strncmp (header_start, "From ", 5) == 0) | ||
187 | { | ||
188 | rfc->hdr[rfc->hdr_count - 1].fn = header_start; | ||
189 | rfc->hdr[rfc->hdr_count - 1].fn_end = header_start + 6; | ||
190 | rfc->hdr[rfc->hdr_count - 1].fv = header_start + 6; | ||
191 | rfc->hdr[rfc->hdr_count - 1].fv_end = header_end; | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | char *colon = memchr (header_start, ':', header_end - header_start); | ||
196 | if (colon == NULL) | ||
197 | { | ||
198 | /* Houston we have a problem */ | ||
199 | free (rfc->blurb); | ||
200 | free (rfc->hdr); | ||
201 | free (rfc); | ||
202 | return EINVAL; | ||
203 | } | ||
204 | rfc->hdr[rfc->hdr_count - 1].fn = header_start; | ||
205 | rfc->hdr[rfc->hdr_count - 1].fn_end = colon; | ||
206 | /* skip leading spaces */ | ||
207 | while (*(++colon) == ' '); | ||
208 | rfc->hdr[rfc->hdr_count - 1].fv = colon; | ||
209 | rfc->hdr[rfc->hdr_count - 1].fv_end = header_end; | ||
210 | } | ||
211 | } | ||
212 | h->data = rfc; | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int | ||
217 | rfc822_set_value (header_t h, const char *fn, const char *fv, | ||
218 | size_t n, int replace) | ||
219 | { | ||
220 | (void)h; (void)fn; (void)fv; (void)n; (void)replace; | ||
221 | return ENOSYS; | ||
222 | } | ||
223 | |||
224 | static int | ||
225 | rfc822_get_value (header_t h, const char *name, char *buffer, | ||
226 | size_t buflen, size_t *n) | ||
227 | { | ||
228 | size_t i = 0; | ||
229 | size_t name_len; | ||
230 | size_t total = 0, fn_len = 0, fv_len = 0; | ||
231 | int threshold; | ||
232 | rfc822_t rfc; | ||
233 | |||
234 | if (h == NULL || name == NULL || | ||
235 | (rfc = (rfc822_t)h->data) == NULL) | ||
236 | return EINVAL; | ||
237 | |||
238 | /* we set the threshold to be 1 less for the null */ | ||
239 | threshold = --buflen; | ||
240 | |||
241 | /* | ||
242 | * Caution: We may have more then one value for a field | ||
243 | * name, for example a "Received" field-name is added by | ||
244 | * each passing MTA. The way that the parsing (_parse()) | ||
245 | * is done it's not take to account. So we just stuff in | ||
246 | * the buffer all the field-values to a corresponding field-name. | ||
247 | * FIXME: Should we kosher the output ? meaning replace | ||
248 | * occurences of " \t\r\n" for spaces ? for now we don't. | ||
249 | */ | ||
250 | for (name_len = strlen (name), i = 0; i < rfc->hdr_count; i++) | ||
251 | { | ||
252 | fn_len = rfc->hdr[i].fn_end - rfc->hdr[i].fn; | ||
253 | if (fn_len == name_len && memcmp (rfc->hdr[i].fn, name, fn_len) == 0) | ||
254 | { | ||
255 | fv_len = (rfc->hdr[i].fv_end - rfc->hdr[i].fv); | ||
256 | total += fv_len; | ||
257 | /* can everything fit in the buffer */ | ||
258 | if (buffer && threshold > 0) | ||
259 | { | ||
260 | threshold -= fv_len; | ||
261 | if (threshold > 0) | ||
262 | { | ||
263 | memcpy (buffer, rfc->hdr[i].fv, fv_len); | ||
264 | buffer += fv_len; | ||
265 | } | ||
266 | else if (threshold < 0) | ||
267 | { | ||
268 | threshold += fv_len; | ||
269 | memcpy (buffer, rfc->hdr[i].fv, threshold); | ||
270 | buffer += threshold; | ||
271 | threshold = 0; | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | if (buffer) | ||
277 | *buffer = '\0'; /* null terminated */ | ||
278 | if (n) | ||
279 | *n = total; | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int | ||
284 | rfc822_entry_count (header_t h, size_t *num) | ||
285 | { | ||
286 | rfc822_t rfc; | ||
287 | if (h == NULL || (rfc = (rfc822_t)h->data) == NULL) | ||
288 | return EINVAL; | ||
289 | if (num) | ||
290 | *num = rfc->hdr_count; | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int | ||
295 | rfc822_entry_name (header_t h, size_t num, char *buf, | ||
296 | size_t buflen, size_t *nwritten) | ||
297 | { | ||
298 | rfc822_t rfc; | ||
299 | size_t len; | ||
300 | if (h == NULL || (rfc = (rfc822_t)h->data) == NULL) | ||
301 | return EINVAL; | ||
302 | if (rfc->hdr_count == 0 || num > rfc->hdr_count) | ||
303 | return ENOENT; | ||
304 | len = rfc->hdr[num].fn_end - rfc->hdr[num].fn; | ||
305 | /* save one for the null */ | ||
306 | --buflen; | ||
307 | if (buf && buflen > 0) | ||
308 | { | ||
309 | buflen = (len > buflen) ? buflen : len; | ||
310 | memcpy (buf, rfc->hdr[num].fn, buflen); | ||
311 | buf[buflen] = '\0'; | ||
312 | } | ||
313 | if (nwritten) | ||
314 | *nwritten = len; | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int | ||
319 | rfc822_entry_value (header_t h, size_t num, char *buf, | ||
320 | size_t buflen, size_t *nwritten) | ||
321 | { | ||
322 | rfc822_t rfc; | ||
323 | size_t len; | ||
324 | if (h == NULL || (rfc = (rfc822_t)h->data) == NULL) | ||
325 | return EINVAL; | ||
326 | if (rfc->hdr_count == 0 || num > rfc->hdr_count) | ||
327 | return ENOENT; | ||
328 | len = rfc->hdr[num].fv_end - rfc->hdr[num].fv; | ||
329 | /* save one for the null */ | ||
330 | --buflen; | ||
331 | if (buf && buflen > 0) | ||
332 | { | ||
333 | buflen = (len > buflen) ? buflen : len; | ||
334 | memcpy (buf, rfc->hdr[num].fv, buflen); | ||
335 | buf[buflen] = '\0'; | ||
336 | } | ||
337 | if (nwritten) | ||
338 | *nwritten = len; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int | ||
343 | rfc822_read (istream_t is, char *buf, size_t buflen, | ||
344 | off_t off, ssize_t *pnread) | ||
345 | { | ||
346 | header_t h; | ||
347 | rfc822_t rfc = NULL; | ||
348 | ssize_t len; | ||
349 | |||
350 | if (is == NULL || (h = (header_t)is->owner) == NULL || | ||
351 | (rfc = (rfc822_t)h->data) == NULL) | ||
352 | return EINVAL; | ||
353 | |||
354 | len = rfc->blurb_len - off; | ||
355 | if ((rfc->blurb_len - off) > 0) | ||
356 | { | ||
357 | if (buf) | ||
358 | { | ||
359 | len = (buflen < (size_t)len) ? buflen : len; | ||
360 | memcpy (buf, rfc->blurb + off, len); | ||
361 | } | ||
362 | } | ||
363 | else | ||
364 | len = 0; | ||
365 | |||
366 | if (pnread) | ||
367 | *pnread = len; | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | int | ||
372 | rfc822_get_istream (header_t h, istream_t *pis) | ||
373 | { | ||
374 | int err; | ||
375 | if (h == NULL || pis == NULL) | ||
376 | return EINVAL; | ||
377 | /* already done */ | ||
378 | if (h->is) | ||
379 | *pis = h->is; | ||
380 | |||
381 | err = istream_init (&(h->is), rfc822_read, h->owner); | ||
382 | if (err != 0) | ||
383 | return err; | ||
384 | /* tell the world this is ours */ | ||
385 | h->is->owner = h; | ||
386 | h->is->_read = rfc822_read; | ||
387 | *pis = h->is; | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | int | ||
392 | rfc822_get_ostream (header_t h, ostream_t *pos) | ||
393 | { | ||
394 | if (h == NULL || pos == NULL) | ||
395 | return EINVAL; | ||
396 | return ENOSYS; | ||
397 | } |
-
Please register or sign in to post a comment