Commit 841783ac 841783ac72068a4b1f8762227afa72cc46ce845c by Sergey Poznyakoff

Moved from mailbox

1 parent 5d0c69dd
Showing 93 changed files with 4936 additions and 0 deletions
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
T
_*
.gdbinit
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or (at
## your option) any later version.
##
## This program 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
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
INCLUDES = @MU_COMMON_INCLUDES@ -I${top_srcdir}/libproto/include @INTLINCS@
lib_LTLIBRARIES = libmu_imap.la
libmu_imap_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_imap_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@
libmu_imap_la_SOURCES = \
folder.c\
mbox.c\
url.c
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2003 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef ENABLE_IMAP
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <registrar0.h>
#include <url0.h>
static void url_imap_destroy (mu_url_t url);
static void
url_imap_destroy (mu_url_t url ARG_UNUSED)
{
}
/*
IMAP URL:
imap://[<user>[;AUTH=<auth>]@]<host>[/<mailbox>]
else
imap://[<user>[:<pass>]@]<host>[/<mailbox>]
*/
int
_url_imap_init (mu_url_t url)
{
int status = 0;
url->_destroy = url_imap_destroy;
status = mu_url_parse (url);
if (status)
return status;
if(!url->host || url->query)
return EINVAL;
/* is it pop? */
if (strcmp ("imap", url->scheme) != 0)
return EINVAL;
/* fill in default port, if necesary */
if (url->port == 0)
url->port = MU_IMAP_PORT;
/* fill in default auth, if necessary */
if (!url->auth)
{
url->auth = malloc (1 + 1);
if (!url->auth)
return ENOMEM;
url->auth[0] = '*';
url->auth[1] = '\0';
}
return status;
}
#endif
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
T
_*
.gdbinit
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or (at
## your option) any later version.
##
## This program 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
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
INCLUDES = @MU_COMMON_INCLUDES@ -I${top_srcdir}/libproto/include @INTLINCS@
lib_LTLIBRARIES = libmu_maildir.la
libmu_maildir_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_maildir_la_LIBADD = ${MU_LIB_MAILUTILS}
libmu_maildir_la_SOURCES = \
folder.c \
maildir.h \
mbox.c
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef ENABLE_MAILDIR
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <folder0.h>
#include <registrar0.h>
#include <maildir.h>
#include <mailutils/mutil.h>
#include <amd.h>
static int
_maildir_folder_init (mu_folder_t folder ARG_UNUSED)
{
return 0;
}
static int
dir_exists (const char *name, const char *suf)
{
struct stat st;
char *s = maildir_mkfilename (name, suf, NULL);
if (stat (s, &st) < 0)
return 0;
free (s);
return S_ISDIR (st.st_mode);
}
static int
_maildir_is_scheme (mu_record_t record, const char *url, int flags)
{
const char *path;
if (!url || !record->scheme)
return 0;
if (strncmp (record->scheme, url, strlen (record->scheme)) == 0)
return MU_FOLDER_ATTRIBUTE_ALL & flags;
if (mu_scheme_autodetect_p (url, &path))
{
/* Attemp auto-detection */
struct stat st;
int rc = 0;
if (stat (path, &st) < 0)
return 0;
if (!S_ISDIR (st.st_mode))
return 0;
rc |= (MU_FOLDER_ATTRIBUTE_DIRECTORY & flags);
if ((flags & MU_FOLDER_ATTRIBUTE_FILE)
&& dir_exists (path, TMPSUF)
&& dir_exists (path, CURSUF)
&& dir_exists (path, NEWSUF))
return rc | MU_FOLDER_ATTRIBUTE_FILE;
}
return 0;
}
/*
MAILDIR url
maildir:path
*/
int
_maildir_url_init (mu_url_t url)
{
return amd_url_init (url, MU_MAILDIR_SCHEME);
}
static struct _mu_record _maildir_record =
{
MU_MAILDIR_PRIO,
MU_MAILDIR_SCHEME,
_maildir_url_init, /* Url init. */
_mailbox_maildir_init, /* Mailbox init. */
NULL, /* Mailer init. */
_maildir_folder_init, /* Folder init. */
NULL, /* back pointer. */
_maildir_is_scheme, /* _is_scheme method. */
NULL, /* _get_url method. */
NULL, /* _get_mailbox method. */
NULL, /* _get_mailer method. */
NULL /* _get_folder method. */
};
mu_record_t mu_maildir_record = &_maildir_record;
#else
#include <stdio.h>
#include <registrar0.h>
mu_record_t mu_maildir_record = NULL;
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#define PERMS 0700
#define TMPSUF "tmp"
#define CURSUF "cur"
#define NEWSUF "new"
extern char *maildir_mkfilename (const char *dir, const char *suffix,
const char *name);
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
T
_*
.gdbinit
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or (at
## your option) any later version.
##
## This program 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
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
INCLUDES = @MU_COMMON_INCLUDES@ -I${top_srcdir}/libproto/include @INTLINCS@
lib_LTLIBRARIES = libmu_mbox.la
libmu_mbox_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_mbox_la_LIBADD = ${MU_LIB_MAILUTILS}
libmu_mbox_la_SOURCES = \
folder.c\
mbox.c\
mboxscan.c\
mbox0.h\
url.c
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#ifdef WITH_PTHREAD
# ifdef HAVE_PTHREAD_H
# ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500
# endif
# include <pthread.h>
# endif
#endif
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <mailbox0.h>
#include <registrar0.h>
#include <mailutils/address.h>
#include <mailutils/attribute.h>
#include <mailutils/body.h>
#include <mailutils/debug.h>
#include <mailutils/envelope.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/header.h>
#include <mailutils/locker.h>
#include <mailutils/message.h>
#include <mailutils/mutil.h>
#include <mailutils/nls.h>
#include <mailutils/observer.h>
#include <mailutils/property.h>
#include <mailutils/stream.h>
#include <mailutils/url.h>
#define H_BCC 0
#define H_CC 1
#define H_CONTENT_LANGUAGE 2
#define H_CONTENT_TRANSFER_ENCODING 3
#define H_CONTENT_TYPE 4
#define H_DATE 5
#define H_FROM 6
#define H_IN_REPLY_TO 7
#define H_MESSAGE_ID 8
#define H_REFERENCE 9
#define H_REPLY_TO 10
#define H_SENDER 11
#define H_SUBJECT 12
#define H_TO 13
#define H_X_UIDL 14
#define HDRSIZE 15
struct _mbox_message;
struct _mbox_data;
typedef struct _mbox_data* mbox_data_t;
typedef struct _mbox_message* mbox_message_t;
/* Keep the file positions of where the headers and bodies start and end.
attr_flags is the "Status:" message. */
struct _mbox_message
{
/* Offset of the messages in the mailbox. */
off_t header_from;
off_t header_from_end;
off_t body;
off_t body_end;
/* Fast header retrieve, we save here the most common headers. This will
speed the header search. The entire headers are copied, when modified,
by the mu_header_t object, we do not have to worry about updating them. */
char *fhdr[HDRSIZE];
size_t uid; /* IMAP uid. */
int attr_flags; /* The attr_flags contains the "Status:" attribute */
size_t header_lines;
size_t body_lines;
mu_message_t message; /* A message attach to it. */
mbox_data_t mud; /* Back pointer. */
};
/* The umessages is an array of pointers that contains umessages_count of
mbox_message_t*; umessages[umessages_count]. We do it this way because
realloc() can move everything to a new memory region and invalidate all
the pointers. Thanks to <Dave Inglis> for pointing this out. The
messages_count is the count number of messages parsed so far. */
struct _mbox_data
{
mbox_message_t *umessages; /* Array. */
size_t umessages_count; /* How big is the umessages[]. */
size_t messages_count; /* How many valid entry in umessages[]. */
off_t size; /* Size of the mailbox. */
unsigned long uidvalidity;
size_t uidnext;
char *name;
/* The variables below are use to hold the state when appending messages. */
enum mbox_state
{
MBOX_NO_STATE = 0,
MBOX_STATE_APPEND_SENDER, MBOX_STATE_APPEND_DATE, MBOX_STATE_APPEND_HEADER,
MBOX_STATE_APPEND_ATTRIBUTE, MBOX_STATE_APPEND_UID, MBOX_STATE_APPEND_BODY,
MBOX_STATE_APPEND_MESSAGE
} state ;
char *sender;
char *date;
off_t off;
mu_mailbox_t mailbox; /* Back pointer. */
};
int mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif);
#ifdef WITH_PTHREAD
void mbox_cleanup (void *arg);
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2003 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <registrar0.h>
#include <url0.h>
#include <mailutils/errno.h>
#include <mailutils/mutil.h>
static void url_mbox_destroy (mu_url_t purl);
static void
url_mbox_destroy (mu_url_t url ARG_UNUSED)
{
}
/* Default mailbox path generator */
static char *
_url_path_default (const char *spooldir, const char *user, int unused)
{
char *mbox = malloc (sizeof(spooldir) + strlen(user) + 2);
if (!mbox)
errno = ENOMEM;
else
sprintf (mbox, "%s/%s", spooldir, user);
return mbox;
}
/* Hashed indexing */
static char *
_url_path_hashed (const char *spooldir, const char *user, int param)
{
int i;
int ulen = strlen (user);
char *mbox;
unsigned hash;
if (param > ulen)
param = ulen;
for (i = 0, hash = 0; i < param; i++)
hash += user[i];
mbox = malloc (ulen + strlen (spooldir) + 5);
sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user);
return mbox;
}
static int transtab[] = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
};
/* Forward Indexing */
static char *
_url_path_index (const char *spooldir, const char *iuser, int index_depth)
{
const unsigned char* user = (const unsigned char*) iuser;
int i, ulen = strlen (iuser);
char *mbox, *p;
if (ulen == 0)
return NULL;
mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
strcpy (mbox, spooldir);
p = mbox + strlen (mbox);
for (i = 0; i < index_depth && i < ulen; i++)
{
*p++ = '/';
*p++ = transtab[ user[i] ];
}
for (; i < index_depth; i++)
{
*p++ = '/';
*p++ = transtab[ user[ulen-1] ];
}
*p++ = '/';
strcpy (p, iuser);
return mbox;
}
/* Reverse Indexing */
static char *
_url_path_rev_index (const char *spooldir, const char *iuser, int index_depth)
{
const unsigned char* user = (const unsigned char*) iuser;
int i, ulen = strlen (iuser);
char *mbox, *p;
if (ulen == 0)
return NULL;
mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
strcpy (mbox, spooldir);
p = mbox + strlen (mbox);
for (i = 0; i < index_depth && i < ulen; i++)
{
*p++ = '/';
*p++ = transtab[ user[ulen - i - 1] ];
}
for (; i < index_depth; i++)
{
*p++ = '/';
*p++ = transtab[ user[0] ];
}
*p++ = '/';
strcpy (p, iuser);
return mbox;
}
/*
UNIX Mbox
mbox:path[;type=TYPE][;param=PARAM][;user=USERNAME]
*/
int
_url_mbox_init (mu_url_t url)
{
const char *name = mu_url_to_string (url);
size_t len = strlen (name);
char *p;
/* reject the obvious */
if (name == NULL || strncmp (MU_MBOX_SCHEME, name, MU_MBOX_SCHEME_LEN) != 0
|| len < (MU_MBOX_SCHEME_LEN + 1) /* (scheme)+1(path)*/)
return EINVAL;
/* do I need to decode url encoding '% hex hex' ? */
/* TYPE */
url->_destroy = url_mbox_destroy;
/* SCHEME */
url->scheme = strdup (MU_MBOX_SCHEME);
if (url->scheme == NULL)
{
url_mbox_destroy (url);
return ENOMEM;
}
/* PATH */
name += MU_MBOX_SCHEME_LEN; /* pass the scheme */
url->path = strdup (name);
if (url->path == NULL)
{
url_mbox_destroy (url);
return ENOMEM;
}
p = strchr (url->path, ';');
if (p)
{
char *(*fun)() = _url_path_default;
char *user = NULL;
int param = 0;
*p++ = 0;
while (p)
{
char *q = strchr (p, ';');
if (q)
*q++ = 0;
if (strncasecmp (p, "type=", 5) == 0)
{
char *type = p + 5;
if (strcmp (type, "hash") == 0)
fun = _url_path_hashed;
else if (strcmp (type, "index") == 0)
fun = _url_path_index;
else if (strcmp (type, "rev-index") == 0)
fun = _url_path_rev_index;
else
{
url_mbox_destroy (url);
return MU_ERR_NOENT;
}
}
else if (strncasecmp (p, "user=", 5) == 0)
{
user = p + 5;
}
else if (strncasecmp (p, "param=", 6) == 0)
{
param = strtoul (p+6, NULL, 0);
}
p = q;
}
if (user)
{
p = fun (url->path, user, param);
free (url->path);
url->path = p;
}
else
{
url_mbox_destroy (url);
return MU_ERR_NOENT;
}
}
return 0;
}
static void
url_path_destroy (mu_url_t url ARG_UNUSED)
{
}
int
_url_path_init (mu_url_t url)
{
const char *name = mu_url_to_string (url);
const char *path;
/* reject the obvious */
if (name == NULL || *name == '\0')
return EINVAL;
mu_scheme_autodetect_p (name, &path);
name = strdup (path);
free (url->name);
url->name = (char*) name;
/* TYPE */
url->_destroy = url_path_destroy;
/* SCHEME */
url->scheme = strdup (MU_PATH_SCHEME);
if (url->scheme == NULL)
{
url_path_destroy (url);
return ENOMEM;
}
/* PATH */
url->path = strdup (name);
if (url->path == NULL)
{
url_path_destroy (url);
return ENOMEM;
}
return 0;
}
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
T
_*
.gdbinit
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or (at
## your option) any later version.
##
## This program 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
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
INCLUDES = @MU_COMMON_INCLUDES@ -I${top_srcdir}/libproto/include @INTLINCS@
lib_LTLIBRARIES = libmu_mh.la
libmu_mh_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_mh_la_LIBADD = ${MU_LIB_MAILUTILS}
libmu_mh_la_SOURCES = \
folder.c\
mbox.c
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef ENABLE_MH
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <url0.h>
#include <folder0.h>
#include <registrar0.h>
#include <amd.h>
#include <mailutils/mutil.h>
static int
_mh_folder_init (mu_folder_t folder ARG_UNUSED)
{
return 0;
}
/* Check if NAME is a valid MH message name */
static int
mh_message_name_p (const char *name)
{
for ( ; *name; name++)
if (!isdigit (*name))
return 0;
return 1;
}
/* Check if directory NAME is a valid MH folder directory */
static int
mh_dir_p (const char *name)
{
DIR *dir;
struct dirent *entry;
int result = 0;
dir = opendir (name);
if (!dir)
return 1; /* Maybe yes */
while (!result && (entry = readdir (dir)))
{
switch (entry->d_name[0])
{
case '.':
result = strcmp (entry->d_name, ".mh_sequences") == 0;
break;
case ',':
result = mh_message_name_p (entry->d_name + 1);
break;
default:
result = mh_message_name_p (entry->d_name);
break;
}
}
closedir (dir);
return result;
}
static int
_mh_is_scheme (mu_record_t record, const char *url, int flags)
{
const char *path;
int rc = 0;
if (!url || !record->scheme)
return 0;
if (strncmp (record->scheme, url, strlen (record->scheme)) == 0)
return MU_FOLDER_ATTRIBUTE_ALL & flags;
if (mu_scheme_autodetect_p (url, &path))
{
/* Attemp auto-detection */
struct stat st;
if (stat (path, &st) < 0)
return 0; /* mu_mailbox_open will complain*/
if (!S_ISDIR (st.st_mode))
return 0;
rc |= (MU_FOLDER_ATTRIBUTE_DIRECTORY & flags);
if ((flags & MU_FOLDER_ATTRIBUTE_FILE) && mh_dir_p (path))
return rc | MU_FOLDER_ATTRIBUTE_FILE;
}
return 0;
}
/*
MH url
mh:path
*/
static int
_mh_url_init (mu_url_t url)
{
return amd_url_init (url, MU_MH_SCHEME);
}
static struct _mu_record _mh_record =
{
MU_MH_PRIO,
MU_MH_SCHEME,
_mh_url_init, /* Url init. */
_mailbox_mh_init, /* Mailbox init. */
NULL, /* Mailer init. */
_mh_folder_init, /* Folder init. */
NULL, /* back pointer. */
_mh_is_scheme, /* _is_scheme method. */
NULL, /* _get_url method. */
NULL, /* _get_mailbox method. */
NULL, /* _get_mailer method. */
NULL /* _get_folder method. */
};
mu_record_t mu_mh_record = &_mh_record;
#else
#include <stdio.h>
#include <registrar0.h>
mu_record_t mu_mh_record = NULL;
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2003,
2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
/* First draft by Sergey Poznyakoff */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef ENABLE_MH
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <dirent.h>
#ifdef WITH_PTHREAD
# ifdef HAVE_PTHREAD_H
# ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500
# endif
# include <pthread.h>
# endif
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <mailutils/attribute.h>
#include <mailutils/body.h>
#include <mailutils/debug.h>
#include <mailutils/envelope.h>
#include <mailutils/error.h>
#include <mailutils/header.h>
#include <mailutils/locker.h>
#include <mailutils/message.h>
#include <mailutils/mutil.h>
#include <mailutils/property.h>
#include <mailutils/stream.h>
#include <mailutils/url.h>
#include <mailutils/observer.h>
#include <mailbox0.h>
#include <registrar0.h>
#include <amd.h>
struct _mh_message
{
struct _amd_message amd_message;
size_t seq_number; /* message sequence number */
};
static int
mh_message_cmp (struct _amd_message *a, struct _amd_message *b)
{
struct _mh_message *ma = (struct _mh_message *) a;
struct _mh_message *mb = (struct _mh_message *) b;
if (ma->seq_number < mb->seq_number)
return -1;
else if (ma->seq_number > mb->seq_number)
return 1;
return 0;
}
static size_t
_mh_next_seq (struct _amd_data *amd)
{
struct _mh_message *msg = (struct _mh_message *)
_amd_get_message (amd, amd->msg_count);
return (msg ? msg->seq_number : 0) + 1;
}
/* Return filename for the message.
NOTE: Allocates memory. */
static char *
_mh_message_name (struct _amd_message *amsg, int deleted)
{
struct _mh_message *mhm = (struct _mh_message *) amsg;
char *filename;
size_t len = strlen (amsg->amd->name) + 32;
filename = malloc (len);
if (deleted)
snprintf (filename, len, "%s/,%lu", amsg->amd->name,
(unsigned long) mhm->seq_number);
else
snprintf (filename, len, "%s/%lu", amsg->amd->name,
(unsigned long) mhm->seq_number);
return filename;
}
/* Find the message with the given sequence number */
static struct _mh_message *
_mh_get_message_seq (struct _amd_data *amd, size_t seq)
{
struct _mh_message msg;
size_t index;
msg.seq_number = seq;
if (amd_msg_lookup (amd, (struct _amd_message*) &msg, &index))
return NULL;
return (struct _mh_message *) _amd_get_message (amd, index);
}
/* Scan the mailbox */
static int
mh_scan0 (mu_mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
int do_notify)
{
struct _amd_data *amd = mailbox->data;
struct _mh_message *msg;
DIR *dir;
struct dirent *entry;
int status = 0;
struct stat st;
if (amd == NULL)
return EINVAL;
dir = opendir (amd->name);
if (!dir)
return errno;
mu_monitor_wrlock (mailbox->monitor);
#ifdef WITH_PTHREAD
pthread_cleanup_push (amd_cleanup, (void *)mailbox);
#endif
mu_locker_lock (mailbox->locker);
/* Do actual work. */
while ((entry = readdir (dir)))
{
char *namep;
int attr_flags;
size_t num;
attr_flags = 0;
switch (entry->d_name[0])
{
case '.':
/* FIXME: .mh_sequences */
continue;
case ',':
continue;
#if 0
attr_flags |= MU_ATTRIBUTE_DELETED;
namep = entry->d_name+1;
break;
#endif
case '0':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':
namep = entry->d_name;
break;
default:
/*FIXME: Invalid entry. Report? */
continue;
}
num = strtoul (namep, &namep, 10);
if (namep[0])
continue;
msg = _mh_get_message_seq (amd, num);
if (!msg)
{
msg = calloc (1, sizeof(*msg));
msg->seq_number = num;
msg->amd_message.attr_flags = attr_flags;
msg->amd_message.deleted = attr_flags & MU_ATTRIBUTE_DELETED;
_amd_message_insert (amd, (struct _amd_message*) msg);
}
else
{
msg->amd_message.attr_flags = attr_flags;
}
}
closedir (dir);
if (do_notify)
{
size_t i;
for (i = 0; i < amd->msg_count; i++)
{
DISPATCH_ADD_MSG(mailbox, amd);
}
}
if (stat (amd->name, &st) == 0)
amd->mtime = st.st_mtime;
if (pcount)
*pcount = amd->msg_count;
/* Reset the uidvalidity. */
if (amd->msg_count > 0)
{
if (amd->uidvalidity == 0)
{
amd->uidvalidity = (unsigned long)time (NULL);
/* Tell that we have been modified for expunging. */
if (amd->msg_count)
{
amd_message_stream_open (amd->msg_array[0]);
amd_message_stream_close (amd->msg_array[0]);
amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
}
}
}
/* Clean up the things */
amd_cleanup (mailbox);
#ifdef WITH_PTHREAD
pthread_cleanup_pop (0);
#endif
return status;
}
/* Note: In this particular implementation the message sequence number
serves also as its UID. This allows to avoid many problems related
to keeping the uids in the headers of the messages. */
static int
mh_message_uid (mu_message_t msg, size_t *puid)
{
struct _mh_message *mhm = mu_message_get_owner (msg);
if (puid)
*puid = mhm->seq_number;
return 0;
}
static int
_mh_msg_init (struct _amd_data *amd, struct _amd_message *amm)
{
struct _mh_message *mhm = (struct _mh_message *) amm;
mhm->seq_number = _mh_next_seq (amd);
return 0;
}
int
_mailbox_mh_init (mu_mailbox_t mailbox)
{
int rc;
struct _amd_data *amd;
rc = amd_init_mailbox (mailbox, sizeof (struct _amd_data), &amd);
if (rc)
return rc;
amd->msg_size = sizeof (struct _mh_message);
amd->msg_free = NULL;
amd->msg_init_delivery = _mh_msg_init;
amd->msg_finish_delivery = NULL;
amd->msg_file_name = _mh_message_name;
amd->scan0 = mh_scan0;
amd->msg_cmp = mh_message_cmp;
amd->message_uid = mh_message_uid;
amd->next_uid = _mh_next_seq;
/* Set our properties. */
{
mu_property_t property = NULL;
mu_mailbox_get_property (mailbox, &property);
mu_property_set_value (property, "TYPE", "MH", 1);
}
return 0;
}
#endif
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
T
_*
.gdbinit
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or (at
## your option) any later version.
##
## This program 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
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
INCLUDES = @MU_COMMON_INCLUDES@ -I${top_srcdir}/libproto/include @INTLINCS@
lib_LTLIBRARIES = libmu_nntp.la
libmu_nntp_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_nntp_la_LIBADD = ${MU_LIB_MAILUTILS}
libmu_nntp_la_SOURCES = \
nntp_article.c \
nntp_body.c \
nntp_carrier.c \
nntp_connect.c \
nntp_create.c \
nntp_date.c \
nntp_debug.c \
nntp_destroy.c \
nntp_disconnect.c \
nntp_group.c \
nntp_head.c \
nntp_help.c \
nntp_ihave.c \
nntp_iterator.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 \
nntp_sendline.c \
nntp_stat.c \
nntp_stream.c \
nntp_timeout.c \
nntp0.h \
url.c \
folder.c \
mbox.c
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 <mailutils/url.h>
#include <folder0.h>
#include "nntp0.h"
/* We export url parsing and the initialisation of
the mailbox, via the register entry/record. */
static struct _mu_record _nntp_record =
{
MU_NNTP_PRIO,
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. */
};
mu_record_t mu_nntp_record = &_nntp_record;
static int nntp_folder_open (mu_folder_t, int);
static int nntp_folder_close (mu_folder_t);
static void nntp_folder_destroy (mu_folder_t folder);
static int nntp_folder_list (mu_folder_t folder, const char *ref,
const char *name,
size_t max,
mu_list_t flist);
int
_nntp_folder_init (mu_folder_t folder)
{
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 (mu_folder_t folder, int flags)
{
f_nntp_t f_nntp = folder->data;
mu_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. */
mu_monitor_wrlock (folder->monitor);
if (f_nntp->isopen)
{
mu_monitor_unlock (folder->monitor);
return 0;
}
mu_monitor_unlock (folder->monitor);
/* Fetch the server name and the port in the mu_url_t. */
status = mu_url_get_host (folder->url, NULL, 0, &len);
if (status != 0)
return status;
host = malloc (len + 1);
if (!host)
return ENOMEM;
mu_url_get_host (folder->url, host, len + 1, NULL);
mu_url_get_port (folder->url, &port);
folder->flags = flags;
/* Create the networking stack. */
status = mu_tcp_stream_create (&carrier, host, port, folder->flags);
free (host);
if (status != 0)
return status;
/* Ask for the stream internal buffering mechanism scheme. */
mu_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)
{
mu_monitor_wrlock (folder->monitor);
f_nntp->isopen++;
mu_monitor_unlock (folder->monitor);
}
}
}
return status;
}
static int
nntp_folder_close (mu_folder_t folder)
{
f_nntp_t f_nntp = folder->data;
int status = 0;
mu_monitor_wrlock (folder->monitor);
f_nntp->isopen--;
if (f_nntp->isopen)
{
mu_monitor_unlock (folder->monitor);
return 0;
}
mu_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 (mu_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 (mu_folder_t folder, const char *ref, const char *name,
size_t max_level, mu_list_t flist)
{
return ENOTSUP;
}
#else
#include <stdio.h>
#include <registrar0.h>
mu_record_t mu_nntp_record = NULL;
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 (mu_url_t);
extern int _nntp_mailbox_init (mu_mailbox_t);
extern int _nntp_folder_init (mu_folder_t);
struct _nntp_folder
{
/* Refcount. */
int isopen;
/* Back pointer. */
mu_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. */
mu_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. */
mu_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. */
mu_stream_t mstream;
/* Stream for body. */
mu_stream_t bstream;
/* Stream for header. */
mu_stream_t hstream;
};
/* 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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_article (mu_nntp_t nntp, unsigned long number, unsigned long *pnum, char **mid, mu_stream_t *pstream)
{
int status;
char *message_id = NULL;
if (number != 0)
{
message_id = malloc (128);
if (message_id == NULL)
{
return ENOMEM;
}
snprintf (message_id, 127, "%lu", number);
}
status = mu_nntp_article_id (nntp, message_id, pnum, mid, pstream);
if (message_id)
{
free (message_id);
}
return status;
}
int
mu_nntp_article_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, char **mid, mu_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:
if (message_id == NULL || *message_id == '\0')
{
status = mu_nntp_writeline (nntp, "ARTICLE\r\n");
}
else
{
status = mu_nntp_writeline (nntp, "ARTICLE %s\r\n", message_id);
}
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_ARTICLE;
case MU_NNTP_ARTICLE:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_ARTICLE_ACK;
case MU_NNTP_ARTICLE_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_ARTICLE_FOLLOW);
nntp->state = MU_NNTP_ARTICLE_RX;
/* parse the answer now. */
status = mu_nntp_parse_article(nntp, MU_NNTP_RESP_CODE_ARTICLE_FOLLOW, pnum, mid);
MU_NNTP_CHECK_ERROR (nntp, status);
case MU_NNTP_ARTICLE_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;
}
int
mu_nntp_parse_article(mu_nntp_t nntp, int code, unsigned long *pnum, char **mid)
{
unsigned long dummy = 0;
char *buf;
char format[24];
if (pnum == NULL)
pnum = &dummy;
/* Message ID should not be longer then 250 and smaller then 3. */
buf = calloc(1, 256);
if (buf == NULL)
{
return ENOMEM;
}
sprintf (format, "%d %%ld %%%ds", code, 250);
sscanf (nntp->ack.buf, format, pnum, buf);
if (*buf == '\0')
{
strcpy (buf, "<0>"); /* RFC 977 */
}
if (mid)
{
*mid = buf;
}
else
{
free (buf);
}
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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_body (mu_nntp_t nntp, unsigned long number, unsigned long *pnum, char **mid, mu_stream_t *pstream)
{
int status;
char *message_id = NULL;
if (number != 0)
{
message_id = malloc (128);
if (message_id == NULL)
{
return ENOMEM;
}
snprintf (message_id, 127, "%lu", number);
}
status = mu_nntp_body_id (nntp, message_id, pnum, mid, pstream);
if (message_id)
{
free (message_id);
}
return status;
}
int
mu_nntp_body_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, char **mid, mu_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:
if (message_id == 0 || *message_id == '\0')
{
status = mu_nntp_writeline (nntp, "BODY\r\n");
}
else
{
status = mu_nntp_writeline (nntp, "BODY %s\r\n", message_id);
}
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_BODY;
case MU_NNTP_BODY:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_BODY_ACK;
case MU_NNTP_BODY_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_BODY_FOLLOW);
/* parse the answer now. */
status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_BODY_FOLLOW, pnum, mid);
MU_NNTP_CHECK_ERROR (nntp, status);
nntp->state = MU_NNTP_BODY_RX;
case MU_NNTP_BODY_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) 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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_set_carrier (mu_nntp_t nntp, mu_stream_t carrier)
{
/* Sanity checks. */
if (nntp == NULL)
return EINVAL;
if (nntp->carrier)
{
/* Close any old carrier. */
mu_nntp_disconnect (nntp);
mu_stream_destroy (&nntp->carrier, nntp);
}
nntp->carrier = carrier;
return 0;
}
int
mu_nntp_get_carrier (mu_nntp_t nntp, mu_stream_t *pcarrier)
{
/* Sanity checks. */
if (nntp == NULL)
return EINVAL;
if (pcarrier == NULL)
return MU_ERR_OUT_PTR_NULL;
*pcarrier = nntp->carrier;
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
/* Open the connection to the server. */
int
mu_nntp_connect (mu_nntp_t nntp)
{
int status;
/* Sanity checks. */
if (nntp == NULL)
return EINVAL;
/* A networking stack. */
if (nntp->carrier == NULL)
return EINVAL;
/* Enter the nntp state machine, and boogy */
switch (nntp->state)
{
default:
/* FALLTHROUGH */
/* If nntp was in an error state going through here should clear it. */
case MU_NNTP_NO_STATE:
status = mu_nntp_disconnect (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->state = MU_NNTP_CONNECT;
case MU_NNTP_CONNECT:
/* Establish the connection. */
status = mu_stream_open (nntp->carrier);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_GREETINGS;
case MU_NNTP_GREETINGS:
/* Get the greetings. */
{
size_t len = 0;
int code;
status = mu_nntp_response (nntp, NULL, 0, &len);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
/* 200 Service available, posting allowed */
/* 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)
{
mu_stream_close (nntp->carrier);
nntp->state = MU_NNTP_NO_STATE;
return EACCES;
}
nntp->state = MU_NNTP_NO_STATE;
}
} /* End AUTHORISATION state. */
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <mailutils/errno.h>
#include <mailutils/sys/nntp.h>
/* Initialise a mu_nntp_t handle. */
int
mu_nntp_create (mu_nntp_t *pnntp)
{
mu_nntp_t nntp;
/* Sanity check. */
if (pnntp == NULL)
return EINVAL;
nntp = calloc (1, sizeof *nntp);
if (nntp == NULL)
return ENOMEM;
/* Reserve space for the ack(nowledgement) response.
According to RFC 977: The maximum length of the first line of a
command response (including the initial greeting) is unchanged at
512 octets (including the terminating CRLF). */
nntp->ack.len = 512;
nntp->ack.buf = calloc (nntp->ack.len, 1);
if (nntp->ack.buf == NULL)
{
mu_nntp_destroy (&nntp);
return ENOMEM;
}
nntp->ack.ptr = nntp->ack.buf;
/* Reserve space for the data response/content.
RFC 977 recommands 255, but we grow it as needed. */
nntp->io.len = 255;
nntp->io.buf = calloc (nntp->io.len, 1);
if (nntp->io.buf == NULL)
{
mu_nntp_destroy (&nntp);
return ENOMEM;
}
nntp->io.ptr = nntp->io.buf;
nntp->state = MU_NNTP_NO_STATE; /* Init with no state. */
nntp->timeout = (10 * 60) * 100; /* The default Timeout is 10 minutes. */
nntp->acknowledge = 0; /* No Ack received. */
*pnntp = nntp;
return 0; /* Okdoke. */
}
/* 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#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)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "DATE\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_DATE;
case MU_NNTP_DATE:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_DATE_ACK;
case MU_NNTP_DATE_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_SERVER_DATE);
nntp->state = MU_NNTP_NO_STATE;
/* parse the answer now. */
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;
/* They must deal with the error first by reopening. */
case MU_NNTP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
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)
{
unsigned int dummy = 0;
char format[32];
if (year == NULL)
year = &dummy;
if (month == NULL)
month = &dummy;
if (day == NULL)
day = &dummy;
if (hour == NULL)
hour = &dummy;
if (min == NULL)
min = &dummy;
if (sec == NULL)
sec = &dummy;
sprintf (format, "%d %%4d%%2d%%2d%%2d%%2d%%2d", code);
sscanf (nntp->ack.buf, format, year, month, day, hour, min, sec);
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_set_debug (mu_nntp_t nntp, mu_debug_t debug)
{
if (nntp == NULL)
return EINVAL;
if (nntp->debug)
mu_debug_destroy (&nntp->debug, NULL);
nntp->debug = debug;
return 0;
}
int
mu_nntp_debug_cmd (mu_nntp_t nntp)
{
if (nntp->debug)
mu_debug_print(nntp->debug, MU_DEBUG_PROT, "%s", nntp->io.buf);
return 0;
}
int
mu_nntp_debug_ack (mu_nntp_t nntp)
{
if (nntp->debug)
{
mu_debug_print (nntp->debug, MU_DEBUG_PROT, "%s\n", nntp->ack.buf);
}
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/errno.h>
#include <mailutils/sys/nntp.h>
void
mu_nntp_destroy (mu_nntp_t *pnntp)
{
if (pnntp && *pnntp)
{
mu_nntp_t nntp = *pnntp;
/* Free the response buffer. */
if (nntp->ack.buf)
free (nntp->ack.buf);
/* Free the io buffer. */
if (nntp->io.buf)
free (nntp->io.buf);
/* Release the carrier. */
if (nntp->carrier)
mu_stream_destroy (&nntp->carrier, nntp);
/* Any posting residue. */
if (nntp->post.buf)
free (nntp->post.buf);
free (nntp);
*pnntp = NULL;
}
}
/* 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_disconnect (mu_nntp_t nntp)
{
/* Sanity checks. */
if (nntp == NULL)
return EINVAL;
/* We can keep some of the fields, if they decide to nntp_connect() again but
clear the states. */
nntp->state = MU_NNTP_NO_STATE;
nntp->acknowledge = 0;
/* Clear the buffers. */
memset (nntp->io.buf, '\0', nntp->io.len);
nntp->io.ptr = nntp->io.buf;
memset (nntp->ack.buf, '\0', nntp->ack.len);
nntp->ack.ptr = nntp->ack.buf;
/* Close the stream. */
return mu_stream_close (nntp->carrier);
}
/* 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#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)
{
int status;
if (nntp == NULL)
return EINVAL;
if (group == NULL || *group == '\0')
return MU_ERR_OUT_PTR_NULL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "GROUP %s\r\n", group);
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_GROUP;
case MU_NNTP_GROUP:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_GROUP_ACK;
case MU_NNTP_GROUP_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_GROUP_SELECTED);
nntp->state = MU_NNTP_NO_STATE;
/* parse group. */
status = mu_nntp_parse_group (nntp, MU_NNTP_RESP_CODE_GROUP_SELECTED, total, low, high, name);
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;
}
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;
char *buf;
char format[24];
if (ptotal == NULL)
ptotal = &dummy;
if (plow == NULL)
plow = &dummy;
if (phigh == NULL)
phigh = &dummy;
/* An nntp response is not longer then 512. */
buf = calloc(1, 512);
if (buf == NULL)
{
return ENOMEM;
}
sprintf (format, "%d %%d %%d %%d %%%ds", code, 511);
sscanf (nntp->ack.buf, format, ptotal, plow, phigh, buf);
if (name)
{
*name = buf;
}
else
{
free (buf);
}
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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_head (mu_nntp_t nntp, unsigned long number, unsigned long *pnum, char **mid, mu_stream_t *pstream)
{
int status;
char *message_id = NULL;
if (number != 0)
{
message_id = malloc (128);
if (message_id == NULL)
{
return ENOMEM;
}
snprintf (message_id, 127, "%lu", number);
}
status = mu_nntp_head_id (nntp, message_id, pnum, mid, pstream);
if (message_id)
{
free (message_id);
}
return status;
}
int
mu_nntp_head_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, char **mid, mu_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:
if (message_id == NULL || *message_id == '\0')
{
status = mu_nntp_writeline (nntp, "HEAD\r\n");
}
else
{
status = mu_nntp_writeline (nntp, "HEAD %s\r\n", message_id);
}
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_HEAD;
case MU_NNTP_HEAD:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_HEAD_ACK;
case MU_NNTP_HEAD_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_HEAD_FOLLOW);
nntp->state = MU_NNTP_HEAD_RX;
/* parse the answer now. */
status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_HEAD_FOLLOW, pnum, mid);
MU_NNTP_CHECK_ERROR (nntp, status);
case MU_NNTP_HEAD_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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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, mu_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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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, mu_stream_t stream)
{
int status;
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 = mu_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, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
#include <mailutils/iterator.h>
static int nntp_itr_dup (void **ptr, void *owner);
static int nntp_itr_destroy (mu_iterator_t itr, void *owner);
static int nntp_itr_first (void *owner);
static int nntp_itr_next (void *woner);
static int nntp_itr_getitem (void *owner, void **pret);
static int nntp_itr_curitem_p (void *owner, void *data);
static int nntp_itr_finished_p (void *owner);
struct nntp_iterator
{
mu_nntp_t nntp;
int done;
char *item;
};
int
mu_nntp_iterator_create (mu_nntp_t nntp, mu_iterator_t *piterator)
{
struct nntp_iterator *nntp_iterator;
mu_iterator_t iterator;
int status;
nntp_iterator = malloc (sizeof *nntp_iterator);
if (nntp_iterator == NULL)
return ENOMEM;
nntp_iterator->item = NULL;
nntp_iterator->done = 0;
nntp_iterator->nntp= nntp;
status = mu_iterator_create (&iterator, nntp_iterator);
if (status != 0)
{
free (nntp_iterator);
return status;
}
mu_iterator_set_first (iterator, nntp_itr_first);
mu_iterator_set_next (iterator, nntp_itr_next);
mu_iterator_set_getitem (iterator, nntp_itr_getitem);
mu_iterator_set_finished_p (iterator, nntp_itr_finished_p);
mu_iterator_set_curitem_p (iterator, nntp_itr_curitem_p);
mu_iterator_set_destroy (iterator, nntp_itr_destroy);
mu_iterator_set_dup (iterator, nntp_itr_dup);
*piterator = iterator;
return 0;
}
static int
nntp_itr_dup (void **ptr, void *owner)
{
struct nntp_iterator *nntp_iterator = (struct nntp_iterator *)owner;
struct nntp_iterator *clone = malloc (sizeof *nntp_iterator);
if (clone == NULL)
return ENOMEM;
/* let the assignement operator copy the elements. */
*clone = *nntp_iterator;
*ptr = clone;
return 0;
}
static int
nntp_itr_destroy (mu_iterator_t iterator, void *owner)
{
struct nntp_iterator *nntp_iterator = (struct nntp_iterator *)owner;
/* Delicate situation if they did not finish to drain the result
We take te approach to do it for the user. FIXME: Not sure
if this is the rigth thing to do. The other way is to close the stream */
if (!nntp_iterator->done)
{
char buf[128];
size_t n = 0;
while (mu_nntp_readline (nntp_iterator->nntp, buf, sizeof buf, &n) > 0 && n > 0)
n = 0;
}
if (nntp_iterator->item)
free (nntp_iterator->item);
nntp_iterator->nntp->state = MU_NNTP_NO_STATE;
free (nntp_iterator);
return 0;
}
static int
nntp_itr_first (void *data)
{
return nntp_itr_next (data);
}
static int
nntp_itr_next (void *owner)
{
struct nntp_iterator *nntp_iterator = (struct nntp_iterator *)owner;
size_t n = 0;
int status = 0;
if (!nntp_iterator->done)
{
/* The first readline will not consume the buffer, we just need to
know how much to read. */
status = mu_nntp_readline (nntp_iterator->nntp, NULL, 0, &n);
if (status == 0)
{
if (n)
{
char *buf;
buf = calloc (n + 1, 1);
if (buf)
{
/* Consume. */
mu_nntp_readline (nntp_iterator->nntp, buf, n + 1, NULL);
if (buf[n - 1] == '\n')
buf[n - 1] = '\0';
if (nntp_iterator->item)
free (nntp_iterator->item);
nntp_iterator->item = buf;
}
else
status = ENOMEM;
}
else
{
nntp_iterator->done = 1;
nntp_iterator->nntp->state = MU_NNTP_NO_STATE;
}
}
}
return status;
}
static int
nntp_itr_getitem (void *owner, void **item)
{
struct nntp_iterator *nntp_iterator = (struct nntp_iterator *)owner;
if (item)
{
*((char **)item) = nntp_iterator->item;
nntp_iterator->item = NULL;
}
return 0;
}
static int
nntp_itr_finished_p (void *owner)
{
struct nntp_iterator *nntp_iterator = (struct nntp_iterator *)owner;
return nntp_iterator->done;
}
static int
nntp_itr_curitem_p (void *owner, void *item)
{
struct nntp_iterator *nntp_iterator = (struct nntp_iterator *)owner;
return *((char **)item) == nntp_iterator->item;
}
/* 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_last (mu_nntp_t nntp, unsigned long *number, char **mid)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "LAST\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_LAST;
case MU_NNTP_LAST:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_LAST_ACK;
case MU_NNTP_LAST_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_ARTICLE_FOUND);
nntp->state = MU_NNTP_NO_STATE;
status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_ARTICLE_FOUND, number, mid);
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) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 iterator that contains the result.
It is the responsability of the caller to destroy the iterator(mu_iterator_destroy).
*/
int
mu_nntp_list_active (mu_nntp_t nntp, const char *wildmat, mu_iterator_t *piterator)
{
int status = 0;
if (nntp == NULL)
return EINVAL;
if (piterator == 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\r\n");
else
status = mu_nntp_writeline (nntp, "LIST ACTIVE %s\r\n", wildmat);
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_LIST_ACTIVE;
case MU_NNTP_LIST_ACTIVE:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_LIST_ACTIVE_ACK;
case MU_NNTP_LIST_ACTIVE_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 = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_LIST_ACTIVE_RX;
case MU_NNTP_LIST_ACTIVE_RX:
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 (const char *buffer, char **group, unsigned long *high, unsigned long *low, char *status)
{
unsigned long dummy;
char cdummy;
char *name;
if (buffer == NULL || *buffer == '\0')
return EINVAL;
name = calloc(512, 1);
if (name == NULL)
return ENOMEM;
if (high == NULL)
high = &dummy;
if (low == NULL)
low = &dummy;
if (status == NULL)
status = &cdummy;
sscanf (buffer, "%511s %ld %ld %c", name, high, low, status);
if (group == NULL)
free (name);
else
*group = name;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 an iterator that contains the result.
It is the responsability of the caller to destroy the iterator(mu_iterator_destroy).
*/
int
mu_nntp_list_distrib_pats (mu_nntp_t nntp, mu_iterator_t *piterator)
{
int status = 0;
if (nntp == NULL)
return EINVAL;
if (piterator == 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 = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_LIST_DISTRIB_PATS_RX;
case MU_NNTP_LIST_DISTRIB_PATS_RX:
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, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 an iterator that contains the result.
It is the responsability of the caller to destroy the iterator(mu_iterator_destroy).
*/
int
mu_nntp_list_distributions (mu_nntp_t nntp, const char *wildmat, mu_iterator_t *piterator)
{
int status = 0;
if (nntp == NULL)
return EINVAL;
if (piterator == 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 = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_LIST_DISTRIBUTIONS_RX;
case MU_NNTP_LIST_DISTRIBUTIONS_RX:
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;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 an iterator that contains the result.
It is the responsability of the caller to destroy the iterator(mu_iterator_destroy).
*/
int
mu_nntp_list_extensions (mu_nntp_t nntp, mu_iterator_t *piterator)
{
int status = 0;
if (nntp == NULL)
return EINVAL;
if (piterator == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "LIST EXTENSIONS\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_LIST_EXTENSIONS;
case MU_NNTP_LIST_EXTENSIONS:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_LIST_EXTENSIONS_ACK;
case MU_NNTP_LIST_EXTENSIONS_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_EXTENSIONS_FOLLOW);
status = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_LIST_EXTENSIONS_RX;
case MU_NNTP_LIST_EXTENSIONS_RX:
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, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 an iterator that contains the result.
It is the responsability of the caller to destroy the iterator(mu_iterator_destroy).
*/
int
mu_nntp_list_newsgroups (mu_nntp_t nntp, const char *wildmat, mu_iterator_t *piterator)
{
int status = 0;
if (nntp == NULL)
return EINVAL;
if (piterator == 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 = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_LIST_NEWSGROUPS_RX;
case MU_NNTP_LIST_NEWSGROUPS_RX:
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, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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 an iterator that contains the result.
It is the responsability of the caller to destroy the iterator(mu_iterator_destroy).
*/
int
mu_nntp_list_active_times (mu_nntp_t nntp, const char *wildmat, mu_iterator_t *piterator)
{
int status = 0;
if (nntp == NULL)
return EINVAL;
if (piterator == 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 = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_LIST_ACTIVE_TIMES_RX;
case MU_NNTP_LIST_ACTIVE_TIMES_RX:
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_mode_reader (mu_nntp_t nntp)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "MODE READER\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_MODE_READER;
case MU_NNTP_MODE_READER:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_MODE_READER_ACK;
case MU_NNTP_MODE_READER_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
MU_NNTP_CHECK_CODE2(nntp, MU_NNTP_RESP_CODE_POSTING_ALLOWED, MU_NNTP_RESP_CODE_POSTING_PROHIBITED);
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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, mu_iterator_t *piterator)
{
int status = 0;
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 = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_NEWGROUPS_RX;
case MU_NNTP_NEWGROUPS_RX:
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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, mu_iterator_t *piterator)
{
int status = 0;
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 = mu_nntp_iterator_create (nntp, piterator);
MU_NNTP_CHECK_ERROR(nntp, status);
nntp->state = MU_NNTP_NEWNEWS_RX;
case MU_NNTP_NEWNEWS_RX:
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_next (mu_nntp_t nntp, unsigned long *number, char **mid)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "NEXT\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_NEXT;
case MU_NNTP_NEXT:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_NEXT_ACK;
case MU_NNTP_NEXT_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_ARTICLE_FOUND);
nntp->state = MU_NNTP_NO_STATE;
status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_ARTICLE_FOUND, number, mid);
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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, mu_stream_t stream)
{
int status;
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 = mu_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;
}
/* 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
int
mu_nntp_quit (mu_nntp_t nntp)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
status = mu_nntp_writeline (nntp, "QUIT\r\n");
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_QUIT;
case MU_NNTP_QUIT:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_QUIT_ACK;
case MU_NNTP_QUIT_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_CLOSING);
nntp->state = MU_NNTP_NO_STATE;
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
#include <mailutils/error.h>
int
mu_nntp_carrier_is_ready (mu_stream_t carrier, int flag, int timeout)
{
struct timeval tv, *tvp = NULL;
int wflags = flag;
int status;
if (timeout >= 0)
{
tv.tv_sec = timeout / 100;
tv.tv_usec = (timeout % 1000) * 1000;
tvp = &tv;
}
status = mu_stream_wait (carrier, &wflags, tvp);
if (status)
return 0; /* FIXME: provide a way to return error code! */
return wflags & flag;
}
/* Read a complete line from the nntp server. Transform CRLF to LF, remove
the stuff byte termination octet ".", put a null in the buffer
when done. And Do a select() (stream_is_readready()) for the timeout. */
static int
mu_nntp_getline (mu_nntp_t nntp)
{
size_t n = 0;
size_t total = nntp->io.ptr - nntp->io.buf;
int status = 0;
/* Must get a full line before bailing out. */
do
{
/* Timeout with select(), note that we have to reset select()
since on linux tv is modified when error. */
if (nntp->timeout)
{
int ready = mu_nntp_carrier_is_ready (nntp->carrier,
MU_STREAM_READY_RD,
nntp->timeout);
if (ready == 0)
return ETIMEDOUT;
}
status = mu_stream_sequential_readline (nntp->carrier, nntp->io.buf + total, nntp->io.len - total, &n);
if (status != 0)
return status;
/* The server went away: It maybe a timeout and some nntp server
does not send the -ERR. Consider this like an error. */
if (n == 0)
return EIO;
total += n;
nntp->io.nl = memchr (nntp->io.buf, '\n', total);
if (nntp->io.nl == NULL) /* Do we have a full line. */
{
/* Allocate a bigger buffer ? */
if (total >= nntp->io.len - 1)
{
nntp->io.len *= 2;
nntp->io.buf = realloc (nntp->io.buf, nntp->io.len + 1);
if (nntp->io.buf == NULL)
return ENOMEM;
}
}
nntp->io.ptr = nntp->io.buf + total;
}
while (nntp->io.nl == NULL); /* Bail only if we have a complete line. */
/* When examining a multi-line response, the client checks to see if the
line begins with the termination octet "."(DOT). If yes and if octets
other than CRLF follow, the first octet of the line (the termination
octet) is stripped away. */
if (total >= 3 && nntp->io.buf[0] == '.')
{
if (nntp->io.buf[1] != '\r' && nntp->io.buf[2] != '\n')
{
memmove (nntp->io.buf, nntp->io.buf + 1, total - 1);
nntp->io.ptr--;
nntp->io.nl--;
}
/* And if CRLF immediately follows the termination character, then
the response from the NNTP server is ended and the line containing
".CRLF" is not considered part of the multi-line response. */
else if (nntp->io.buf[1] == '\r' && nntp->io.buf[2] == '\n')
{
nntp->io.buf[0] = '\0';
nntp->io.ptr = nntp->io.buf;
nntp->io.nl = NULL;
}
}
/* \r\n --> \n\0, conversion. */
if (nntp->io.nl > nntp->io.buf)
{
*(nntp->io.nl - 1) = '\n';
*(nntp->io.nl) = '\0';
nntp->io.ptr = nntp->io.nl;
}
return status;
}
/* Call nntp_getline() for the dirty work, and consume i.e. put
in the user buffer only buflen. If buflen == 0 or buffer == NULL
nothing is consume, the data is save for another call to nntp_readline()
with a buffer != NULL.
*/
int
mu_nntp_readline (mu_nntp_t nntp, char *buffer, size_t buflen, size_t *pnread)
{
size_t nread = 0;
size_t n = 0;
int status = 0;
/* Do we need to fill up? Yes if no NL or the buffer is empty. */
if (nntp->carrier && (nntp->io.nl == NULL || nntp->io.ptr == nntp->io.buf))
{
status = mu_nntp_getline (nntp);
if (status != 0)
return status;
}
/* How much we can copy ? */
n = nntp->io.ptr - nntp->io.buf;
/* Consume the line? */
if (buffer && buflen)
{
buflen--; /* For the null. */
if (buflen)
{
int nleft = buflen - n;
/* We got more then requested. */
if (nleft < 0)
{
size_t sentinel;
nread = buflen;
sentinel = nntp->io.ptr - (nntp->io.buf + nread);
memcpy (buffer, nntp->io.buf, nread);
memmove (nntp->io.buf, nntp->io.buf + nread, sentinel);
nntp->io.ptr = nntp->io.buf + sentinel;
}
else
{
/* Drain our buffer. */;
nread = n;
memcpy (buffer, nntp->io.buf, nread);
nntp->io.ptr = nntp->io.buf;
/* Clear of all residue. */
memset (nntp->io.buf, '\0', nntp->io.len);
}
}
buffer[nread] = '\0';
}
else
nread = n;
if (pnread)
*pnread = nread;
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
/* If we did not grap the ack already, call nntp_readline() but handle
Nonblocking also. */
int
mu_nntp_response (mu_nntp_t nntp, char *buffer, size_t buflen, size_t *pnread)
{
size_t n = 0;
int status = 0;
if (nntp == NULL)
return EINVAL;
if (!nntp->acknowledge)
{
size_t len = nntp->ack.len - (nntp->ack.ptr - nntp->ack.buf);
status = mu_nntp_readline (nntp, nntp->ack.ptr, len, &n);
nntp->ack.ptr += n;
if (status == 0)
{
len = nntp->ack.ptr - nntp->ack.buf;
if (len && nntp->ack.buf[len - 1] == '\n')
nntp->ack.buf[len - 1] = '\0';
nntp->acknowledge = 1; /* Flag that we have the ack. */
nntp->ack.ptr = nntp->ack.buf;
}
else
{
/* Provide them with an error. */
const char *econ = "500 NNTP IO ERROR";
n = strlen (econ);
strcpy (nntp->ack.buf, econ);
}
}
else
n = strlen (nntp->ack.buf);
if (buffer)
{
buflen--; /* Leave space for the NULL. */
n = (buflen < n) ? buflen : n;
memcpy (buffer, nntp->ack.buf, n);
buffer[n] = '\0';
}
if (pnread)
*pnread = n;
return status;
}
int
mu_nntp_response_code(mu_nntp_t nntp)
{
char buffer[4];
int code;
memset (buffer, '\0', 4);
mu_nntp_response(nntp, buffer, 4, NULL);
/* translate the number, basically strtol() without the overhead. */
code = (buffer[0] - '0')*100 + (buffer[1] - '0')*10 + (buffer[2] - '0');
return code;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
/* A socket may write less then expected but stream.c:mu_stream_write() will
always try to send the entire buffer unless an error is reported. We have
to cope with nonblocking, it is done by keeping track with the nntp->ptr
pointer if the write failed we keep track and restart where we left. */
int
mu_nntp_send (mu_nntp_t nntp)
{
int status = 0;
if (nntp->carrier && (nntp->io.ptr > nntp->io.buf))
{
size_t n = 0;
size_t len = nntp->io.ptr - nntp->io.buf;
/* Timeout with select(), note that we have to reset select()
since on linux tv is modified when error. */
if (nntp->timeout)
{
int ready = mu_nntp_carrier_is_ready (nntp->carrier,
MU_STREAM_READY_WR,
nntp->timeout);
if (ready == 0)
return ETIMEDOUT;
}
status = mu_stream_write (nntp->carrier, nntp->io.buf, len, 0, &n);
if (n)
{
/* Consume what we sent. */
memmove (nntp->io.buf, nntp->io.buf + n, len - n);
nntp->io.ptr -= n;
}
}
else
nntp->io.ptr = nntp->io.buf;
return status;
}
/* According to RFC 2449: The maximum length of a command is increased from
47 characters (4 character command, single space, 40 character argument,
CRLF) to 255 octets, including the terminating CRLF. But we are flexible
on this and realloc() as needed. NOTE: The terminated CRLF is not
included. */
int
mu_nntp_writeline (mu_nntp_t nntp, const char *format, ...)
{
int len;
va_list ap;
int done = 1;
va_start(ap, format);
/* C99 says that a conforming implementation of snprintf () should
return the number of char that would have been call but many old
GNU/Linux && BSD implementations return -1 on error. Worse,
QnX/Neutrino actually does not put the terminal null char. So
let's try to cope. */
do
{
len = vsnprintf (nntp->io.buf, nntp->io.len - 1, format, ap);
if (len < 0 || len >= (int)nntp->io.len
|| !memchr (nntp->io.buf, '\0', len + 1))
{
nntp->io.len *= 2;
nntp->io.buf = realloc (nntp->io.buf, nntp->io.len);
if (nntp->io.buf == NULL)
return ENOMEM;
done = 0;
}
else
done = 1;
}
while (!done);
va_end(ap);
nntp->io.ptr = nntp->io.buf + len;
return 0;
}
int
mu_nntp_sendline (mu_nntp_t nntp, const char *line)
{
if (line)
{
int status = mu_nntp_writeline (nntp, line);
if (status)
return status;
}
return mu_nntp_send (nntp);
}
/* 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 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_stat (mu_nntp_t nntp, unsigned long number, unsigned long *pnumber, char **mid)
{
int status;
char *message_id = NULL;
if (number != 0)
{
message_id = malloc (128);
if (message_id == NULL)
{
return ENOMEM;
}
snprintf (message_id, 127, "%ld", number);
}
status = mu_nntp_stat_id (nntp, message_id, pnumber, mid);
if (message_id)
{
free (message_id);
}
return status;
}
int
mu_nntp_stat_id (mu_nntp_t nntp, const char *message_id, unsigned long *number, char **mid)
{
int status;
if (nntp == NULL)
return EINVAL;
switch (nntp->state)
{
case MU_NNTP_NO_STATE:
if (message_id == NULL || *message_id == '\0')
{
status = mu_nntp_writeline (nntp, "STAT\r\n");
}
else
{
status = mu_nntp_writeline (nntp, "STAT %s\r\n", message_id);
}
MU_NNTP_CHECK_ERROR (nntp, status);
mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_STAT;
case MU_NNTP_STAT:
status = mu_nntp_send (nntp);
MU_NNTP_CHECK_EAGAIN (nntp, status);
nntp->acknowledge = 0;
nntp->state = MU_NNTP_STAT_ACK;
case MU_NNTP_STAT_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_ARTICLE_FOUND);
nntp->state = MU_NNTP_NO_STATE;
/* parse the answer now. */
status = mu_nntp_parse_article(nntp, MU_NNTP_RESP_CODE_ARTICLE_FOUND, number, mid);
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) 2003, 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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <mailutils/sys/nntp.h>
/* Implementation of the stream for HELP, ARTICLE, etc ... */
struct mu_nntp_stream
{
mu_nntp_t nntp;
int done;
};
static void
mu_nntp_stream_destroy (mu_stream_t stream)
{
struct mu_nntp_stream *nntp_stream = mu_stream_get_owner (stream);
if (nntp_stream)
{
free (nntp_stream);
}
}
static int
mu_nntp_stream_read (mu_stream_t stream, char *buf, size_t buflen, mu_off_t offset, size_t *pn)
{
struct mu_nntp_stream *nntp_stream = mu_stream_get_owner (stream);
size_t n = 0;
int status = 0;
char *p = buf;
(void)offset;
if (nntp_stream)
{
if (!nntp_stream->done)
{
do
{
size_t nread = 0;
/* The nntp_readline () function will always read one less to
be able to null terminate the buffer, this will cause
serious grief for mu_stream_read() where it is legitimate to
have a buffer of 1 char. So we must catch it here. */
if (buflen == 1)
{
char buffer[2];
*buffer = '\0';
status = mu_nntp_readline (nntp_stream->nntp, buffer, 2, &nread);
*p = *buffer;
}
else
status = mu_nntp_readline (nntp_stream->nntp, p, buflen, &nread);
if (status != 0)
break;
if (nread == 0)
{
nntp_stream->nntp->state = MU_NNTP_NO_STATE;
nntp_stream->done = 1;
break;
}
n += nread;
buflen -= nread;
p += nread;
}
while (buflen > 0);
}
}
if (pn)
*pn = n;
return status;
}
static int
mu_nntp_stream_readline (mu_stream_t stream, char *buf, size_t buflen, mu_off_t offset, size_t *pn)
{
struct mu_nntp_stream *nntp_stream = mu_stream_get_owner (stream);
size_t n = 0;
int status = 0;
(void)offset;
if (nntp_stream)
{
if (!nntp_stream->done)
{
status = mu_nntp_readline (nntp_stream->nntp, buf, buflen, &n);
if (n == 0)
{
nntp_stream->nntp->state = MU_NNTP_NO_STATE;
nntp_stream->done = 1;
}
}
}
if (pn)
*pn = n;
return status;
}
int
mu_nntp_stream_create (mu_nntp_t nntp, mu_stream_t *pstream)
{
struct mu_nntp_stream *nntp_stream;
int status;
nntp_stream = malloc (sizeof *nntp_stream);
if (nntp_stream == NULL)
return ENOMEM;
nntp_stream->nntp = nntp;
nntp_stream->done = 0;
status = mu_stream_create (pstream, MU_STREAM_READ | MU_STREAM_NO_CLOSE | MU_STREAM_NO_CHECK, nntp_stream);
if (status != 0)
{
free (nntp_stream);
return status;
}
mu_stream_set_read (*pstream, mu_nntp_stream_read, nntp_stream);
mu_stream_set_readline (*pstream, mu_nntp_stream_readline, nntp_stream);
mu_stream_set_destroy (*pstream, mu_nntp_stream_destroy, nntp_stream);
return 0;
}