Commit 87f5761f 87f5761f9c0289afc5d485cdd270c1749f55f69f by Alain Magloire

Adding more framework for NNTP support.

1 parent ecccf28a
......@@ -35,10 +35,20 @@ libmu_nntp_la_SOURCES = \
nntp_disconnect.c \
nntp_group.c \
nntp_head.c \
nntp_help.c \
nntp_ihave.c \
nntp_last.c \
nntp_list_active.c \
nntp_list_distribpats.c \
nntp_list_distributions.c \
nntp_list_extensions.c \
nntp_list_newsgroups.c \
nntp_list_times.c \
nntp_mode_reader.c \
nntp_newgroups.c \
nntp_newnews.c \
nntp_next.c \
nntp_post.c \
nntp_quit.c \
nntp_readline.c \
nntp_response.c \
......
......@@ -20,6 +20,7 @@
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
......
......@@ -20,6 +20,7 @@
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
......
......@@ -40,7 +40,7 @@ mu_nntp_connect (mu_nntp_t nntp)
if (nntp->carrier == NULL)
return EINVAL;
/* Enter the pop state machine, and boogy: AUTHORISATION State. */
/* Enter the nntp state machine, and boogy */
switch (nntp->state)
{
default:
......@@ -69,9 +69,9 @@ mu_nntp_connect (mu_nntp_t nntp)
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
/* 200 Service available, posting allowed */
/* 2001 Servie available, posting prohibited */
/* 201 Servie available, posting prohibited */
code = mu_nntp_response_code(nntp);
if (code == MU_NNTP_RESP_CODE_POSTING_ALLOWED || code == MU_NNTP_RESP_CODE_POSTING_PROHIBITED)
if (code != MU_NNTP_RESP_CODE_POSTING_ALLOWED && code != MU_NNTP_RESP_CODE_POSTING_PROHIBITED)
{
stream_close (nntp->carrier);
nntp->state = MU_NNTP_NO_STATE;
......
......@@ -23,6 +23,10 @@
#include <errno.h>
#include <mailutils/sys/nntp.h>
static int
mu_nntp_parse_date (mu_nntp_t nntp, int code, unsigned int *year, unsigned int *month, unsigned int *day,
unsigned int *hour, unsigned int *min, unsigned int *sec);
int
mu_nntp_date (mu_nntp_t nntp, unsigned int *year, unsigned int *month, unsigned int *day,
unsigned int *hour, unsigned int *min, unsigned int *sec)
......@@ -56,7 +60,7 @@ mu_nntp_date (mu_nntp_t nntp, unsigned int *year, unsigned int *month, unsigned
nntp->state = MU_NNTP_NO_STATE;
/* parse the answer now. */
status = mu_parse_date(nntp, MU_NNTP_RESP_CODE_SERVER_DATE, year, month, day, hour, min, sec);
status = mu_nntp_parse_date(nntp, MU_NNTP_RESP_CODE_SERVER_DATE, year, month, day, hour, min, sec);
MU_NNTP_CHECK_ERROR (nntp, status);
break;
......
......@@ -42,6 +42,9 @@ mu_nntp_destroy (mu_nntp_t *pnntp)
if (nntp->carrier)
stream_destroy (&nntp->carrier, nntp);
/* Any posting residue. */
if (nntp->post.buf)
free (nntp->post.buf);
free (nntp);
*pnntp = NULL;
......
......@@ -24,6 +24,8 @@
#include <stdlib.h>
#include <mailutils/sys/nntp.h>
static int mu_nntp_parse_group(mu_nntp_t nntp, int code, unsigned long *ptotal, unsigned long *plow, unsigned long *phigh, char **name);
int
mu_nntp_group (mu_nntp_t nntp, const char *group, unsigned long *total, unsigned long *low, unsigned long *high, char **name)
{
......@@ -72,8 +74,7 @@ mu_nntp_group (mu_nntp_t nntp, const char *group, unsigned long *total, unsigned
return status;
}
int
static int
mu_nntp_parse_group(mu_nntp_t nntp, int code, unsigned long *ptotal, unsigned long *plow, unsigned long *phigh, char **name)
{
unsigned long dummy = 0;
......
......@@ -20,6 +20,7 @@
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 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
#include <string.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_help (mu_nntp_t nntp, stream_t *pstream)
{
int status;
if (nntp == NULL)
return EINVAL;
if (pstream == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "HELP\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_HELP;
case MU_NNTP_HELP:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_HELP_ACK;
case MU_NNTP_HELP_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_HELP_FOLLOW);
nntp->state = MU_NNTP_HELP_RX;
case MU_NNTP_HELP_RX:
status = mu_nntp_stream_create (nntp, pstream);
MU_NNTP_CHECK_ERROR (nntp, status);
break;
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 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
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_ihave (mu_nntp_t nntp, const char *mid, stream_t stream)
{
int status;
unsigned long dummy = 0;
char *buf;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "IHAVE %s\r\n", mid);
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_IHAVE;
case MU_NNTP_IHAVE:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_IHAVE_ACK;
case MU_NNTP_IHAVE_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_TRANSFER_ARTICLE);
if (nntp->post.buf != NULL)
{
free (nntp->post.buf);
}
nntp->post.buf = calloc (1, 256);
if (nntp->post.buf == NULL)
{
MU_NNTP_CHECK_ERROR (nntp, ENOMEM);
}
nntp->post.len = 256;
nntp->post.offset = 0;
nntp->post.nread = 0;
nntp->post.sent_crlf = 0;
nntp->state = MU_NNTP_IHAVE_0;
ihave_loop:
case MU_NNTP_IHAVE_0:
status = stream_readline (stream, nntp->post.buf, nntp->post.len, nntp->post.offset, &(nntp->post.nread));
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->post.offset += nntp->post.nread;
if (nntp->post.nread > 0)
{
if (nntp->post.buf[nntp->post.nread - 1] == '\n')
{
nntp->post.buf[nntp->post.nread - 1] = '\0';
if (nntp->post.sent_crlf && nntp->post.buf[0] == '.')
{
status = mu_nntp_writeline (nntp, ".%s\r\n", nntp->post.buf);
}
else
{
status = mu_nntp_writeline (nntp, "%s\r\n", nntp->post.buf);
}
nntp->post.sent_crlf = 1;
}
else
{
if (nntp->post.sent_crlf && nntp->post.buf[0] == '.')
{
status = mu_nntp_writeline (nntp, ".%s", nntp->post.buf);
}
else
{
status = mu_nntp_writeline (nntp, "%s", nntp->post.buf);
}
nntp->post.sent_crlf = 0;
}
MU_NNTP_CHECK_ERROR (nntp, status);
}
nntp->state = MU_NNTP_IHAVE_1;
case MU_NNTP_IHAVE_1:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
if (nntp->post.nread > 0)
{
goto ihave_loop;
}
if (nntp->post.sent_crlf)
status = mu_nntp_writeline (nntp, ".\r\n");
else
status = mu_nntp_writeline (nntp, "\r\n.\r\n");
if (nntp->post.buf != NULL)
{
free (nntp->post.buf);
nntp->post.buf = NULL;
nntp->post.len = 0;
nntp->post.offset = 0;
nntp->post.nread = 0;
nntp->post.sent_crlf = 0;
}
MU_NNTP_CHECK_ERROR (nntp, status);
nntp->state = MU_NNTP_IHAVE_2;
case MU_NNTP_POST_2:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_IHAVE_3;
case MU_NNTP_POST_3:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_TRANSFER_OK);
nntp->state = MU_NNTP_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
/* 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
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/error.h>
#include <mailutils/sys/nntp.h>
/*
LIST xxxx command, return a list that contains the result.
It is the responsability of the caller to destroy the list(list_destroy).
*/
int
mu_nntp_list_distrib_pats (mu_nntp_t nntp, list_t *plist)
{
int status;
if (nntp == NULL)
return EINVAL;
if (plist == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "LIST DISTRIB.PATS\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_LIST_DISTRIB_PATS;
case MU_NNTP_LIST_DISTRIB_PATS:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_LIST_DISTRIB_PATS_ACK;
case MU_NNTP_LIST_DISTRIB_PATS_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_LIST_FOLLOW);
status = list_create (plist);
MU_NNTP_CHECK_ERROR(nntp, status);
list_set_destroy_item(*plist, free);
nntp->state = MU_NNTP_LIST_DISTRIB_PATS_RX;
case MU_NNTP_LIST_DISTRIB_PATS_RX:
{
/* line are 512 octets maximum according to RFC. */
char *distributions;
size_t n = 0;
distributions = malloc (512);
if (distributions == NULL)
{
/* MU_NNTP_CHECK_ERROR(nntp, ENOMEM);
We need to destroy the list if error. */
nntp->io.ptr = nntp->io.buf;
nntp->state = MU_NNTP_ERROR;
list_destroy (*plist);
return ENOMEM;
}
while ((status = mu_nntp_readline (nntp, distributions, 512, &n)) == 0 && n > 0)
{
/* Nuke the trailing newline */
if (distributions[n - 1] == '\n')
distributions[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (distributions));
n = 0;
}
free (distributions);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_NO_STATE;
break;
}
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
int
mu_nntp_parse_list_distrib_pats (const char *buffer, unsigned long *weight, char **wildmat, char **distrib)
{
char *w;
char *d;
unsigned long dummy;
if (buffer == NULL || *buffer == '\0')
return EINVAL;
w = calloc(512, 1);
if (w == NULL)
return ENOMEM;
d = calloc(512, 1);
if (d == NULL)
{
free (w);
return ENOMEM;
}
if (weight == NULL)
weight = &dummy;
sscanf (buffer, "%ld:%511s:%511s", weight, w, d);
if (wildmat == NULL)
free (w);
else
*wildmat = w;
if (distrib == NULL)
free (d);
else
*distrib = d;
return 0;
}
/* 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
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/error.h>
#include <mailutils/sys/nntp.h>
/*
LIST xxxx command, return a list that contains the result.
It is the responsability of the caller to destroy the list(list_destroy).
*/
int
mu_nntp_list_distributions (mu_nntp_t nntp, const char *wildmat, list_t *plist)
{
int status;
if (nntp == NULL)
return EINVAL;
if (plist == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
if (wildmat == NULL || *wildmat == '\0')
status = mu_nntp_writeline (nntp, "LIST DISTRIBUTIONS\r\n");
else
status = mu_nntp_writeline (nntp, "LIST DISTRIBUTIONS %s\r\n", wildmat);
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_LIST_DISTRIBUTIONS;
case MU_NNTP_LIST_DISTRIBUTIONS:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_LIST_DISTRIBUTIONS_ACK;
case MU_NNTP_LIST_DISTRIBUTIONS_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_LIST_FOLLOW);
status = list_create (plist);
MU_NNTP_CHECK_ERROR(nntp, status);
list_set_destroy_item(*plist, free);
nntp->state = MU_NNTP_LIST_DISTRIBUTIONS_RX;
case MU_NNTP_LIST_DISTRIBUTIONS_RX:
{
/* line are 512 octets maximum according to RFC. */
char *distributions;
size_t n = 0;
distributions = malloc (512);
if (distributions == NULL)
{
/* MU_NNTP_CHECK_ERROR(nntp, ENOMEM);
We need to destroy the list if error. */
nntp->io.ptr = nntp->io.buf;
nntp->state = MU_NNTP_ERROR;
list_destroy (*plist);
return ENOMEM;
}
while ((status = mu_nntp_readline (nntp, distributions, 512, &n)) == 0 && n > 0)
{
/* Nuke the trailing newline */
if (distributions[n - 1] == '\n')
distributions[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (distributions));
n = 0;
}
free (distributions);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_NO_STATE;
break;
}
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
int
mu_nntp_parse_list_distributions (const char *buffer, char **key, char **value)
{
char *k;
char *v;
if (buffer == NULL || *buffer == '\0')
return EINVAL;
k = calloc(512, 1);
if (k == NULL)
return ENOMEM;
v = calloc(512, 1);
if (v == NULL)
{
free (k);
return ENOMEM;
}
sscanf (buffer, "%511s %511s", k, v);
if (key == NULL)
free (k);
else
*key = k;
if (value == NULL)
free (v);
else
*value = v;
return 0;
}
......@@ -59,7 +59,7 @@ mu_nntp_list_extensions (mu_nntp_t nntp, list_t *plist)
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_LIST_FOLLOW);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_EXTENSIONS_FOLLOW);
status = list_create (plist);
MU_NNTP_CHECK_ERROR(nntp, status);
list_set_destroy_item(*plist, free);
......
/* 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
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/error.h>
#include <mailutils/sys/nntp.h>
/*
LIST NEWSGROUPS command, return a list that contains the result.
It is the responsability of the caller to destroy the list(list_destroy).
*/
int
mu_nntp_list_newsgroups (mu_nntp_t nntp, const char *wildmat, list_t *plist)
{
int status;
if (nntp == NULL)
return EINVAL;
if (plist == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
if (wildmat == NULL || *wildmat == '\0')
status = mu_nntp_writeline (nntp, "LIST NEWSGROUPS\r\n");
else
status = mu_nntp_writeline (nntp, "LIST NEWSGROUPS %s\r\n", wildmat);
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_LIST_NEWSGROUPS;
case MU_NNTP_LIST_NEWSGROUPS:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_LIST_NEWSGROUPS_ACK;
case MU_NNTP_LIST_NEWSGROUPS_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_LIST_FOLLOW);
status = list_create (plist);
MU_NNTP_CHECK_ERROR(nntp, status);
list_set_destroy_item(*plist, free);
nntp->state = MU_NNTP_LIST_NEWSGROUPS_RX;
case MU_NNTP_LIST_NEWSGROUPS_RX:
{
/* line are 512 octets maximum according to RFC. */
char *newsgroups;
size_t n = 0;
newsgroups = malloc (512);
if (newsgroups == NULL)
{
/* MU_NNTP_CHECK_ERROR(nntp, ENOMEM);
We need to destroy the list if error. */
nntp->io.ptr = nntp->io.buf;
nntp->state = MU_NNTP_ERROR;
list_destroy (*plist);
return ENOMEM;
}
while ((status = mu_nntp_readline (nntp, newsgroups, 512, &n)) == 0 && n > 0)
{
/* Nuke the trailing newline */
if (newsgroups[n - 1] == '\n')
newsgroups[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (newsgroups));
n = 0;
}
free (newsgroups);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_NO_STATE;
break;
}
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
int
mu_nntp_parse_list_newsgroups (const char *buffer, char **group, char **description)
{
char *name;
char *desc;
if (buffer == NULL || *buffer == '\0')
return EINVAL;
name = calloc(512, 1);
if (name == NULL)
return ENOMEM;
desc = calloc(512, 1);
if (desc == NULL)
{
free (name);
return ENOMEM;
}
sscanf (buffer, "%511s %511s", name, desc);
if (group == NULL)
free (name);
else
*group = name;
if (description == NULL)
free (desc);
else
*description = desc;
return 0;
}
/* 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
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/error.h>
#include <mailutils/sys/nntp.h>
/*
LIST EXTENSIONS command, return a list that contains the result.
It is the responsability of the caller to destroy the list(list_destroy).
*/
int
mu_nntp_list_active_times (mu_nntp_t nntp, const char *wildmat, list_t *plist)
{
int status;
if (nntp == NULL)
return EINVAL;
if (plist == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
if (wildmat == NULL || *wildmat == '\0')
status = mu_nntp_writeline (nntp, "LIST ACTIVE.TIMES\r\n");
else
status = mu_nntp_writeline (nntp, "LIST ACTIVE.TIMES %s\r\n", wildmat);
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_LIST_ACTIVE_TIMES;
case MU_NNTP_LIST_ACTIVE_TIMES:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_LIST_ACTIVE_TIMES_ACK;
case MU_NNTP_LIST_ACTIVE_TIMES_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_LIST_FOLLOW);
status = list_create (plist);
MU_NNTP_CHECK_ERROR(nntp, status);
list_set_destroy_item(*plist, free);
nntp->state = MU_NNTP_LIST_ACTIVE_TIMES_RX;
case MU_NNTP_LIST_ACTIVE_TIMES_RX:
{
/* line are 512 octets maximum according to RFC. */
char *active;
size_t n = 0;
active = malloc (512);
if (active == NULL)
{
/* MU_NNTP_CHECK_ERROR(nntp, ENOMEM);
We need to destroy the list if error. */
nntp->io.ptr = nntp->io.buf;
nntp->state = MU_NNTP_ERROR;
list_destroy (*plist);
return ENOMEM;
}
while ((status = mu_nntp_readline (nntp, active, 512, &n)) == 0 && n > 0)
{
/* Nuke the trailing newline */
if (active[n - 1] == '\n')
active[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (active));
n = 0;
}
free (active);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_NO_STATE;
break;
}
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
int
mu_nntp_parse_list_active_times (const char *buffer, char **group, unsigned long *time, char **creator)
{
unsigned long dummy;
char *name;
char *owner;
if (buffer == NULL || *buffer == '\0')
return EINVAL;
name = calloc(512, 1);
if (name == NULL)
return ENOMEM;
owner = calloc(512, 1);
if (owner == NULL)
{
free (name);
return ENOMEM;
}
if (time == NULL)
time = &dummy;
sscanf (buffer, "%511s %ld %511s", name, time, owner);
if (group == NULL)
free (name);
else
*group = name;
if (creator == NULL)
free (owner);
else
*creator = owner;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 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
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_newgroups (mu_nntp_t nntp, unsigned int year, unsigned int month, unsigned int day,
unsigned int hour, unsigned int minute, unsigned int second, int is_gmt, list_t *plist)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
if (is_gmt > 0)
status = mu_nntp_writeline (nntp, "NEWGROUPS %.4d%.2d%.2d %.2d%.2d%.2d GMT\r\n", year, month, day, hour, minute, second);
else
status = mu_nntp_writeline (nntp, "NEWGROUPS %.4d%.2d%.2d %.2d%.2d%.2d\r\n", year, month, day, hour, minute, second);
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_NEWGROUPS;
case MU_NNTP_NEWGROUPS:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_NEWGROUPS_ACK;
case MU_NNTP_NEWGROUPS_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_NEWGROUPS_FOLLOW);
status = list_create (plist);
MU_NNTP_CHECK_ERROR(nntp, status);
list_set_destroy_item(*plist, free);
nntp->state = MU_NNTP_NEWGROUPS_RX;
case MU_NNTP_NEWGROUPS_RX:
{
/* line should not be over 512 octets maximum. */
char *lista;
size_t n = 0;
lista = malloc (512);
if (lista == NULL)
{
/* MU_NNTP_CHECK_ERROR(nntp, ENOMEM);
Do not use the macro we need to clear the list if errors. */
nntp->io.ptr = nntp->io.buf;
nntp->state = MU_NNTP_ERROR;
list_destroy (plist);
return ENOMEM;
}
while ((status = mu_nntp_readline (nntp, lista, 512, &n)) == 0 && n > 0)
{
/* Nuke the trailing newline */
if (lista[n - 1] == '\n')
lista[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (lista));
n = 0;
}
free (lista);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_NO_STATE;
break;
}
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
int
mu_nntp_parse_newgroups (const char *buffer, char **group, unsigned long *high, unsigned long *low, char *status)
{
return mu_nntp_parse_list_active (buffer, group, high, low, status);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 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
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_newnews (mu_nntp_t nntp, const char *wildmat, unsigned int year, unsigned int month, unsigned int day,
unsigned int hour, unsigned int minute, unsigned int second, int is_gmt, list_t *plist)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
if (wildmat == NULL || *wildmat == '\0')
{
if (is_gmt > 0)
status = mu_nntp_writeline (nntp, "NEWNEWS %.4d%.2d%.2d %.2d%.2d%.2d GMT\r\n", year, month, day, hour, minute, second);
else
status = mu_nntp_writeline (nntp, "NEWNEWS %.4d%.2d%.2d %.2d%.2d%.2d\r\n", year, month, day, hour, minute, second);
}
else
{
if (is_gmt > 0)
{
status = mu_nntp_writeline (nntp, "NEWNEWS %s %.4d%.2d%.2d %.2d%.2d%.2d GMT\r\n", wildmat, year, month, day,
hour, minute, second);
}
else
{
status = mu_nntp_writeline (nntp, "NEWNEWS %s %.4d%.2d%.2d %.2d%.2d%.2d\r\n", wildmat, year, month, day,
hour, minute, second);
}
}
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_NEWNEWS;
case MU_NNTP_NEWNEWS:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_NEWNEWS_ACK;
case MU_NNTP_NEWNEWS_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_NEWNEWS_FOLLOW);
status = list_create (plist);
MU_NNTP_CHECK_ERROR(nntp, status);
list_set_destroy_item(*plist, free);
nntp->state = MU_NNTP_NEWNEWS_RX;
case MU_NNTP_NEWNEWS_RX:
{
/* line should not be over 512 octets maximum. */
char *lista;
size_t n = 0;
lista = malloc (512);
if (lista == NULL)
{
/* MU_NNTP_CHECK_ERROR(nntp, ENOMEM);
Do not use the macro we need to clear the list if errors. */
nntp->io.ptr = nntp->io.buf;
nntp->state = MU_NNTP_ERROR;
list_destroy (plist);
return ENOMEM;
}
while ((status = mu_nntp_readline (nntp, lista, 512, &n)) == 0 && n > 0)
{
/* Nuke the trailing newline */
if (lista[n - 1] == '\n')
lista[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (lista));
n = 0;
}
free (lista);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_NO_STATE;
break;
}
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 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
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_post (mu_nntp_t nntp, stream_t stream)
{
int status;
unsigned long dummy = 0;
char *buf;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "POST\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_POST;
case MU_NNTP_POST:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_POST_ACK;
case MU_NNTP_POST_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_SEND_ARTICLE);
if (nntp->post.buf != NULL)
{
free (nntp->post.buf);
}
nntp->post.buf = calloc (1, 256);
if (nntp->post.buf == NULL)
{
MU_NNTP_CHECK_ERROR (nntp, ENOMEM);
}
nntp->post.len = 256;
nntp->post.offset = 0;
nntp->post.nread = 0;
nntp->post.sent_crlf = 0;
nntp->state = MU_NNTP_POST_0;
post_loop:
case MU_NNTP_POST_0:
status = stream_readline (stream, nntp->post.buf, nntp->post.len, nntp->post.offset, &(nntp->post.nread));
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->post.offset += nntp->post.nread;
if (nntp->post.nread > 0)
{
if (nntp->post.buf[nntp->post.nread - 1] == '\n')
{
nntp->post.buf[nntp->post.nread - 1] = '\0';
if (nntp->post.sent_crlf && nntp->post.buf[0] == '.')
{
status = mu_nntp_writeline (nntp, ".%s\r\n", nntp->post.buf);
}
else
{
status = mu_nntp_writeline (nntp, "%s\r\n", nntp->post.buf);
}
nntp->post.sent_crlf = 1;
}
else
{
if (nntp->post.sent_crlf && nntp->post.buf[0] == '.')
{
status = mu_nntp_writeline (nntp, ".%s", nntp->post.buf);
}
else
{
status = mu_nntp_writeline (nntp, "%s", nntp->post.buf);
}
nntp->post.sent_crlf = 0;
}
MU_NNTP_CHECK_ERROR (nntp, status);
}
nntp->state = MU_NNTP_POST_1;
case MU_NNTP_POST_1:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
if (nntp->post.nread > 0)
{
goto post_loop;
}
if (nntp->post.sent_crlf)
status = mu_nntp_writeline (nntp, ".\r\n");
else
status = mu_nntp_writeline (nntp, "\r\n.\r\n");
if (nntp->post.buf != NULL)
{
free (nntp->post.buf);
nntp->post.buf = NULL;
nntp->post.len = 0;
nntp->post.offset = 0;
nntp->post.nread = 0;
nntp->post.sent_crlf = 0;
}
MU_NNTP_CHECK_ERROR (nntp, status);
nntp->state = MU_NNTP_POST_2;
case MU_NNTP_POST_2:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_POST_3;
case MU_NNTP_POST_3:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_ARTICLE_RECEIVED);
nntp->state = MU_NNTP_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......@@ -20,6 +20,7 @@
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
......
......@@ -24,7 +24,7 @@
#include <stdlib.h>
#include <mailutils/sys/nntp.h>
/* Implementation of the stream for TOP and RETR. */
/* Implementation of the stream for HELP, ARTICLE, etc ... */
struct mu_nntp_stream
{
mu_nntp_t nntp;
......