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