1 /*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * $Id: mhdriver_message.c,v 1.23 2008/02/17 13:13:26 hoa Exp $
34 */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #include "mhdriver_message.h"
41
42 #include "mailmessage_tools.h"
43 #include "mhdriver_tools.h"
44 #include "mhdriver.h"
45 #include "mailmh.h"
46
47 #ifdef HAVE_UNISTD_H
48 # include <unistd.h>
49 #endif
50 #ifdef HAVE_SYS_MMAN_H
51 # include <sys/mman.h>
52 #endif
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <fcntl.h>
56 #include <string.h>
57 #include <stdlib.h>
58
59 static int mh_prefetch(mailmessage * msg_info);
60
61 static void mh_prefetch_free(struct generic_message_t * msg);
62
63 static int mh_initialize(mailmessage * msg_info);
64
65 static int mh_fetch_size(mailmessage * msg_info,
66 size_t * result);
67
68 static int mh_fetch_header(mailmessage * msg_info,
69 char ** result,
70 size_t * result_len);
71
72 static mailmessage_driver local_mh_message_driver = {
73 /* msg_name */ "mh",
74
75 /* msg_initialize */ mh_initialize,
76 /* msg_uninitialize */ mailmessage_generic_uninitialize,
77
78 /* msg_flush */ mailmessage_generic_flush,
79 /* msg_check */ NULL,
80
81 /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free,
82
83 /* msg_fetch */ mailmessage_generic_fetch,
84 /* msg_fetch_header */ mh_fetch_header,
85 /* msg_fetch_body */ mailmessage_generic_fetch_body,
86 /* msg_fetch_size */ mh_fetch_size,
87 /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure,
88 /* msg_fetch_section */ mailmessage_generic_fetch_section,
89 /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header,
90 /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime,
91 /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body,
92 /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope,
93
94 /* msg_get_flags */ NULL
95 };
96
97 mailmessage_driver * mh_message_driver = &local_mh_message_driver;
98
mh_prefetch(mailmessage * msg_info)99 static int mh_prefetch(mailmessage * msg_info)
100 {
101 struct generic_message_t * msg;
102 int r;
103 char * msg_content;
104 size_t msg_length;
105
106 r = mhdriver_fetch_message(msg_info->msg_session, msg_info->msg_index,
107 &msg_content, &msg_length);
108 if (r != MAIL_NO_ERROR)
109 return r;
110
111 msg = msg_info->msg_data;
112
113 msg->msg_message = msg_content;
114 msg->msg_length = msg_length;
115
116 return MAIL_NO_ERROR;
117 }
118
mh_prefetch_free(struct generic_message_t * msg)119 static void mh_prefetch_free(struct generic_message_t * msg)
120 {
121 if (msg->msg_message != NULL) {
122 mmap_string_unref(msg->msg_message);
123 msg->msg_message = NULL;
124 }
125 }
126
get_data(mailmessage * msg)127 static inline struct mh_session_state_data * get_data(mailmessage * msg)
128 {
129 return msg->msg_session->sess_data;
130 }
131
get_mh_cur_folder(mailmessage * msg)132 static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg)
133 {
134 return get_data(msg)->mh_cur_folder;
135 }
136
mh_initialize(mailmessage * msg_info)137 static int mh_initialize(mailmessage * msg_info)
138 {
139 struct generic_message_t * msg;
140 int r;
141 char * uid;
142 char static_uid[PATH_MAX];
143 struct mailmh_msg_info * mh_msg_info;
144 chashdatum key;
145 chashdatum value;
146
147 key.data = &msg_info->msg_index;
148 key.len = sizeof(msg_info->msg_index);
149 r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value);
150 if (r < 0)
151 return MAIL_ERROR_INVAL;
152
153 mh_msg_info = value.data;
154
155 snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index,
156 (unsigned long) mh_msg_info->msg_mtime,
157 (unsigned long) mh_msg_info->msg_size);
158 uid = strdup(static_uid);
159 if (uid == NULL)
160 return MAIL_ERROR_MEMORY;
161
162 r = mailmessage_generic_initialize(msg_info);
163 if (r != MAIL_NO_ERROR) {
164 free(uid);
165 return r;
166 }
167
168 msg = msg_info->msg_data;
169 msg->msg_prefetch = mh_prefetch;
170 msg->msg_prefetch_free = mh_prefetch_free;
171 msg_info->msg_uid = uid;
172
173 return MAIL_NO_ERROR;
174 }
175
176
mh_fetch_size(mailmessage * msg_info,size_t * result)177 static int mh_fetch_size(mailmessage * msg_info,
178 size_t * result)
179 {
180 int r;
181 size_t size;
182
183 r = mhdriver_fetch_size(msg_info->msg_session, msg_info->msg_index, &size);
184 if (r != MAIL_NO_ERROR)
185 return r;
186
187 * result = size;
188
189 return MAIL_NO_ERROR;
190 }
191
192
193
194
mh_fetch_header(mailmessage * msg_info,char ** result,size_t * result_len)195 static int mh_fetch_header(mailmessage * msg_info,
196 char ** result,
197 size_t * result_len)
198 {
199 struct generic_message_t * msg;
200 int r;
201 char * msg_content;
202 size_t msg_length;
203
204 msg = msg_info->msg_data;
205 if (msg->msg_message != NULL) {
206
207 r = mailmessage_generic_fetch_header(msg_info, result, result_len);
208 return r;
209 }
210 else {
211 r = mhdriver_fetch_header(msg_info->msg_session, msg_info->msg_index,
212 &msg_content, &msg_length);
213 if (r != MAIL_NO_ERROR)
214 return r;
215
216 * result = msg_content;
217 * result_len = msg_length;
218
219 return MAIL_NO_ERROR;
220 }
221 }
222