Implement the mailbox framework for NNTP.
Showing
5 changed files
with
1054 additions
and
1 deletions
mailbox/nntp/folder.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2004 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with this library; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #ifdef ENABLE_NNTP | ||
23 | |||
24 | #include <errno.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <string.h> | ||
27 | |||
28 | #ifdef HAVE_STRINGS_H | ||
29 | # include <strings.h> | ||
30 | #endif | ||
31 | |||
32 | #include <mailutils/nntp.h> | ||
33 | #include <mailutils/errno.h> | ||
34 | #include <mailutils/mailbox.h> | ||
35 | #include <mailutils/registrar.h> | ||
36 | |||
37 | #include <folder0.h> | ||
38 | #include "nntp0.h" | ||
39 | |||
40 | /* We export url parsing and the initialisation of | ||
41 | the mailbox, via the register entry/record. */ | ||
42 | |||
43 | static struct _record _nntp_record = | ||
44 | { | ||
45 | MU_NNTP_URL_SCHEME, | ||
46 | _nntp_url_init, /* Url init. */ | ||
47 | _nntp_mailbox_init, /* Mailbox init. */ | ||
48 | NULL, /* Mailer init. */ | ||
49 | _nntp_folder_init, /* Folder init. */ | ||
50 | NULL, /* No need for an back pointer. */ | ||
51 | NULL, /* _is_scheme method. */ | ||
52 | NULL, /* _get_url method. */ | ||
53 | NULL, /* _get_mailbox method. */ | ||
54 | NULL, /* _get_mailer method. */ | ||
55 | NULL /* _get_folder method. */ | ||
56 | }; | ||
57 | record_t nntp_record = &_nntp_record; | ||
58 | |||
59 | static int nntp_folder_open __P ((folder_t, int)); | ||
60 | static int nntp_folder_close __P ((folder_t)); | ||
61 | static void nntp_folder_destroy __P ((folder_t folder)); | ||
62 | static int nntp_folder_list __P ((folder_t folder, const char *ref, const char *name, struct folder_list *pflist)); | ||
63 | |||
64 | int | ||
65 | _nntp_folder_init (folder_t folder) | ||
66 | { | ||
67 | int status; | ||
68 | f_nntp_t f_nntp; | ||
69 | |||
70 | f_nntp = folder->data = calloc (1, sizeof (*f_nntp)); | ||
71 | if (f_nntp == NULL) | ||
72 | return ENOMEM; | ||
73 | |||
74 | f_nntp->folder = folder; | ||
75 | |||
76 | folder->_destroy = nntp_folder_destroy; | ||
77 | |||
78 | folder->_open = nntp_folder_open; | ||
79 | folder->_close = nntp_folder_close; | ||
80 | |||
81 | folder->_list = nntp_folder_list; | ||
82 | /* Not supported. | ||
83 | folder->_lsub = folder_nntp_lsub; | ||
84 | folder->_subscribe = folder_nntp_subscribe; | ||
85 | folder->_unsubscribe = folder_nntp_unsubscribe; | ||
86 | folder->_delete = folder_nntp_delete; | ||
87 | folder->_rename = folder_nntp_rename; | ||
88 | */ | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int | ||
94 | nntp_folder_open (folder_t folder, int flags) | ||
95 | { | ||
96 | f_nntp_t f_nntp = folder->data; | ||
97 | stream_t carrier = NULL; | ||
98 | char *host; | ||
99 | long port = MU_NNTP_DEFAULT_PORT; /* default nntp port. */ | ||
100 | int status = 0; | ||
101 | size_t len = 0; | ||
102 | |||
103 | /* If we are already open for business, noop. */ | ||
104 | monitor_wrlock (folder->monitor); | ||
105 | if (f_nntp->isopen) | ||
106 | { | ||
107 | monitor_unlock (folder->monitor); | ||
108 | return 0; | ||
109 | } | ||
110 | monitor_unlock (folder->monitor); | ||
111 | |||
112 | /* Fetch the server name and the port in the url_t. */ | ||
113 | status = url_get_host (folder->url, NULL, 0, &len); | ||
114 | if (status != 0) | ||
115 | return status; | ||
116 | host = alloca (len + 1); | ||
117 | url_get_host (folder->url, host, len + 1, NULL); | ||
118 | url_get_port (folder->url, &port); | ||
119 | |||
120 | folder->flags = flags; | ||
121 | |||
122 | /* Create the networking stack. */ | ||
123 | status = tcp_stream_create (&carrier, host, port, folder->flags); | ||
124 | if (status != 0) | ||
125 | return status; | ||
126 | /* Ask for the stream internal buffering mechanism scheme. */ | ||
127 | stream_setbufsiz (carrier, BUFSIZ); | ||
128 | FOLDER_DEBUG2 (folder, MU_DEBUG_PROT, "folder_nntp_open (%s:%d)\n", host, port); | ||
129 | |||
130 | status = mu_nntp_create (&f_nntp->nntp); | ||
131 | if (status == 0) | ||
132 | { | ||
133 | status = mu_nntp_set_carrier (f_nntp->nntp, carrier); | ||
134 | if (status == 0) | ||
135 | { | ||
136 | status = mu_nntp_connect (f_nntp->nntp); | ||
137 | if (status == 0) | ||
138 | { | ||
139 | monitor_wrlock (folder->monitor); | ||
140 | f_nntp->isopen++; | ||
141 | monitor_unlock (folder->monitor); | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | return status; | ||
147 | } | ||
148 | |||
149 | static int | ||
150 | nntp_folder_close (folder_t folder) | ||
151 | { | ||
152 | f_nntp_t f_nntp = folder->data; | ||
153 | int status = 0; | ||
154 | |||
155 | monitor_wrlock (folder->monitor); | ||
156 | f_nntp->isopen--; | ||
157 | if (f_nntp->isopen) | ||
158 | { | ||
159 | monitor_unlock (folder->monitor); | ||
160 | return 0; | ||
161 | } | ||
162 | monitor_unlock (folder->monitor); | ||
163 | status = mu_nntp_quit (f_nntp->nntp); | ||
164 | f_nntp->selected = NULL; | ||
165 | return status; | ||
166 | |||
167 | } | ||
168 | |||
169 | /* Destroy the folder resources. */ | ||
170 | static void | ||
171 | nntp_folder_destroy (folder_t folder) | ||
172 | { | ||
173 | if (folder->data) | ||
174 | { | ||
175 | f_nntp_t f_nntp = folder->data; | ||
176 | if (f_nntp->nntp) | ||
177 | mu_nntp_destroy (&f_nntp->nntp); | ||
178 | free (f_nntp); | ||
179 | folder->data = NULL; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | |||
184 | static int | ||
185 | nntp_folder_list (folder_t folder, const char *ref, const char *name, struct folder_list *pflist) | ||
186 | { | ||
187 | return ENOTSUP; | ||
188 | } | ||
189 | #else | ||
190 | #include <stdio.h> | ||
191 | #include <registrar0.h> | ||
192 | record_t nntp_record = NULL; | ||
193 | #endif |
mailbox/nntp/mbox.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2004 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with this library; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #ifdef ENABLE_NNTP | ||
23 | |||
24 | #include <termios.h> | ||
25 | #include <errno.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <stdio.h> | ||
28 | #include <string.h> | ||
29 | #include <sys/time.h> | ||
30 | #include <sys/types.h> | ||
31 | #include <unistd.h> | ||
32 | #include <fcntl.h> | ||
33 | #include <stdarg.h> | ||
34 | |||
35 | #ifdef HAVE_ALLOCA_H | ||
36 | # include <alloca.h> | ||
37 | #endif | ||
38 | |||
39 | #ifdef HAVE_STRINGS_H | ||
40 | # include <strings.h> | ||
41 | #endif | ||
42 | |||
43 | #include <md5.h> | ||
44 | |||
45 | #include <mailutils/body.h> | ||
46 | #include <mailutils/debug.h> | ||
47 | #include <mailutils/errno.h> | ||
48 | #include <mailutils/error.h> | ||
49 | #include <mailutils/header.h> | ||
50 | #include <mailutils/message.h> | ||
51 | #include <mailutils/observer.h> | ||
52 | #include <mailutils/property.h> | ||
53 | #include <mailutils/stream.h> | ||
54 | #include <mailutils/url.h> | ||
55 | #include <mailutils/nntp.h> | ||
56 | |||
57 | #include <folder0.h> | ||
58 | #include <mailbox0.h> | ||
59 | #include "nntp0.h" | ||
60 | |||
61 | |||
62 | /* Functions/Methods that implements the mailbox_t API. */ | ||
63 | static void nntp_mailbox_destroy __P ((mailbox_t)); | ||
64 | static int nntp_mailbox_open __P ((mailbox_t, int)); | ||
65 | static int nntp_mailbox_close __P ((mailbox_t)); | ||
66 | static int nntp_mailbox_get_message __P ((mailbox_t, size_t, message_t *)); | ||
67 | static int nntp_mailbox_messages_count __P ((mailbox_t, size_t *)); | ||
68 | static int nntp_mailbox_scan __P ((mailbox_t, size_t, size_t *)); | ||
69 | static int nntp_mailbox_get_size __P ((mailbox_t, off_t *)); | ||
70 | |||
71 | static int nntp_message_get_transport2 __P ((stream_t, mu_transport_t *, mu_transport_t *)); | ||
72 | static int nntp_message_read __P ((stream_t, char *, size_t, off_t, size_t *)); | ||
73 | static int nntp_message_size __P ((message_t, size_t *)); | ||
74 | static int nntp_message_line __P ((message_t, size_t *)); | ||
75 | static int nntp_message_uidl __P ((message_t, char *, size_t, size_t *)); | ||
76 | static int nntp_message_uid __P ((message_t, size_t *)); | ||
77 | |||
78 | static int nntp_header_get_transport2 __P ((header_t, char *, size_t, off_t, size_t *)); | ||
79 | static int nntp_header_fill __P ((header_t, char *, size_t, off_t, size_t *)); | ||
80 | |||
81 | static int nntp_body_get_transport2 __P ((stream_t, mu_transport_t *, mu_transport_t *)); | ||
82 | static int nntp_body_read __P ((stream_t, char *, size_t, off_t, size_t *)); | ||
83 | static int nntp_body_size __P ((body_t, size_t *)); | ||
84 | static int nntp_body_lines __P ((body_t, size_t *)); | ||
85 | |||
86 | static int nntp_get_transport2 __P ((msg_nntp_t, mu_transport_t *, mu_transport_t *)); | ||
87 | |||
88 | int | ||
89 | _nntp_mailbox_init (mailbox_t mbox) | ||
90 | { | ||
91 | m_nntp_t m_nntp; | ||
92 | int status = 0; | ||
93 | size_t name_len = 0; | ||
94 | |||
95 | /* Allocate specifics for nntp data. */ | ||
96 | m_nntp = mbox->data = calloc (1, sizeof (*m_nntp)); | ||
97 | if (mbox->data == NULL) | ||
98 | return ENOMEM; | ||
99 | |||
100 | /* Get the back pointer of the concrete folder. */ | ||
101 | if (mbox->folder) | ||
102 | m_nntp->f_nntp = mbox->folder->data; | ||
103 | |||
104 | m_nntp->mailbox = mbox; /* Back pointer. */ | ||
105 | |||
106 | /* Retrieve the name of the newsgroup from the URL. */ | ||
107 | url_get_path (mbox->url, NULL, 0, &name_len); | ||
108 | if (name_len == 0) | ||
109 | { | ||
110 | /* name "INBOX" is the default. */ | ||
111 | m_nntp->name = calloc (6, sizeof (char)); | ||
112 | strcpy (m_nntp->name, "INBOX"); | ||
113 | } | ||
114 | else | ||
115 | { | ||
116 | char *p; | ||
117 | m_nntp->name = calloc (name_len + 1, sizeof (char)); | ||
118 | url_get_path (mbox->url, m_nntp->name, name_len + 1, NULL); | ||
119 | p = strchr (m_nntp->name,'/'); | ||
120 | if (p) | ||
121 | *p = '\0'; | ||
122 | } | ||
123 | |||
124 | /* Initialize the structure. */ | ||
125 | mbox->_destroy = nntp_mailbox_destroy; | ||
126 | |||
127 | mbox->_open = nntp_mailbox_open; | ||
128 | mbox->_close = nntp_mailbox_close; | ||
129 | |||
130 | /* Messages. */ | ||
131 | mbox->_get_message = nntp_mailbox_get_message; | ||
132 | mbox->_messages_count = nntp_mailbox_messages_count; | ||
133 | mbox->_messages_recent = nntp_mailbox_messages_count; | ||
134 | mbox->_message_unseen = nntp_mailbox_messages_count; | ||
135 | /*mbox->_expunge = nntp_mailbox_expunge;*/ | ||
136 | |||
137 | mbox->_scan = nntp_mailbox_scan; | ||
138 | /*mbox->_is_updated = nntp_mailbox_is_updated; */ | ||
139 | |||
140 | /*mbox->_get_size = nntp_mailbox_get_size; */ | ||
141 | |||
142 | /* Set our properties. */ | ||
143 | { | ||
144 | property_t property = NULL; | ||
145 | mailbox_get_property (mbox, &property); | ||
146 | property_set_value (property, "TYPE", "NNTP", 1); | ||
147 | } | ||
148 | |||
149 | return status; | ||
150 | } | ||
151 | |||
152 | /* Cleaning up all the ressources associate with a newsgroup/mailbox. */ | ||
153 | static void | ||
154 | nntp_mailbox_destroy (mailbox_t mbox) | ||
155 | { | ||
156 | if (mbox->data) | ||
157 | { | ||
158 | m_nntp_t m_nntp = mbox->data; | ||
159 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
160 | size_t i; | ||
161 | |||
162 | /* Deselect. */ | ||
163 | if (m_nntp == f_nntp->selected) | ||
164 | f_nntp->selected = NULL; | ||
165 | |||
166 | monitor_wrlock (mbox->monitor); | ||
167 | |||
168 | if (m_nntp->name) | ||
169 | free (m_nntp->name); | ||
170 | |||
171 | /* Destroy the nntp messages and ressources associated to them. */ | ||
172 | for (i = 0; i < m_nntp->messages_count; i++) | ||
173 | { | ||
174 | if (m_nntp->messages[i]) | ||
175 | { | ||
176 | message_destroy (&(m_nntp->messages[i]->message), m_nntp->messages[i]); | ||
177 | if (m_nntp->messages[i]->mid) | ||
178 | free (m_nntp->messages[i]->mid); | ||
179 | free (m_nntp->messages[i]); | ||
180 | m_nntp->messages[i] = NULL; | ||
181 | } | ||
182 | } | ||
183 | if (m_nntp->messages) | ||
184 | free (m_nntp->messages); | ||
185 | free (m_nntp); | ||
186 | mbox->data = NULL; | ||
187 | monitor_unlock (mbox->monitor); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | /* If the connection was not up it is open by the folder since the stream | ||
192 | socket is actually created by the folder. It is not necessary | ||
193 | to set select the mailbox/newsgoup right away, there are maybe on going operations. | ||
194 | But on any operation by a particular mailbox, it will be selected first. */ | ||
195 | static int | ||
196 | nntp_mailbox_open (mailbox_t mbox, int flags) | ||
197 | { | ||
198 | int status = 0; | ||
199 | m_nntp_t m_nntp = mbox->data; | ||
200 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
201 | folder_t folder = f_nntp->folder; | ||
202 | iterator_t iterator; | ||
203 | |||
204 | /* m_nntp must have been created during mailbox initialization. */ | ||
205 | /* assert (mbox->data); | ||
206 | assert (m_nntp->name); */ | ||
207 | |||
208 | mbox->flags = flags; | ||
209 | |||
210 | /* make sure the connection is up. */ | ||
211 | if ((status = folder_open (f_nntp->folder, flags))) | ||
212 | return status; | ||
213 | |||
214 | mu_nntp_set_debug (f_nntp->nntp, mbox->debug); | ||
215 | |||
216 | /* We might not have to SELECT the newsgroup, but we need to know it | ||
217 | exists. */ | ||
218 | status = mu_nntp_list_active (f_nntp->nntp, m_nntp->name, &iterator); | ||
219 | if (status == 0) | ||
220 | { | ||
221 | for (iterator_first (iterator); | ||
222 | !iterator_is_done (iterator); iterator_next (iterator)) | ||
223 | { | ||
224 | char *buffer = NULL; | ||
225 | iterator_current (iterator, (void **) &buffer); | ||
226 | mu_nntp_parse_list_active (buffer, NULL, &m_nntp->high, &m_nntp->low, &m_nntp->status); | ||
227 | } | ||
228 | iterator_destroy (&iterator); | ||
229 | } | ||
230 | return status; | ||
231 | } | ||
232 | |||
233 | /* We can not close the folder in term of shuting down the connection but if | ||
234 | we were the selected mailbox/newsgroup we deselect ourself. */ | ||
235 | static int | ||
236 | nntp_mailbox_close (mailbox_t mailbox) | ||
237 | { | ||
238 | m_nntp_t m_nntp = mailbox->data; | ||
239 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
240 | int i; | ||
241 | |||
242 | monitor_wrlock (mailbox->monitor); | ||
243 | |||
244 | /* Destroy the nntp posts and ressources associated to them. */ | ||
245 | for (i = 0; i < m_nntp->messages_count; i++) | ||
246 | { | ||
247 | if (m_nntp->messages[i]) | ||
248 | { | ||
249 | msg_nntp_t msg_nntp = m_nntp->messages[i]; | ||
250 | if (msg_nntp->message) | ||
251 | message_destroy (&(msg_nntp->message), msg_nntp); | ||
252 | } | ||
253 | free (m_nntp->messages[i]); | ||
254 | } | ||
255 | if (m_nntp->messages) | ||
256 | free (m_nntp->messages); | ||
257 | m_nntp->messages = NULL; | ||
258 | m_nntp->messages_count = 0; | ||
259 | m_nntp->number = 0; | ||
260 | m_nntp->low = 0; | ||
261 | m_nntp->high = 0; | ||
262 | monitor_unlock (mailbox->monitor); | ||
263 | |||
264 | /* Deselect. */ | ||
265 | if (m_nntp != f_nntp->selected) | ||
266 | f_nntp->selected = NULL; | ||
267 | |||
268 | /* Decrement the ref count. */ | ||
269 | return folder_close (mailbox->folder); | ||
270 | } | ||
271 | |||
272 | static int | ||
273 | nntp_mailbox_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ||
274 | { | ||
275 | m_nntp_t m_nntp = mbox->data; | ||
276 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
277 | msg_nntp_t msg_nntp; | ||
278 | message_t msg = NULL; | ||
279 | int status; | ||
280 | size_t i; | ||
281 | |||
282 | /* Sanity. */ | ||
283 | if (pmsg == NULL) | ||
284 | return MU_ERR_OUT_PTR_NULL; | ||
285 | |||
286 | msgno--; | ||
287 | monitor_rdlock (mbox->monitor); | ||
288 | /* See if we have already this message. */ | ||
289 | for (i = 0; i < m_nntp->messages_count; i++) | ||
290 | { | ||
291 | if (m_nntp->messages[i]) | ||
292 | { | ||
293 | if (m_nntp->messages[i]->msgno == msgno + m_nntp->low) | ||
294 | { | ||
295 | *pmsg = m_nntp->messages[i]->message; | ||
296 | monitor_unlock (mbox->monitor); | ||
297 | return 0; | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | monitor_unlock (mbox->monitor); | ||
302 | |||
303 | msg_nntp = calloc (1, sizeof (*msg_nntp)); | ||
304 | if (msg_nntp == NULL) | ||
305 | return ENOMEM; | ||
306 | |||
307 | /* Back pointer. */ | ||
308 | msg_nntp->m_nntp = m_nntp; | ||
309 | msg_nntp->msgno = msgno + m_nntp->low; | ||
310 | |||
311 | /* Create the message. */ | ||
312 | { | ||
313 | stream_t stream = NULL; | ||
314 | if ((status = message_create (&msg, msg_nntp)) != 0 | ||
315 | || (status = stream_create (&stream, mbox->flags, msg)) != 0) | ||
316 | { | ||
317 | stream_destroy (&stream, msg); | ||
318 | message_destroy (&msg, msg_nntp); | ||
319 | free (msg_nntp); | ||
320 | return status; | ||
321 | } | ||
322 | /* Help for the readline()s */ | ||
323 | stream_set_read (stream, nntp_message_read, msg); | ||
324 | stream_set_get_transport2 (stream, nntp_message_get_transport2, msg); | ||
325 | message_set_stream (msg, stream, msg_nntp); | ||
326 | message_set_size (msg, nntp_message_size, msg_nntp); | ||
327 | } | ||
328 | |||
329 | /* Create the header. */ | ||
330 | { | ||
331 | header_t header = NULL; | ||
332 | if ((status = header_create (&header, NULL, 0, msg)) != 0) | ||
333 | { | ||
334 | message_destroy (&msg, msg_nntp); | ||
335 | free (msg_nntp); | ||
336 | return status; | ||
337 | } | ||
338 | header_set_fill (header, nntp_header_fill, msg); | ||
339 | message_set_header (msg, header, msg_nntp); | ||
340 | } | ||
341 | |||
342 | /* Create the body and its stream. */ | ||
343 | { | ||
344 | body_t body = NULL; | ||
345 | stream_t stream = NULL; | ||
346 | if ((status = body_create (&body, msg)) != 0 | ||
347 | || (status = stream_create (&stream, mbox->flags, body)) != 0) | ||
348 | { | ||
349 | body_destroy (&body, msg); | ||
350 | stream_destroy (&stream, body); | ||
351 | message_destroy (&msg, msg_nntp); | ||
352 | free (msg_nntp); | ||
353 | return status; | ||
354 | } | ||
355 | /* Helps for the readline()s */ | ||
356 | stream_set_read (stream, nntp_body_read, body); | ||
357 | stream_set_get_transport2 (stream, nntp_body_get_transport2, body); | ||
358 | body_set_size (body, nntp_body_size, msg); | ||
359 | body_set_lines (body, nntp_body_lines, msg); | ||
360 | body_set_stream (body, stream, msg); | ||
361 | message_set_body (msg, body, msg_nntp); | ||
362 | } | ||
363 | |||
364 | /* Set the UID on the message. */ | ||
365 | message_set_uid (msg, nntp_message_uid, msg_nntp); | ||
366 | |||
367 | /* Add it to the list. */ | ||
368 | monitor_wrlock (mbox->monitor); | ||
369 | { | ||
370 | msg_nntp_t *m ; | ||
371 | m = realloc (m_nntp->messages, (m_nntp->messages_count + 1)*sizeof (*m)); | ||
372 | if (m == NULL) | ||
373 | { | ||
374 | message_destroy (&msg, msg_nntp); | ||
375 | free (msg_nntp); | ||
376 | monitor_unlock (mbox->monitor); | ||
377 | return ENOMEM; | ||
378 | } | ||
379 | m_nntp->messages = m; | ||
380 | m_nntp->messages[m_nntp->messages_count] = msg_nntp; | ||
381 | m_nntp->messages_count++; | ||
382 | } | ||
383 | monitor_unlock (mbox->monitor); | ||
384 | |||
385 | /* Save The message pointer. */ | ||
386 | message_set_mailbox (msg, mbox, msg_nntp); | ||
387 | *pmsg = msg_nntp->message = msg; | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | /* There is no explicit call to get the message count. The count is send on | ||
393 | a "GROUP" command. The function is also use as a way to select newsgoupr by other functions. */ | ||
394 | static int | ||
395 | nntp_mailbox_messages_count (mailbox_t mbox, size_t *pcount) | ||
396 | { | ||
397 | m_nntp_t m_nntp = mbox->data; | ||
398 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
399 | int status = 0; | ||
400 | |||
401 | status = folder_open (mbox->folder, mbox->flags); | ||
402 | if (status != 0) | ||
403 | return status; | ||
404 | |||
405 | /* Are we already selected ? */ | ||
406 | if (m_nntp == (f_nntp->selected)) | ||
407 | { | ||
408 | if (pcount) | ||
409 | *pcount = m_nntp->number; | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /* Put the mailbox as selected. */ | ||
414 | f_nntp->selected = m_nntp; | ||
415 | |||
416 | status = mu_nntp_group (f_nntp->nntp, m_nntp->name, &m_nntp->number, &m_nntp->low, &m_nntp->high, NULL); | ||
417 | |||
418 | if (pcount) | ||
419 | *pcount = m_nntp->number; | ||
420 | |||
421 | return status; | ||
422 | } | ||
423 | |||
424 | /* Update and scanning. */ | ||
425 | static int | ||
426 | nntp_is_updated (mailbox_t mbox) | ||
427 | { | ||
428 | return 1; | ||
429 | } | ||
430 | |||
431 | /* We just simulate by sending a notification for the total msgno. */ | ||
432 | /* FIXME is message is set deleted should we sent a notif ? */ | ||
433 | static int | ||
434 | nntp_mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ||
435 | { | ||
436 | int status; | ||
437 | size_t i; | ||
438 | size_t count = 0; | ||
439 | |||
440 | /* Select first. */ | ||
441 | status = nntp_mailbox_messages_count (mbox, &count); | ||
442 | if (pcount) | ||
443 | *pcount = count; | ||
444 | if (status != 0) | ||
445 | return status; | ||
446 | if (mbox->observable == NULL) | ||
447 | return 0; | ||
448 | for (i = msgno; i <= count; i++) | ||
449 | { | ||
450 | if (observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD) != 0) | ||
451 | break; | ||
452 | if (((i +1) % 10) == 0) | ||
453 | { | ||
454 | observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS); | ||
455 | } | ||
456 | } | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int | ||
461 | nntp_message_size (message_t msg, size_t *psize) | ||
462 | { | ||
463 | if (psize) | ||
464 | *psize = 0; | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int | ||
469 | nntp_body_size (body_t body, size_t *psize) | ||
470 | { | ||
471 | if (psize) | ||
472 | *psize = 0; | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | /* Not know until the whole message get downloaded. */ | ||
478 | static int | ||
479 | nntp_body_lines (body_t body, size_t *plines) | ||
480 | { | ||
481 | if (plines) | ||
482 | *plines = 0; | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | /* Stub to call the fd from body object. */ | ||
487 | static int | ||
488 | nntp_body_get_transport2 (stream_t stream, mu_transport_t *pin, mu_transport_t *pout) | ||
489 | { | ||
490 | body_t body = stream_get_owner (stream); | ||
491 | message_t msg = body_get_owner (body); | ||
492 | msg_nntp_t msg_nntp = message_get_owner (msg); | ||
493 | return nntp_get_transport2 (msg_nntp, pin, pout); | ||
494 | } | ||
495 | |||
496 | /* Stub to call the fd from message object. */ | ||
497 | static int | ||
498 | nntp_message_get_transport2 (stream_t stream, mu_transport_t *pin, mu_transport_t *pout) | ||
499 | { | ||
500 | message_t msg = stream_get_owner (stream); | ||
501 | msg_nntp_t msg_nntp = message_get_owner (msg); | ||
502 | return nntp_get_transport2 (msg_nntp, pin, pout); | ||
503 | } | ||
504 | |||
505 | static int | ||
506 | nntp_get_transport2 (msg_nntp_t msg_nntp, mu_transport_t *pin, mu_transport_t *pout) | ||
507 | { | ||
508 | int status = EINVAL; | ||
509 | if (msg_nntp && msg_nntp->m_nntp | ||
510 | && msg_nntp->m_nntp->f_nntp && msg_nntp->m_nntp->f_nntp->folder) | ||
511 | { | ||
512 | stream_t carrier; | ||
513 | status = mu_nntp_get_carrier (msg_nntp->m_nntp->f_nntp->nntp, &carrier); | ||
514 | if (status == 0) | ||
515 | return stream_get_transport2 (carrier, pin, pout); | ||
516 | } | ||
517 | return status; | ||
518 | } | ||
519 | |||
520 | static int | ||
521 | nntp_message_uid (message_t msg, size_t *puid) | ||
522 | { | ||
523 | msg_nntp_t msg_nntp = message_get_owner (msg); | ||
524 | m_nntp_t m_nntp = msg_nntp->m_nntp; | ||
525 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
526 | int status; | ||
527 | |||
528 | if (puid) | ||
529 | return 0; | ||
530 | |||
531 | /* Select first. */ | ||
532 | status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL); | ||
533 | if (status != 0) | ||
534 | return status; | ||
535 | |||
536 | if (puid) | ||
537 | *puid = msg_nntp->msgno; | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static int | ||
542 | nntp_message_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | ||
543 | { | ||
544 | msg_nntp_t msg_nntp = message_get_owner (msg); | ||
545 | m_nntp_t m_nntp = msg_nntp->m_nntp; | ||
546 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
547 | int status = 0; | ||
548 | |||
549 | /* Select first. */ | ||
550 | status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL); | ||
551 | if (status != 0) | ||
552 | return status; | ||
553 | |||
554 | if (msg_nntp->mid) | ||
555 | { | ||
556 | size_t len = strlen (msg_nntp->mid); | ||
557 | if (buffer) | ||
558 | { | ||
559 | buflen--; /* Leave space for the null. */ | ||
560 | buflen = (len > buflen) ? buflen : len; | ||
561 | memcpy (buffer, msg_nntp->mid, buflen); | ||
562 | buffer[buflen] = '\0'; | ||
563 | } | ||
564 | else | ||
565 | buflen = len; | ||
566 | } | ||
567 | else | ||
568 | buflen = 0; | ||
569 | |||
570 | if (pnwriten) | ||
571 | *pnwriten = buflen; | ||
572 | return status; | ||
573 | } | ||
574 | |||
575 | /* Message read overload */ | ||
576 | static int | ||
577 | nntp_message_read (stream_t stream, char *buffer, size_t buflen, off_t offset, size_t *plen) | ||
578 | { | ||
579 | message_t msg = stream_get_owner (stream); | ||
580 | msg_nntp_t msg_nntp = message_get_owner (msg); | ||
581 | m_nntp_t m_nntp = msg_nntp->m_nntp; | ||
582 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
583 | int status; | ||
584 | size_t len = 0; | ||
585 | |||
586 | /* Start over. */ | ||
587 | if (plen == NULL) | ||
588 | plen = &len; | ||
589 | |||
590 | /* Select first. */ | ||
591 | status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL); | ||
592 | if (status != 0) | ||
593 | return status; | ||
594 | |||
595 | if (msg_nntp->mstream == NULL) | ||
596 | { | ||
597 | status = mu_nntp_article (f_nntp->nntp, msg_nntp->msgno, NULL, &msg_nntp->mid, &msg_nntp->mstream); | ||
598 | if (status != 0) | ||
599 | return status; | ||
600 | } | ||
601 | status = stream_read (msg_nntp->mstream, buffer, buflen, offset, plen); | ||
602 | if (status == 0) | ||
603 | { | ||
604 | /* Destroy the stream. */ | ||
605 | if (*plen == 0) | ||
606 | { | ||
607 | stream_destroy (&msg_nntp->mstream, NULL); | ||
608 | } | ||
609 | } | ||
610 | return status; | ||
611 | } | ||
612 | |||
613 | /* Message read overload */ | ||
614 | static int | ||
615 | nntp_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset, size_t *plen) | ||
616 | { | ||
617 | body_t body = stream_get_owner (stream); | ||
618 | message_t msg = body_get_owner (body); | ||
619 | msg_nntp_t msg_nntp = message_get_owner (msg); | ||
620 | m_nntp_t m_nntp = msg_nntp->m_nntp; | ||
621 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
622 | int status; | ||
623 | size_t len = 0; | ||
624 | |||
625 | /* Start over. */ | ||
626 | if (plen == NULL) | ||
627 | plen = &len; | ||
628 | |||
629 | /* Select first. */ | ||
630 | status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL); | ||
631 | if (status != 0) | ||
632 | return status; | ||
633 | |||
634 | if (msg_nntp->bstream == NULL) | ||
635 | { | ||
636 | status = mu_nntp_body (f_nntp->nntp, msg_nntp->msgno, NULL, &msg_nntp->mid, &msg_nntp->bstream); | ||
637 | if (status != 0) | ||
638 | return status; | ||
639 | } | ||
640 | status = stream_read (msg_nntp->bstream, buffer, buflen, offset, plen); | ||
641 | if (status == 0) | ||
642 | { | ||
643 | /* Destroy the stream. */ | ||
644 | if (*plen == 0) | ||
645 | { | ||
646 | stream_destroy (&msg_nntp->bstream, NULL); | ||
647 | } | ||
648 | } | ||
649 | return status; | ||
650 | } | ||
651 | |||
652 | /* Header read overload */ | ||
653 | static int | ||
654 | nntp_header_fill (header_t header, char *buffer, size_t buflen, off_t offset, size_t *plen) | ||
655 | { | ||
656 | message_t msg = header_get_owner (header); | ||
657 | msg_nntp_t msg_nntp = message_get_owner (msg); | ||
658 | m_nntp_t m_nntp = msg_nntp->m_nntp; | ||
659 | f_nntp_t f_nntp = m_nntp->f_nntp; | ||
660 | int status; | ||
661 | size_t len = 0; | ||
662 | |||
663 | /* Start over. */ | ||
664 | if (plen == NULL) | ||
665 | plen = &len; | ||
666 | |||
667 | /* Select first. */ | ||
668 | status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL); | ||
669 | if (status != 0) | ||
670 | return status; | ||
671 | |||
672 | if (msg_nntp->hstream == NULL) | ||
673 | { | ||
674 | status = mu_nntp_head (f_nntp->nntp, msg_nntp->msgno, NULL, &msg_nntp->mid, &msg_nntp->hstream); | ||
675 | if (status != 0) | ||
676 | return status; | ||
677 | } | ||
678 | status = stream_read (msg_nntp->hstream, buffer, buflen, offset, plen); | ||
679 | if (status == 0) | ||
680 | { | ||
681 | /* Destroy the stream. */ | ||
682 | if (*plen == 0) | ||
683 | { | ||
684 | stream_destroy (&msg_nntp->hstream, NULL); | ||
685 | } | ||
686 | } | ||
687 | return status; | ||
688 | } | ||
689 | |||
690 | #endif |
mailbox/nntp/nntp0.h
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2004 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with this library; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | struct _nntp_folder; | ||
23 | struct _nntp_mailbox; | ||
24 | struct _nntp_message; | ||
25 | typedef struct _nntp_folder *f_nntp_t; | ||
26 | typedef struct _nntp_mailbox *m_nntp_t; | ||
27 | typedef struct _nntp_message *msg_nntp_t; | ||
28 | |||
29 | extern int _nntp_url_init __P ((url_t)); | ||
30 | extern int _nntp_mailbox_init __P ((mailbox_t)); | ||
31 | extern int _nntp_folder_init __P ((folder_t)); | ||
32 | |||
33 | struct _nntp_folder | ||
34 | { | ||
35 | /* Refcount. */ | ||
36 | int isopen; | ||
37 | |||
38 | /* Back pointer. */ | ||
39 | folder_t folder; | ||
40 | |||
41 | /* Selected newsgroup. */ | ||
42 | m_nntp_t selected; | ||
43 | |||
44 | /* NNTP object. */ | ||
45 | mu_nntp_t nntp; | ||
46 | }; | ||
47 | |||
48 | struct _nntp_mailbox | ||
49 | { | ||
50 | char status; | ||
51 | |||
52 | char *name; | ||
53 | |||
54 | /* Pointer back to the mailbox/newsgroup. */ | ||
55 | mailbox_t mailbox; | ||
56 | |||
57 | /* Our nntp folder. */ | ||
58 | f_nntp_t f_nntp; | ||
59 | |||
60 | /* Read Messages on the newsgroup. */ | ||
61 | msg_nntp_t *messages; | ||
62 | size_t messages_count; | ||
63 | |||
64 | /* Estimated number of articles in the group. */ | ||
65 | unsigned long number; | ||
66 | /* High water mark from "GROUP" command */ | ||
67 | unsigned long high; | ||
68 | /* Low water mark from "GROUP" command */ | ||
69 | unsigned long low; | ||
70 | }; | ||
71 | |||
72 | struct _nntp_message | ||
73 | { | ||
74 | /* Back pointer. */ | ||
75 | message_t message; | ||
76 | |||
77 | /* Our nntp folder. */ | ||
78 | m_nntp_t m_nntp; | ||
79 | |||
80 | /* Message id. */ | ||
81 | char *mid; | ||
82 | |||
83 | /* mesgno of the post. */ | ||
84 | unsigned long msgno; | ||
85 | |||
86 | /* Stream for message. */ | ||
87 | stream_t mstream; | ||
88 | /* Stream for body. */ | ||
89 | stream_t bstream; | ||
90 | /* Stream for header. */ | ||
91 | stream_t hstream; | ||
92 | }; |
mailbox/nntp/url.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2004 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with this library; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #ifdef ENABLE_NNTP | ||
23 | |||
24 | #include <errno.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <string.h> | ||
27 | #include <errno.h> | ||
28 | #ifdef HAVE_STRINGS_H | ||
29 | # include <strings.h> | ||
30 | #endif | ||
31 | |||
32 | #include <mailutils/nntp.h> | ||
33 | |||
34 | #include <url0.h> | ||
35 | |||
36 | static void url_nntp_destroy (url_t url); | ||
37 | |||
38 | static void | ||
39 | url_nntp_destroy (url_t url ARG_UNUSED) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | POP URL: | ||
45 | nntp://<host>:<port>/<newsgroup-name>/<article-number> | ||
46 | */ | ||
47 | |||
48 | int | ||
49 | _nntp_url_init (url_t url) | ||
50 | { | ||
51 | int status = 0; | ||
52 | |||
53 | url->_destroy = url_nntp_destroy; | ||
54 | |||
55 | status = url_parse(url); | ||
56 | |||
57 | if(status) | ||
58 | return status; | ||
59 | |||
60 | /* is it nntp? */ | ||
61 | if (strcmp (MU_NNTP_URL_SCHEME, url->scheme) != 0) | ||
62 | return EINVAL; | ||
63 | |||
64 | /* not valid in a nntp url */ | ||
65 | if (!url->host || !url->path) | ||
66 | return EINVAL; | ||
67 | |||
68 | if (url->port == 0) | ||
69 | url->port = MU_NNTP_DEFAULT_PORT; | ||
70 | |||
71 | return status; | ||
72 | } | ||
73 | |||
74 | #endif |
-
Please register or sign in to post a comment