Commit 8f6a087a 8f6a087af2063a2c9e368301799968d995f87d08 by Alain Magloire

Implement the mailbox framework for NNTP.

1 parent ebf3a875
......@@ -56,4 +56,8 @@ libmu_nntp_la_SOURCES = \
nntp_sendline.c \
nntp_stat.c \
nntp_stream.c \
nntp_timeout.c
nntp_timeout.c \
\
url.c \
folder.c \
mbox.c
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef ENABLE_NNTP
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <mailutils/nntp.h>
#include <mailutils/errno.h>
#include <mailutils/mailbox.h>
#include <mailutils/registrar.h>
#include <folder0.h>
#include "nntp0.h"
/* We export url parsing and the initialisation of
the mailbox, via the register entry/record. */
static struct _record _nntp_record =
{
MU_NNTP_URL_SCHEME,
_nntp_url_init, /* Url init. */
_nntp_mailbox_init, /* Mailbox init. */
NULL, /* Mailer init. */
_nntp_folder_init, /* Folder init. */
NULL, /* No need for an back pointer. */
NULL, /* _is_scheme method. */
NULL, /* _get_url method. */
NULL, /* _get_mailbox method. */
NULL, /* _get_mailer method. */
NULL /* _get_folder method. */
};
record_t nntp_record = &_nntp_record;
static int nntp_folder_open __P ((folder_t, int));
static int nntp_folder_close __P ((folder_t));
static void nntp_folder_destroy __P ((folder_t folder));
static int nntp_folder_list __P ((folder_t folder, const char *ref, const char *name, struct folder_list *pflist));
int
_nntp_folder_init (folder_t folder)
{
int status;
f_nntp_t f_nntp;
f_nntp = folder->data = calloc (1, sizeof (*f_nntp));
if (f_nntp == NULL)
return ENOMEM;
f_nntp->folder = folder;
folder->_destroy = nntp_folder_destroy;
folder->_open = nntp_folder_open;
folder->_close = nntp_folder_close;
folder->_list = nntp_folder_list;
/* Not supported.
folder->_lsub = folder_nntp_lsub;
folder->_subscribe = folder_nntp_subscribe;
folder->_unsubscribe = folder_nntp_unsubscribe;
folder->_delete = folder_nntp_delete;
folder->_rename = folder_nntp_rename;
*/
return 0;
}
static int
nntp_folder_open (folder_t folder, int flags)
{
f_nntp_t f_nntp = folder->data;
stream_t carrier = NULL;
char *host;
long port = MU_NNTP_DEFAULT_PORT; /* default nntp port. */
int status = 0;
size_t len = 0;
/* If we are already open for business, noop. */
monitor_wrlock (folder->monitor);
if (f_nntp->isopen)
{
monitor_unlock (folder->monitor);
return 0;
}
monitor_unlock (folder->monitor);
/* Fetch the server name and the port in the url_t. */
status = url_get_host (folder->url, NULL, 0, &len);
if (status != 0)
return status;
host = alloca (len + 1);
url_get_host (folder->url, host, len + 1, NULL);
url_get_port (folder->url, &port);
folder->flags = flags;
/* Create the networking stack. */
status = tcp_stream_create (&carrier, host, port, folder->flags);
if (status != 0)
return status;
/* Ask for the stream internal buffering mechanism scheme. */
stream_setbufsiz (carrier, BUFSIZ);
FOLDER_DEBUG2 (folder, MU_DEBUG_PROT, "folder_nntp_open (%s:%d)\n", host, port);
status = mu_nntp_create (&f_nntp->nntp);
if (status == 0)
{
status = mu_nntp_set_carrier (f_nntp->nntp, carrier);
if (status == 0)
{
status = mu_nntp_connect (f_nntp->nntp);
if (status == 0)
{
monitor_wrlock (folder->monitor);
f_nntp->isopen++;
monitor_unlock (folder->monitor);
}
}
}
return status;
}
static int
nntp_folder_close (folder_t folder)
{
f_nntp_t f_nntp = folder->data;
int status = 0;
monitor_wrlock (folder->monitor);
f_nntp->isopen--;
if (f_nntp->isopen)
{
monitor_unlock (folder->monitor);
return 0;
}
monitor_unlock (folder->monitor);
status = mu_nntp_quit (f_nntp->nntp);
f_nntp->selected = NULL;
return status;
}
/* Destroy the folder resources. */
static void
nntp_folder_destroy (folder_t folder)
{
if (folder->data)
{
f_nntp_t f_nntp = folder->data;
if (f_nntp->nntp)
mu_nntp_destroy (&f_nntp->nntp);
free (f_nntp);
folder->data = NULL;
}
}
static int
nntp_folder_list (folder_t folder, const char *ref, const char *name, struct folder_list *pflist)
{
return ENOTSUP;
}
#else
#include <stdio.h>
#include <registrar0.h>
record_t nntp_record = NULL;
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef ENABLE_NNTP
#include <termios.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <md5.h>
#include <mailutils/body.h>
#include <mailutils/debug.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/header.h>
#include <mailutils/message.h>
#include <mailutils/observer.h>
#include <mailutils/property.h>
#include <mailutils/stream.h>
#include <mailutils/url.h>
#include <mailutils/nntp.h>
#include <folder0.h>
#include <mailbox0.h>
#include "nntp0.h"
/* Functions/Methods that implements the mailbox_t API. */
static void nntp_mailbox_destroy __P ((mailbox_t));
static int nntp_mailbox_open __P ((mailbox_t, int));
static int nntp_mailbox_close __P ((mailbox_t));
static int nntp_mailbox_get_message __P ((mailbox_t, size_t, message_t *));
static int nntp_mailbox_messages_count __P ((mailbox_t, size_t *));
static int nntp_mailbox_scan __P ((mailbox_t, size_t, size_t *));
static int nntp_mailbox_get_size __P ((mailbox_t, off_t *));
static int nntp_message_get_transport2 __P ((stream_t, mu_transport_t *, mu_transport_t *));
static int nntp_message_read __P ((stream_t, char *, size_t, off_t, size_t *));
static int nntp_message_size __P ((message_t, size_t *));
static int nntp_message_line __P ((message_t, size_t *));
static int nntp_message_uidl __P ((message_t, char *, size_t, size_t *));
static int nntp_message_uid __P ((message_t, size_t *));
static int nntp_header_get_transport2 __P ((header_t, char *, size_t, off_t, size_t *));
static int nntp_header_fill __P ((header_t, char *, size_t, off_t, size_t *));
static int nntp_body_get_transport2 __P ((stream_t, mu_transport_t *, mu_transport_t *));
static int nntp_body_read __P ((stream_t, char *, size_t, off_t, size_t *));
static int nntp_body_size __P ((body_t, size_t *));
static int nntp_body_lines __P ((body_t, size_t *));
static int nntp_get_transport2 __P ((msg_nntp_t, mu_transport_t *, mu_transport_t *));
int
_nntp_mailbox_init (mailbox_t mbox)
{
m_nntp_t m_nntp;
int status = 0;
size_t name_len = 0;
/* Allocate specifics for nntp data. */
m_nntp = mbox->data = calloc (1, sizeof (*m_nntp));
if (mbox->data == NULL)
return ENOMEM;
/* Get the back pointer of the concrete folder. */
if (mbox->folder)
m_nntp->f_nntp = mbox->folder->data;
m_nntp->mailbox = mbox; /* Back pointer. */
/* Retrieve the name of the newsgroup from the URL. */
url_get_path (mbox->url, NULL, 0, &name_len);
if (name_len == 0)
{
/* name "INBOX" is the default. */
m_nntp->name = calloc (6, sizeof (char));
strcpy (m_nntp->name, "INBOX");
}
else
{
char *p;
m_nntp->name = calloc (name_len + 1, sizeof (char));
url_get_path (mbox->url, m_nntp->name, name_len + 1, NULL);
p = strchr (m_nntp->name,'/');
if (p)
*p = '\0';
}
/* Initialize the structure. */
mbox->_destroy = nntp_mailbox_destroy;
mbox->_open = nntp_mailbox_open;
mbox->_close = nntp_mailbox_close;
/* Messages. */
mbox->_get_message = nntp_mailbox_get_message;
mbox->_messages_count = nntp_mailbox_messages_count;
mbox->_messages_recent = nntp_mailbox_messages_count;
mbox->_message_unseen = nntp_mailbox_messages_count;
/*mbox->_expunge = nntp_mailbox_expunge;*/
mbox->_scan = nntp_mailbox_scan;
/*mbox->_is_updated = nntp_mailbox_is_updated; */
/*mbox->_get_size = nntp_mailbox_get_size; */
/* Set our properties. */
{
property_t property = NULL;
mailbox_get_property (mbox, &property);
property_set_value (property, "TYPE", "NNTP", 1);
}
return status;
}
/* Cleaning up all the ressources associate with a newsgroup/mailbox. */
static void
nntp_mailbox_destroy (mailbox_t mbox)
{
if (mbox->data)
{
m_nntp_t m_nntp = mbox->data;
f_nntp_t f_nntp = m_nntp->f_nntp;
size_t i;
/* Deselect. */
if (m_nntp == f_nntp->selected)
f_nntp->selected = NULL;
monitor_wrlock (mbox->monitor);
if (m_nntp->name)
free (m_nntp->name);
/* Destroy the nntp messages and ressources associated to them. */
for (i = 0; i < m_nntp->messages_count; i++)
{
if (m_nntp->messages[i])
{
message_destroy (&(m_nntp->messages[i]->message), m_nntp->messages[i]);
if (m_nntp->messages[i]->mid)
free (m_nntp->messages[i]->mid);
free (m_nntp->messages[i]);
m_nntp->messages[i] = NULL;
}
}
if (m_nntp->messages)
free (m_nntp->messages);
free (m_nntp);
mbox->data = NULL;
monitor_unlock (mbox->monitor);
}
}
/* If the connection was not up it is open by the folder since the stream
socket is actually created by the folder. It is not necessary
to set select the mailbox/newsgoup right away, there are maybe on going operations.
But on any operation by a particular mailbox, it will be selected first. */
static int
nntp_mailbox_open (mailbox_t mbox, int flags)
{
int status = 0;
m_nntp_t m_nntp = mbox->data;
f_nntp_t f_nntp = m_nntp->f_nntp;
folder_t folder = f_nntp->folder;
iterator_t iterator;
/* m_nntp must have been created during mailbox initialization. */
/* assert (mbox->data);
assert (m_nntp->name); */
mbox->flags = flags;
/* make sure the connection is up. */
if ((status = folder_open (f_nntp->folder, flags)))
return status;
mu_nntp_set_debug (f_nntp->nntp, mbox->debug);
/* We might not have to SELECT the newsgroup, but we need to know it
exists. */
status = mu_nntp_list_active (f_nntp->nntp, m_nntp->name, &iterator);
if (status == 0)
{
for (iterator_first (iterator);
!iterator_is_done (iterator); iterator_next (iterator))
{
char *buffer = NULL;
iterator_current (iterator, (void **) &buffer);
mu_nntp_parse_list_active (buffer, NULL, &m_nntp->high, &m_nntp->low, &m_nntp->status);
}
iterator_destroy (&iterator);
}
return status;
}
/* We can not close the folder in term of shuting down the connection but if
we were the selected mailbox/newsgroup we deselect ourself. */
static int
nntp_mailbox_close (mailbox_t mailbox)
{
m_nntp_t m_nntp = mailbox->data;
f_nntp_t f_nntp = m_nntp->f_nntp;
int i;
monitor_wrlock (mailbox->monitor);
/* Destroy the nntp posts and ressources associated to them. */
for (i = 0; i < m_nntp->messages_count; i++)
{
if (m_nntp->messages[i])
{
msg_nntp_t msg_nntp = m_nntp->messages[i];
if (msg_nntp->message)
message_destroy (&(msg_nntp->message), msg_nntp);
}
free (m_nntp->messages[i]);
}
if (m_nntp->messages)
free (m_nntp->messages);
m_nntp->messages = NULL;
m_nntp->messages_count = 0;
m_nntp->number = 0;
m_nntp->low = 0;
m_nntp->high = 0;
monitor_unlock (mailbox->monitor);
/* Deselect. */
if (m_nntp != f_nntp->selected)
f_nntp->selected = NULL;
/* Decrement the ref count. */
return folder_close (mailbox->folder);
}
static int
nntp_mailbox_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
{
m_nntp_t m_nntp = mbox->data;
f_nntp_t f_nntp = m_nntp->f_nntp;
msg_nntp_t msg_nntp;
message_t msg = NULL;
int status;
size_t i;
/* Sanity. */
if (pmsg == NULL)
return MU_ERR_OUT_PTR_NULL;
msgno--;
monitor_rdlock (mbox->monitor);
/* See if we have already this message. */
for (i = 0; i < m_nntp->messages_count; i++)
{
if (m_nntp->messages[i])
{
if (m_nntp->messages[i]->msgno == msgno + m_nntp->low)
{
*pmsg = m_nntp->messages[i]->message;
monitor_unlock (mbox->monitor);
return 0;
}
}
}
monitor_unlock (mbox->monitor);
msg_nntp = calloc (1, sizeof (*msg_nntp));
if (msg_nntp == NULL)
return ENOMEM;
/* Back pointer. */
msg_nntp->m_nntp = m_nntp;
msg_nntp->msgno = msgno + m_nntp->low;
/* Create the message. */
{
stream_t stream = NULL;
if ((status = message_create (&msg, msg_nntp)) != 0
|| (status = stream_create (&stream, mbox->flags, msg)) != 0)
{
stream_destroy (&stream, msg);
message_destroy (&msg, msg_nntp);
free (msg_nntp);
return status;
}
/* Help for the readline()s */
stream_set_read (stream, nntp_message_read, msg);
stream_set_get_transport2 (stream, nntp_message_get_transport2, msg);
message_set_stream (msg, stream, msg_nntp);
message_set_size (msg, nntp_message_size, msg_nntp);
}
/* Create the header. */
{
header_t header = NULL;
if ((status = header_create (&header, NULL, 0, msg)) != 0)
{
message_destroy (&msg, msg_nntp);
free (msg_nntp);
return status;
}
header_set_fill (header, nntp_header_fill, msg);
message_set_header (msg, header, msg_nntp);
}
/* Create the body and its stream. */
{
body_t body = NULL;
stream_t stream = NULL;
if ((status = body_create (&body, msg)) != 0
|| (status = stream_create (&stream, mbox->flags, body)) != 0)
{
body_destroy (&body, msg);
stream_destroy (&stream, body);
message_destroy (&msg, msg_nntp);
free (msg_nntp);
return status;
}
/* Helps for the readline()s */
stream_set_read (stream, nntp_body_read, body);
stream_set_get_transport2 (stream, nntp_body_get_transport2, body);
body_set_size (body, nntp_body_size, msg);
body_set_lines (body, nntp_body_lines, msg);
body_set_stream (body, stream, msg);
message_set_body (msg, body, msg_nntp);
}
/* Set the UID on the message. */
message_set_uid (msg, nntp_message_uid, msg_nntp);
/* Add it to the list. */
monitor_wrlock (mbox->monitor);
{
msg_nntp_t *m ;
m = realloc (m_nntp->messages, (m_nntp->messages_count + 1)*sizeof (*m));
if (m == NULL)
{
message_destroy (&msg, msg_nntp);
free (msg_nntp);
monitor_unlock (mbox->monitor);
return ENOMEM;
}
m_nntp->messages = m;
m_nntp->messages[m_nntp->messages_count] = msg_nntp;
m_nntp->messages_count++;
}
monitor_unlock (mbox->monitor);
/* Save The message pointer. */
message_set_mailbox (msg, mbox, msg_nntp);
*pmsg = msg_nntp->message = msg;
return 0;
}
/* There is no explicit call to get the message count. The count is send on
a "GROUP" command. The function is also use as a way to select newsgoupr by other functions. */
static int
nntp_mailbox_messages_count (mailbox_t mbox, size_t *pcount)
{
m_nntp_t m_nntp = mbox->data;
f_nntp_t f_nntp = m_nntp->f_nntp;
int status = 0;
status = folder_open (mbox->folder, mbox->flags);
if (status != 0)
return status;
/* Are we already selected ? */
if (m_nntp == (f_nntp->selected))
{
if (pcount)
*pcount = m_nntp->number;
return 0;
}
/* Put the mailbox as selected. */
f_nntp->selected = m_nntp;
status = mu_nntp_group (f_nntp->nntp, m_nntp->name, &m_nntp->number, &m_nntp->low, &m_nntp->high, NULL);
if (pcount)
*pcount = m_nntp->number;
return status;
}
/* Update and scanning. */
static int
nntp_is_updated (mailbox_t mbox)
{
return 1;
}
/* We just simulate by sending a notification for the total msgno. */
/* FIXME is message is set deleted should we sent a notif ? */
static int
nntp_mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
{
int status;
size_t i;
size_t count = 0;
/* Select first. */
status = nntp_mailbox_messages_count (mbox, &count);
if (pcount)
*pcount = count;
if (status != 0)
return status;
if (mbox->observable == NULL)
return 0;
for (i = msgno; i <= count; i++)
{
if (observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD) != 0)
break;
if (((i +1) % 10) == 0)
{
observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS);
}
}
return 0;
}
static int
nntp_message_size (message_t msg, size_t *psize)
{
if (psize)
*psize = 0;
return 0;
}
static int
nntp_body_size (body_t body, size_t *psize)
{
if (psize)
*psize = 0;
return 0;
}
/* Not know until the whole message get downloaded. */
static int
nntp_body_lines (body_t body, size_t *plines)
{
if (plines)
*plines = 0;
return 0;
}
/* Stub to call the fd from body object. */
static int
nntp_body_get_transport2 (stream_t stream, mu_transport_t *pin, mu_transport_t *pout)
{
body_t body = stream_get_owner (stream);
message_t msg = body_get_owner (body);
msg_nntp_t msg_nntp = message_get_owner (msg);
return nntp_get_transport2 (msg_nntp, pin, pout);
}
/* Stub to call the fd from message object. */
static int
nntp_message_get_transport2 (stream_t stream, mu_transport_t *pin, mu_transport_t *pout)
{
message_t msg = stream_get_owner (stream);
msg_nntp_t msg_nntp = message_get_owner (msg);
return nntp_get_transport2 (msg_nntp, pin, pout);
}
static int
nntp_get_transport2 (msg_nntp_t msg_nntp, mu_transport_t *pin, mu_transport_t *pout)
{
int status = EINVAL;
if (msg_nntp && msg_nntp->m_nntp
&& msg_nntp->m_nntp->f_nntp && msg_nntp->m_nntp->f_nntp->folder)
{
stream_t carrier;
status = mu_nntp_get_carrier (msg_nntp->m_nntp->f_nntp->nntp, &carrier);
if (status == 0)
return stream_get_transport2 (carrier, pin, pout);
}
return status;
}
static int
nntp_message_uid (message_t msg, size_t *puid)
{
msg_nntp_t msg_nntp = message_get_owner (msg);
m_nntp_t m_nntp = msg_nntp->m_nntp;
f_nntp_t f_nntp = m_nntp->f_nntp;
int status;
if (puid)
return 0;
/* Select first. */
status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL);
if (status != 0)
return status;
if (puid)
*puid = msg_nntp->msgno;
return 0;
}
static int
nntp_message_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten)
{
msg_nntp_t msg_nntp = message_get_owner (msg);
m_nntp_t m_nntp = msg_nntp->m_nntp;
f_nntp_t f_nntp = m_nntp->f_nntp;
int status = 0;
/* Select first. */
status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL);
if (status != 0)
return status;
if (msg_nntp->mid)
{
size_t len = strlen (msg_nntp->mid);
if (buffer)
{
buflen--; /* Leave space for the null. */
buflen = (len > buflen) ? buflen : len;
memcpy (buffer, msg_nntp->mid, buflen);
buffer[buflen] = '\0';
}
else
buflen = len;
}
else
buflen = 0;
if (pnwriten)
*pnwriten = buflen;
return status;
}
/* Message read overload */
static int
nntp_message_read (stream_t stream, char *buffer, size_t buflen, off_t offset, size_t *plen)
{
message_t msg = stream_get_owner (stream);
msg_nntp_t msg_nntp = message_get_owner (msg);
m_nntp_t m_nntp = msg_nntp->m_nntp;
f_nntp_t f_nntp = m_nntp->f_nntp;
int status;
size_t len = 0;
/* Start over. */
if (plen == NULL)
plen = &len;
/* Select first. */
status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL);
if (status != 0)
return status;
if (msg_nntp->mstream == NULL)
{
status = mu_nntp_article (f_nntp->nntp, msg_nntp->msgno, NULL, &msg_nntp->mid, &msg_nntp->mstream);
if (status != 0)
return status;
}
status = stream_read (msg_nntp->mstream, buffer, buflen, offset, plen);
if (status == 0)
{
/* Destroy the stream. */
if (*plen == 0)
{
stream_destroy (&msg_nntp->mstream, NULL);
}
}
return status;
}
/* Message read overload */
static int
nntp_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset, size_t *plen)
{
body_t body = stream_get_owner (stream);
message_t msg = body_get_owner (body);
msg_nntp_t msg_nntp = message_get_owner (msg);
m_nntp_t m_nntp = msg_nntp->m_nntp;
f_nntp_t f_nntp = m_nntp->f_nntp;
int status;
size_t len = 0;
/* Start over. */
if (plen == NULL)
plen = &len;
/* Select first. */
status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL);
if (status != 0)
return status;
if (msg_nntp->bstream == NULL)
{
status = mu_nntp_body (f_nntp->nntp, msg_nntp->msgno, NULL, &msg_nntp->mid, &msg_nntp->bstream);
if (status != 0)
return status;
}
status = stream_read (msg_nntp->bstream, buffer, buflen, offset, plen);
if (status == 0)
{
/* Destroy the stream. */
if (*plen == 0)
{
stream_destroy (&msg_nntp->bstream, NULL);
}
}
return status;
}
/* Header read overload */
static int
nntp_header_fill (header_t header, char *buffer, size_t buflen, off_t offset, size_t *plen)
{
message_t msg = header_get_owner (header);
msg_nntp_t msg_nntp = message_get_owner (msg);
m_nntp_t m_nntp = msg_nntp->m_nntp;
f_nntp_t f_nntp = m_nntp->f_nntp;
int status;
size_t len = 0;
/* Start over. */
if (plen == NULL)
plen = &len;
/* Select first. */
status = nntp_mailbox_messages_count (m_nntp->mailbox, NULL);
if (status != 0)
return status;
if (msg_nntp->hstream == NULL)
{
status = mu_nntp_head (f_nntp->nntp, msg_nntp->msgno, NULL, &msg_nntp->mid, &msg_nntp->hstream);
if (status != 0)
return status;
}
status = stream_read (msg_nntp->hstream, buffer, buflen, offset, plen);
if (status == 0)
{
/* Destroy the stream. */
if (*plen == 0)
{
stream_destroy (&msg_nntp->hstream, NULL);
}
}
return status;
}
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
struct _nntp_folder;
struct _nntp_mailbox;
struct _nntp_message;
typedef struct _nntp_folder *f_nntp_t;
typedef struct _nntp_mailbox *m_nntp_t;
typedef struct _nntp_message *msg_nntp_t;
extern int _nntp_url_init __P ((url_t));
extern int _nntp_mailbox_init __P ((mailbox_t));
extern int _nntp_folder_init __P ((folder_t));
struct _nntp_folder
{
/* Refcount. */
int isopen;
/* Back pointer. */
folder_t folder;
/* Selected newsgroup. */
m_nntp_t selected;
/* NNTP object. */
mu_nntp_t nntp;
};
struct _nntp_mailbox
{
char status;
char *name;
/* Pointer back to the mailbox/newsgroup. */
mailbox_t mailbox;
/* Our nntp folder. */
f_nntp_t f_nntp;
/* Read Messages on the newsgroup. */
msg_nntp_t *messages;
size_t messages_count;
/* Estimated number of articles in the group. */
unsigned long number;
/* High water mark from "GROUP" command */
unsigned long high;
/* Low water mark from "GROUP" command */
unsigned long low;
};
struct _nntp_message
{
/* Back pointer. */
message_t message;
/* Our nntp folder. */
m_nntp_t m_nntp;
/* Message id. */
char *mid;
/* mesgno of the post. */
unsigned long msgno;
/* Stream for message. */
stream_t mstream;
/* Stream for body. */
stream_t bstream;
/* Stream for header. */
stream_t hstream;
};
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef ENABLE_NNTP
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <mailutils/nntp.h>
#include <url0.h>
static void url_nntp_destroy (url_t url);
static void
url_nntp_destroy (url_t url ARG_UNUSED)
{
}
/*
POP URL:
nntp://<host>:<port>/<newsgroup-name>/<article-number>
*/
int
_nntp_url_init (url_t url)
{
int status = 0;
url->_destroy = url_nntp_destroy;
status = url_parse(url);
if(status)
return status;
/* is it nntp? */
if (strcmp (MU_NNTP_URL_SCHEME, url->scheme) != 0)
return EINVAL;
/* not valid in a nntp url */
if (!url->host || !url->path)
return EINVAL;
if (url->port == 0)
url->port = MU_NNTP_DEFAULT_PORT;
return status;
}
#endif