Commit 8f6a087a 8f6a087af2063a2c9e368301799968d995f87d08 by Alain Magloire

Implement the mailbox framework for NNTP.

1 parent ebf3a875
...@@ -56,4 +56,8 @@ libmu_nntp_la_SOURCES = \ ...@@ -56,4 +56,8 @@ libmu_nntp_la_SOURCES = \
56 nntp_sendline.c \ 56 nntp_sendline.c \
57 nntp_stat.c \ 57 nntp_stat.c \
58 nntp_stream.c \ 58 nntp_stream.c \
59 nntp_timeout.c 59 nntp_timeout.c \
60 \
61 url.c \
62 folder.c \
63 mbox.c
......
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
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
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 };
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