/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2004, 2007, 2011-2012, 2014-2016 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 3 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, see . */ #ifndef _MAILUTILS_SYS_NNTP_H #define _MAILUTILS_SYS_NNTP_H #include #include #include #ifdef DMALLOC # include #endif #ifdef __cplusplus extern "C" { #endif /* Response codes. */ #define MU_NNTP_RESP_CODE_HELP_FOLLOW 100 #define MU_NNTP_RESP_CODE_SERVER_DATE 111 #define MU_NNTP_RESP_CODE_POSTING_ALLOWED 200 #define MU_NNTP_RESP_CODE_POSTING_PROHIBITED 201 #define MU_NNTP_RESP_CODE_EXTENSIONS_FOLLOW 202 #define MU_NNTP_RESP_CODE_CLOSING 205 #define MU_NNTP_RESP_CODE_GROUP_SELECTED 211 #define MU_NNTP_RESP_CODE_LIST_FOLLOW 215 #define MU_NNTP_RESP_CODE_ARTICLE_FOLLOW 220 #define MU_NNTP_RESP_CODE_HEAD_FOLLOW 221 #define MU_NNTP_RESP_CODE_BODY_FOLLOW 222 #define MU_NNTP_RESP_CODE_ARTICLE_FOUND 223 #define MU_NNTP_RESP_CODE_NEWNEWS_FOLLOW 230 #define MU_NNTP_RESP_CODE_NEWGROUPS_FOLLOW 231 #define MU_NNTP_RESP_CODE_TRANSFER_OK 235 #define MU_NNTP_RESP_CODE_ARTICLE_RECEIVED 240 #define MU_NNTP_RESP_CODE_TRANSFER_ARTICLE 335 #define MU_NNTP_RESP_CODE_SEND_ARTICLE 340 #define MU_NNTP_RESP_CODE_TEMP_UNAVAILABLE 400 #define MU_NNTP_RESP_CODE_NO_EXTENSION 402 #define MU_NNTP_RESP_CODE_NO_ARTICLE_WITH_MID 430 #define MU_NNTP_RESP_CODE_NO_GROUP_SELECTED 412 #define MU_NNTP_RESP_CODE_NUMBER_INVALID 420 #define MU_NNTP_RESP_CODE_NO_ARTICLE 422 #define MU_NNTP_RESP_CODE_NO_ARTICLE_IN_RANGE 423 #define MU_NNTP_RESP_CODE_ARTICLE_NOT_WANTED 435 #define MU_NNTP_RESP_CODE_TRANSFER_NOT_POSSIBLE 436 #define MU_NNTP_RESP_CODE_TRANSFER_REJECTED 437 #define MU_NNTP_RESP_CODE_POSTING_NOT_PERMITTED 440 #define MU_NNTP_RESP_CODE_POSTING_FAILED 441 #define MU_NNTP_RESP_CODE_PERM_UNAVAILABLE 502 enum mu_nntp_state { MU_NNTP_NO_STATE, MU_NNTP_CONNECT, MU_NNTP_GREETINGS, MU_NNTP_MODE_READER, MU_NNTP_MODE_READER_ACK, MU_NNTP_LIST_EXTENSIONS, MU_NNTP_LIST_EXTENSIONS_ACK, MU_NNTP_LIST_EXTENSIONS_RX, MU_NNTP_LIST_ACTIVE, MU_NNTP_LIST_ACTIVE_ACK, MU_NNTP_LIST_ACTIVE_RX, MU_NNTP_LIST_ACTIVE_TIMES, MU_NNTP_LIST_ACTIVE_TIMES_ACK, MU_NNTP_LIST_ACTIVE_TIMES_RX, MU_NNTP_LIST_DISTRIBUTIONS, MU_NNTP_LIST_DISTRIBUTIONS_ACK, MU_NNTP_LIST_DISTRIBUTIONS_RX, MU_NNTP_LIST_DISTRIB_PATS, MU_NNTP_LIST_DISTRIB_PATS_ACK, MU_NNTP_LIST_DISTRIB_PATS_RX, MU_NNTP_LIST_NEWSGROUPS, MU_NNTP_LIST_NEWSGROUPS_ACK, MU_NNTP_LIST_NEWSGROUPS_RX, MU_NNTP_QUIT, MU_NNTP_QUIT_ACK, MU_NNTP_GROUP, MU_NNTP_GROUP_ACK, MU_NNTP_LAST, MU_NNTP_LAST_ACK, MU_NNTP_NEXT, MU_NNTP_NEXT_ACK, MU_NNTP_ARTICLE, MU_NNTP_ARTICLE_ACK, MU_NNTP_ARTICLE_RX, MU_NNTP_HEAD, MU_NNTP_HEAD_ACK, MU_NNTP_HEAD_RX, MU_NNTP_BODY, MU_NNTP_BODY_ACK, MU_NNTP_BODY_RX, MU_NNTP_STAT, MU_NNTP_STAT_ACK, MU_NNTP_DATE, MU_NNTP_DATE_ACK, MU_NNTP_HELP, MU_NNTP_HELP_ACK, MU_NNTP_HELP_RX, MU_NNTP_NEWGROUPS, MU_NNTP_NEWGROUPS_ACK, MU_NNTP_NEWGROUPS_RX, MU_NNTP_NEWNEWS, MU_NNTP_NEWNEWS_ACK, MU_NNTP_NEWNEWS_RX, MU_NNTP_POST, MU_NNTP_POST_ACK, MU_NNTP_POST_0, MU_NNTP_POST_1, MU_NNTP_POST_2, MU_NNTP_POST_3, MU_NNTP_IHAVE, MU_NNTP_IHAVE_ACK, MU_NNTP_IHAVE_0, MU_NNTP_IHAVE_1, MU_NNTP_IHAVE_2, MU_NNTP_IHAVE_3, MU_NNTP_DONE, MU_NNTP_UNKNOWN, MU_NNTP_ERROR }; /* Structure holding the data necessary to do proper buffering. */ struct mu_nntp_work_buf { char *buf; char *ptr; char *nl; size_t len; }; /* Structure holding the data for post. */ struct mu_nntp_post_buf { char *buf; int sent_crlf; size_t nread; long offset; size_t len; }; /* Structure to hold things general to nntp connection, like its state, etc ... */ struct _mu_nntp { /* Working I/O buffer. io.buf: Working io buffer io.ptr: Points to the end of the buffer, the non consumed chars io.nl: Points to the '\n' char in the string io.len: Len of io_buf. */ struct mu_nntp_work_buf io; /* Holds the first line response of the last command, i.e the ACK: ack.buf: Buffer for the ack ack.ptr: Working pointer, indicate the start of the non consumed chars ack.len: Size 512 according to RFC2449. */ struct mu_nntp_work_buf ack; int acknowledge; /* Holds the buffer/offset etc ... for the article to post. */ struct mu_nntp_post_buf post; unsigned timeout; /* Default is 10 minutes. */ enum mu_nntp_state state; /* Indicate the state of the running command. */ mu_stream_t carrier; /* TCP Connection. */ }; extern int mu_nntp_debug_cmd (mu_nntp_t); extern int mu_nntp_debug_ack (mu_nntp_t); extern int mu_nntp_iterator_create (mu_nntp_t, mu_iterator_t *iterator); extern int mu_nntp_stream_create (mu_nntp_t nntp, mu_stream_t *pstream); extern int mu_nntp_carrier_is_ready (mu_stream_t carrier, int flag, int timeout); extern int mu_nntp_parse_article (mu_nntp_t nntp, int code, unsigned long *pnum, char **mid); /* Check for non recoverable error. The error is consider not recoverable if not part of the signal set: EAGAIN, EINPROGRESS, EINTR. For unrecoverable error we reset, by moving the working ptr to the begining of the buffer and setting the state to error. */ #define MU_NNTP_CHECK_EAGAIN(nntp, status) \ do \ { \ if (status != 0) \ { \ if (status != EAGAIN && status != EINPROGRESS && status != EINTR) \ { \ nntp->io.ptr = nntp->io.buf; \ nntp->state = MU_NNTP_ERROR; \ } \ return status; \ } \ } \ while (0) /* If error return. Check status an reset(see MU_NNTP_CHECK_EAGAIN) the buffer. */ #define MU_NNTP_CHECK_ERROR(nntp, status) \ do \ { \ if (status != 0) \ { \ nntp->io.ptr = nntp->io.buf; \ nntp->state = MU_NNTP_ERROR; \ return status; \ } \ } \ while (0) /* Check if we got the rigth. In NNTP protocol and ack of "2xx" means the command was completed. */ #define MU_NNTP_CHECK_CODE(nntp, code) \ do \ { \ if (mu_nntp_response_code (nntp) != code) \ { \ nntp->state = MU_NNTP_NO_STATE; \ return EACCES; \ } \ } \ while (0) #define MU_NNTP_CHECK_CODE2(nntp, code1, code2) \ do \ { \ if (mu_nntp_response_code (nntp) != code1 && mu_nntp_response_code (nntp) != code2) \ { \ nntp->state = MU_NNTP_NO_STATE; \ return EACCES; \ } \ } \ while (0) #ifdef __cplusplus } #endif #endif /* _MAILUTILS_SYS_NNTP_H */