summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/nntp
Side-by-side diff
Diffstat (limited to 'libetpan/src/driver/implementation/nntp') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.c1180
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.c1059
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c365
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.c169
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.c563
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.h88
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_types.h146
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.c267
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.h93
13 files changed, 4138 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.c b/libetpan/src/driver/implementation/nntp/nntpdriver.c
new file mode 100644
index 0000000..15b764f
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.c
@@ -0,0 +1,1180 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "nntpdriver.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "mail.h"
+#include "mailmessage.h"
+#include "nntpdriver_tools.h"
+#include "maildriver_tools.h"
+#include "nntpdriver_message.h"
+
+static int nntpdriver_initialize(mailsession * session);
+
+static void nntpdriver_uninitialize(mailsession * session);
+
+static int nntpdriver_parameters(mailsession * session,
+ int id, void * value);
+
+static int nntpdriver_connect_stream(mailsession * session, mailstream * s);
+
+static int nntpdriver_login(mailsession * session,
+ char * userid, char * password);
+
+static int nntpdriver_logout(mailsession * session);
+
+static int nntpdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int nntpdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_append_message(mailsession * session,
+ char * message, size_t size);
+
+static int nntpdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int
+nntpdriver_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+
+static int nntpdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int nntpdriver_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_subscribe_folder(mailsession * session, char * mb);
+
+static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb);
+
+static int nntpdriver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int nntpdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static int nntpdriver_noop(mailsession * session);
+
+static mailsession_driver local_nntp_session_driver = {
+ .sess_name = "nntp",
+
+ .sess_initialize = nntpdriver_initialize,
+ .sess_uninitialize = nntpdriver_uninitialize,
+
+ .sess_parameters = nntpdriver_parameters,
+
+ .sess_connect_stream = nntpdriver_connect_stream,
+ .sess_connect_path = NULL,
+ .sess_starttls = NULL,
+ .sess_login = nntpdriver_login,
+ .sess_logout = nntpdriver_logout,
+ .sess_noop = nntpdriver_noop,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = NULL,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = nntpdriver_select_folder,
+ .sess_expunge_folder = NULL,
+ .sess_status_folder = nntpdriver_status_folder,
+ .sess_messages_number = nntpdriver_messages_number,
+ .sess_recent_number = nntpdriver_messages_number,
+ .sess_unseen_number = nntpdriver_messages_number,
+ .sess_list_folders = nntpdriver_list_folders,
+ .sess_lsub_folders = nntpdriver_lsub_folders,
+ .sess_subscribe_folder = nntpdriver_subscribe_folder,
+ .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder,
+
+ .sess_append_message = nntpdriver_append_message,
+ .sess_append_message_flags = nntpdriver_append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = nntpdriver_get_messages_list,
+ .sess_get_envelopes_list = nntpdriver_get_envelopes_list,
+ .sess_remove_message = NULL,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = nntpdriver_get_message,
+ .sess_get_message_by_uid = nntpdriver_get_message_by_uid,
+};
+
+
+mailsession_driver * nntp_session_driver = &local_nntp_session_driver;
+
+static inline struct nntp_session_state_data *
+get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline newsnntp * get_nntp_session(mailsession * session)
+{
+ return get_data(session)->nntp_session;
+}
+
+static int nntpdriver_initialize(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+ newsnntp * nntp;
+
+ nntp = newsnntp_new(0, NULL);
+ if (nntp == NULL)
+ goto err;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto free;
+
+ data->nntp_session = nntp;
+
+ data->nntp_userid = NULL;
+ data->nntp_password = NULL;
+
+ data->nntp_group_info = NULL;
+ data->nntp_group_name = NULL;
+
+ data->nntp_subscribed_list = clist_new();
+ if (data->nntp_subscribed_list == NULL)
+ goto free_data;
+
+ data->nntp_max_articles = 0;
+
+ data->nntp_mode_reader = FALSE;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free_data:
+ free(data);
+ free:
+ newsnntp_free(nntp);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static void nntpdriver_uninitialize(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL);
+ clist_free(data->nntp_subscribed_list);
+
+ if (data->nntp_group_info != NULL)
+ newsnntp_group_free(data->nntp_group_info);
+
+ if (data->nntp_group_name != NULL)
+ free(data->nntp_group_name);
+
+ if (data->nntp_userid != NULL)
+ free(data->nntp_userid);
+
+ if (data->nntp_password != NULL)
+ free(data->nntp_password);
+
+ newsnntp_free(data->nntp_session);
+ free(data);
+
+ session->sess_data = NULL;
+}
+
+
+static int nntpdriver_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ switch (id) {
+ case NNTPDRIVER_SET_MAX_ARTICLES:
+ {
+ uint32_t * param;
+
+ param = value;
+
+ data->nntp_max_articles = * param;
+ return MAIL_NO_ERROR;
+ }
+ }
+
+ return MAIL_ERROR_INVAL;
+}
+
+
+static int add_to_list(mailsession * session, char * mb)
+{
+ char * new_mb;
+ int r;
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ new_mb = strdup(mb);
+ if (new_mb == NULL)
+ return -1;
+
+ r = clist_append(data->nntp_subscribed_list, new_mb);
+ if (r < 0) {
+ free(mb);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int remove_from_list(mailsession * session, char * mb)
+{
+ clistiter * cur;
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ char * cur_name;
+
+ cur_name = clist_content(cur);
+ if (strcmp(cur_name, mb) == 0) {
+ clist_delete(data->nntp_subscribed_list, cur);
+ free(cur_name);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+static int nntpdriver_connect_stream(mailsession * session, mailstream * s)
+{
+ int r;
+
+ r = newsnntp_connect(get_nntp_session(session), s);
+
+ switch (r) {
+ case NEWSNNTP_NO_ERROR:
+ return MAIL_NO_ERROR_NON_AUTHENTICATED;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+}
+
+static int nntpdriver_login(mailsession * session,
+ char * userid, char * password)
+{
+ struct nntp_session_state_data * data;
+ char * new_userid;
+ char * new_password;
+
+ data = get_data(session);
+
+ if (userid != NULL) {
+ new_userid = strdup(userid);
+ if (new_userid == NULL)
+ goto err;
+ }
+ else
+ new_userid = NULL;
+
+ if (password != NULL) {
+ new_password = strdup(password);
+ if (new_password == NULL)
+ goto free_uid;
+ }
+ else
+ new_password = NULL;
+
+ data->nntp_userid = new_userid;
+ data->nntp_password = new_password;
+
+ return MAIL_NO_ERROR;
+
+ free_uid:
+ if (new_userid != NULL)
+ free(new_userid);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static int nntpdriver_logout(mailsession * session)
+{
+ int r;
+
+ r = newsnntp_quit(get_nntp_session(session));
+
+ return nntpdriver_nntp_error_to_mail_error(r);
+}
+
+
+static int nntpdriver_status_folder(mailsession * session, char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ uint32_t count;
+ int r;
+
+ r = nntpdriver_select_folder(session, mb);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ r = nntpdriver_messages_number(session, mb, &count);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result_messages = count;
+ * result_recent = count;
+ * result_unseen = count;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_messages_number(mailsession * session, char * mb,
+ uint32_t * result)
+{
+ int r;
+ struct nntp_session_state_data * data;
+
+ if (mb != NULL) {
+ r = nntpdriver_select_folder(session, mb);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ }
+
+ data = get_data(session);
+
+ if (data->nntp_group_info == NULL)
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ * result = data->nntp_group_info->grp_last -
+ data->nntp_group_info->grp_first + 1;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ int r;
+ clist * group_list;
+ newsnntp * nntp;
+ clistiter * cur;
+ char * new_mb;
+ int done;
+ clist * list;
+ struct mail_list * ml;
+ int res;
+
+ nntp = get_nntp_session(session);
+
+ new_mb = NULL;
+ if ((mb != NULL) && (*mb != '\0')) {
+ new_mb = malloc(strlen(mb) + 3);
+ if (new_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+ strcpy(new_mb, mb);
+ strcat(new_mb, ".*");
+ }
+
+ done = FALSE;
+ do {
+ if (new_mb != NULL)
+ r = newsnntp_list_active(nntp, new_mb, &group_list);
+ else
+ r = newsnntp_list(nntp, &group_list);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ if (new_mb != NULL)
+ free(new_mb);
+ done = TRUE;
+ break;
+
+ default:
+ if (new_mb != NULL)
+ free(new_mb);
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(group_list) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ struct newsnntp_group_info * info;
+ char * new_name;
+
+ info = clist_content(cur);
+ new_name = strdup(info->grp_name);
+ if (new_name == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, new_name);
+ if (r < 0) {
+ free(new_name);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ ml = mail_list_new(list);
+ if (ml == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ newsnntp_list_free(group_list);
+
+ * result = ml;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) free, NULL);
+ clist_free(list);
+ newsnntp_list_free(group_list);
+ err:
+ return res;
+}
+
+static int nntpdriver_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ clist * subscribed;
+ clist * lsub_result;
+ clistiter * cur;
+ struct mail_list * lsub;
+ size_t length;
+ int res;
+ int r;
+ struct nntp_session_state_data * data;
+
+ length = strlen(mb);
+
+ data = get_data(session);
+
+ subscribed = data->nntp_subscribed_list;
+ lsub_result = clist_new();
+ if (lsub_result == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(cur = clist_begin(subscribed) ; cur != NULL ;
+ cur = clist_next(cur)) {
+ char * cur_mb;
+ char * new_mb;
+
+ cur_mb = clist_content(cur);
+
+ if (strncmp(mb, cur_mb, length) == 0) {
+ new_mb = strdup(cur_mb);
+ if (new_mb == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(lsub_result, new_mb);
+ if (r < 0) {
+ free(new_mb);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+ }
+
+ lsub = mail_list_new(lsub_result);
+ if (lsub == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = lsub;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(lsub_result, (clist_func) free, NULL);
+ clist_free(lsub_result);
+ err:
+ return res;
+}
+
+static int nntpdriver_subscribe_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = add_to_list(session, mb);
+ if (r < 0)
+ return MAIL_ERROR_SUBSCRIBE;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb)
+{
+ int r;
+
+ r = remove_from_list(session, mb);
+ if (r < 0)
+ return MAIL_ERROR_UNSUBSCRIBE;
+
+ return MAIL_NO_ERROR;
+}
+
+
+
+/* messages operations */
+
+static int nntpdriver_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ int r;
+ struct nntp_session_state_data * data;
+
+ data = get_data(session);
+
+ do {
+ r = newsnntp_post(get_nntp_session(session), message, size);
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (1);
+}
+
+static int nntpdriver_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ return nntpdriver_append_message(session, message, size);
+}
+
+
+static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
+ struct mailimf_fields ** result);
+
+
+static int
+nntpdriver_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ newsnntp * nntp;
+ int r;
+ struct nntp_session_state_data * data;
+ clist * list;
+ int done;
+ clistiter * cur;
+ uint32_t first_seq;
+ unsigned int i;
+
+ nntp = get_nntp_session(session);
+
+ data = get_data(session);
+
+ if (data->nntp_group_info == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ first_seq = data->nntp_group_info->grp_first;
+
+ if (carray_count(env_list->msg_tab) > 0) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, 0);
+
+ first_seq = msg->msg_index;
+ }
+
+ if (carray_count(env_list->msg_tab) > 0) {
+ i = carray_count(env_list->msg_tab) - 1;
+ while (1) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ first_seq = msg->msg_index + 1;
+ break;
+ }
+
+ if (i == 0)
+ break;
+
+ i --;
+ }
+ }
+
+ if (first_seq > data->nntp_group_info->grp_last) {
+ list = NULL;
+ }
+ else {
+ done = FALSE;
+ do {
+ r = newsnntp_xover_range(nntp, first_seq,
+ data->nntp_group_info->grp_last, &list);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+ }
+
+#if 0
+ i = 0;
+ j = 0;
+
+ if (list != NULL) {
+ for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
+ struct newsnntp_xover_resp_item * item;
+ struct mailimf_fields * fields;
+
+ item = clist_content(cur);
+
+ while (i < carray_count(env_list->msg_tab)) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+
+ if (item->ovr_article == info->msg_index) {
+
+ if (info->fields == NULL) {
+ r = xover_resp_to_fields(item, &fields);
+ if (r == MAIL_NO_ERROR) {
+ info->fields = fields;
+ }
+
+ info->size = item->ovr_size;
+
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ i ++;
+ break;
+ }
+ else {
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ }
+ }
+ else {
+ if (info->fields != NULL) {
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ }
+ else {
+ if (info->flags != NULL) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
+ mailmessage_check(info);
+ }
+ mailmessage_free(info);
+ carray_set(env_list->msg_tab, i, NULL);
+ }
+ }
+
+ i ++;
+ }
+ }
+ }
+
+ while (i < carray_count(env_list->msg_tab)) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+ if (info->fields != NULL) {
+ carray_set(env_list->msg_tab, j, info);
+ j ++;
+ }
+ else {
+ if (info->flags != NULL) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
+ mailmessage_check(info);
+ }
+ mailmessage_free(info);
+ carray_set(env_list->msg_tab, i, NULL);
+ }
+
+ i ++;
+ }
+
+ r = carray_set_size(env_list->msg_tab, j);
+ if (r < 0) {
+ if (list != NULL)
+ newsnntp_xover_resp_list_free(list);
+ return MAIL_ERROR_MEMORY;
+ }
+#endif
+ i = 0;
+
+ if (list != NULL) {
+ for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
+ struct newsnntp_xover_resp_item * item;
+ struct mailimf_fields * fields;
+
+ item = clist_content(cur);
+
+ while (i < carray_count(env_list->msg_tab)) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+
+ if (item->ovr_article == info->msg_index) {
+
+ if (info->msg_fields == NULL) {
+ r = xover_resp_to_fields(item, &fields);
+ if (r == MAIL_NO_ERROR) {
+ info->msg_fields = fields;
+ }
+
+ info->msg_size = item->ovr_size;
+
+ i ++;
+ break;
+ }
+ }
+#if 0
+ else if ((info->fields == NULL) && (info->flags != NULL)) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_CANCELLED;
+ mailmessage_check(info);
+ }
+#endif
+
+ i ++;
+ }
+ }
+ }
+
+#if 0
+ while (i < env_list->msg_tab->len) {
+ mailmessage * info;
+
+ info = carray_get(env_list->msg_tab, i);
+ if ((info->fields == NULL) && (info->flags != NULL)) {
+ info->flags->flags &= ~MAIL_FLAG_NEW;
+ info->flags->flags |= MAIL_FLAG_CANCELLED;
+ mailmessage_check(info);
+ }
+
+ i ++;
+ }
+#endif
+
+ if (list != NULL)
+ newsnntp_xover_resp_list_free(list);
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
+ struct mailimf_fields ** result)
+{
+ size_t cur_token;
+ clist * list;
+ int r;
+ struct mailimf_fields * fields;
+ int res;
+
+ list = clist_new();
+ if (list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ if (item->ovr_subject != NULL) {
+ char * subject_str;
+ struct mailimf_subject * subject;
+ struct mailimf_field * field;
+
+ subject_str = strdup(item->ovr_subject);
+ if (subject_str == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ subject = mailimf_subject_new(subject_str);
+ if (subject == NULL) {
+ free(subject_str);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, subject, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_subject_free(subject);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r < 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ if (item->ovr_author != NULL) {
+ struct mailimf_mailbox_list * mb_list;
+ struct mailimf_from * from;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+ r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author),
+ &cur_token, &mb_list);
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ from = mailimf_from_new(mb_list);
+ if (from == NULL) {
+ mailimf_mailbox_list_free(mb_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_FROM,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, from,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_from_free(from);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r < 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ break;
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ if (item->ovr_date != NULL) {
+ struct mailimf_date_time * date_time;
+ struct mailimf_orig_date * orig_date;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+ r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date),
+ &cur_token, &date_time);
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ orig_date = mailimf_orig_date_new(date_time);
+ if (orig_date == NULL) {
+ mailimf_date_time_free(date_time);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, orig_date, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (field == NULL) {
+ mailimf_orig_date_free(orig_date);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = clist_append(list, field);
+ if (r < 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ break;
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ if (item->ovr_message_id != NULL) {
+ char * msgid_str;
+ struct mailimf_message_id * msgid;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+ r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id),
+ &cur_token, &msgid_str);
+
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ msgid = mailimf_message_id_new(msgid_str);
+ if (msgid == NULL) {
+ mailimf_msg_id_free(msgid_str);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, msgid, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+
+ r = clist_append(list, field);
+ if (r < 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ break;
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ if (item->ovr_references != NULL) {
+ clist * msgid_list;
+ struct mailimf_references * references;
+ struct mailimf_field * field;
+
+ cur_token = 0;
+
+ r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references),
+ &cur_token, &msgid_list);
+
+ switch (r) {
+ case MAILIMF_NO_ERROR:
+ references = mailimf_references_new(msgid_list);
+ if (references == NULL) {
+ clist_foreach(msgid_list,
+ (clist_func) mailimf_msg_id_free, NULL);
+ clist_free(msgid_list);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ references, NULL, NULL, NULL, NULL);
+
+ r = clist_append(list, field);
+ if (r < 0) {
+ mailimf_field_free(field);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ case MAILIMF_ERROR_PARSE:
+ break;
+
+ default:
+ res = maildriver_imf_error_to_mail_error(r);
+ goto free_list;
+ }
+ }
+
+ fields = mailimf_fields_new(list);
+ if (fields == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ clist_foreach(list, (clist_func) mailimf_field_free, NULL);
+ clist_free(list);
+ err:
+ return res;
+}
+
+
+/* get messages list with group info */
+
+static int nntpdriver_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ return nntp_get_messages_list(session, session, nntp_message_driver, result);
+
+}
+
+static int nntpdriver_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg_info;
+ int r;
+
+ msg_info = mailmessage_new();
+ if (msg_info == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_noop(mailsession * session)
+{
+ newsnntp * nntp;
+ int r;
+ struct tm tm;
+
+ nntp = get_nntp_session(session);
+
+ r = newsnntp_date(nntp, &tm);
+
+ return nntpdriver_nntp_error_to_mail_error(r);
+}
+
+static int nntpdriver_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t num;
+ char * p;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ num = strtoul(uid, &p, 10);
+ if ((p == uid) || (* p != '\0'))
+ return MAIL_ERROR_INVAL;
+
+ return nntpdriver_get_message(session, num, result);
+ }
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.h b/libetpan/src/driver/implementation/nntp/nntpdriver.h
new file mode 100644
index 0000000..56aaa39
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef NNTPDRIVER_H
+
+#define NNTPDRIVER_H
+
+#include <libetpan/nntpdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * nntp_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c
new file mode 100644
index 0000000..5c29b7b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c
@@ -0,0 +1,1059 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "nntpdriver_cached.h"
+
+#include "libetpan-config.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "mail_cache_db.h"
+
+#include "mail.h"
+#include "mailmessage.h"
+#include "maildriver_tools.h"
+#include "nntpdriver.h"
+#include "maildriver.h"
+#include "newsnntp.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "maillock.h"
+#include "nntpdriver_cached_message.h"
+#include "nntpdriver_tools.h"
+
+static int nntpdriver_cached_initialize(mailsession * session);
+
+static void nntpdriver_cached_uninitialize(mailsession * session);
+
+static int nntpdriver_cached_parameters(mailsession * session,
+ int id, void * value);
+
+static int nntpdriver_cached_connect_stream(mailsession * session,
+ mailstream * s);
+
+static int nntpdriver_cached_login(mailsession * session,
+ char * userid, char * password);
+
+static int nntpdriver_cached_logout(mailsession * session);
+
+static int nntpdriver_cached_check_folder(mailsession * session);
+
+static int nntpdriver_cached_select_folder(mailsession * session, char * mb);
+
+static int nntpdriver_cached_status_folder(mailsession * session,
+ char * mb,
+ uint32_t * result_messages,
+ uint32_t * result_recent,
+ uint32_t * result_unseen);
+
+static int nntpdriver_cached_messages_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_cached_recent_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_cached_unseen_number(mailsession * session, char * mb,
+ uint32_t * result);
+
+static int nntpdriver_cached_append_message(mailsession * session,
+ char * message, size_t size);
+
+static int nntpdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
+
+static int
+nntpdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list);
+
+
+static int
+nntpdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result);
+
+static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result);
+
+static int nntpdriver_cached_subscribe_folder(mailsession * session,
+ char * mb);
+
+static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
+ char * mb);
+
+static int nntpdriver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result);
+
+static int nntpdriver_cached_noop(mailsession * session);
+
+static int nntpdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result);
+
+static mailsession_driver local_nntp_cached_session_driver = {
+ .sess_name = "nntp-cached",
+
+ .sess_initialize = nntpdriver_cached_initialize,
+ .sess_uninitialize = nntpdriver_cached_uninitialize,
+
+ .sess_parameters = nntpdriver_cached_parameters,
+
+ .sess_connect_stream = nntpdriver_cached_connect_stream,
+ .sess_connect_path = NULL,
+ .sess_starttls = NULL,
+ .sess_login = nntpdriver_cached_login,
+ .sess_logout = nntpdriver_cached_logout,
+ .sess_noop = nntpdriver_cached_noop,
+
+ .sess_build_folder_name = NULL,
+ .sess_create_folder = NULL,
+ .sess_delete_folder = NULL,
+ .sess_rename_folder = NULL,
+ .sess_check_folder = nntpdriver_cached_check_folder,
+ .sess_examine_folder = NULL,
+ .sess_select_folder = nntpdriver_cached_select_folder,
+ .sess_expunge_folder = NULL,
+ .sess_status_folder = nntpdriver_cached_status_folder,
+ .sess_messages_number = nntpdriver_cached_messages_number,
+ .sess_recent_number = nntpdriver_cached_recent_number,
+ .sess_unseen_number = nntpdriver_cached_unseen_number,
+ .sess_list_folders = nntpdriver_cached_list_folders,
+ .sess_lsub_folders = nntpdriver_cached_lsub_folders,
+ .sess_subscribe_folder = nntpdriver_cached_subscribe_folder,
+ .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder,
+
+ .sess_append_message = nntpdriver_cached_append_message,
+ .sess_append_message_flags = nntpdriver_cached_append_message_flags,
+ .sess_copy_message = NULL,
+ .sess_move_message = NULL,
+
+ .sess_get_messages_list = nntpdriver_cached_get_messages_list,
+ .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list,
+ .sess_remove_message = NULL,
+#if 0
+ .sess_search_messages = maildriver_generic_search_messages,
+#endif
+
+ .sess_get_message = nntpdriver_cached_get_message,
+ .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid,
+};
+
+
+mailsession_driver * nntp_cached_session_driver =
+&local_nntp_cached_session_driver;
+
+#define ENV_NAME "env.db"
+#define FLAGS_NAME "flags.db"
+
+
+
+static void read_article_seq(mailsession * session,
+ uint32_t * pfirst, uint32_t * plast);
+
+static void write_article_seq(mailsession * session,
+ uint32_t first, uint32_t last);
+
+
+static inline struct nntp_cached_session_state_data *
+get_cached_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession * get_ancestor(mailsession * session)
+{
+ return get_cached_data(session)->nntp_ancestor;
+}
+
+static inline struct nntp_session_state_data *
+get_ancestor_data(mailsession * session)
+{
+ return get_ancestor(session)->sess_data;
+}
+
+static inline newsnntp * get_nntp_session(mailsession * session)
+{
+ return get_ancestor_data(session)->nntp_session;
+}
+
+static int nntpdriver_cached_initialize(mailsession * session)
+{
+ struct nntp_cached_session_state_data * data;
+
+ data = malloc(sizeof(* data));
+ if (data == NULL)
+ goto err;
+
+ data->nntp_flags_store = mail_flags_store_new();
+ if (data->nntp_flags_store == NULL)
+ goto free;
+
+ data->nntp_ancestor = mailsession_new(nntp_session_driver);
+ if (data->nntp_ancestor == NULL)
+ goto free_store;
+
+ session->sess_data = data;
+
+ return MAIL_NO_ERROR;
+
+ free_store:
+ mail_flags_store_free(data->nntp_flags_store);
+ free:
+ free(data);
+ err:
+ return MAIL_ERROR_MEMORY;
+}
+
+static int nntp_flags_store_process(char * flags_directory, char * group_name,
+ struct mail_flags_store * flags_store)
+{
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ unsigned int i;
+ int r;
+ int res;
+
+ if (carray_count(flags_store->fls_tab) == 0)
+ return MAIL_NO_ERROR;
+
+ if (group_name == NULL)
+ return MAIL_NO_ERROR;
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ flags_directory, group_name, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_FILE;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(flags_store->fls_tab, i);
+
+ r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_index, msg->msg_flags);
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ mail_flags_store_clear(flags_store);
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static void nntpdriver_cached_uninitialize(mailsession * session)
+{
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ mail_flags_store_free(cached_data->nntp_flags_store);
+
+ mailsession_free(cached_data->nntp_ancestor);
+ free(cached_data);
+
+ session->sess_data = NULL;
+}
+
+static int nntpdriver_cached_parameters(mailsession * session,
+ int id, void * value)
+{
+ struct nntp_cached_session_state_data * cached_data;
+ int r;
+
+ cached_data = get_cached_data(session);
+
+ switch (id) {
+ case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY:
+ strncpy(cached_data->nntp_cache_directory, value, PATH_MAX);
+ cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(cached_data->nntp_cache_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY:
+ strncpy(cached_data->nntp_flags_directory, value, PATH_MAX);
+ cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0';
+
+ r = generic_cache_create_dir(cached_data->nntp_flags_directory);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ return MAIL_NO_ERROR;
+
+ default:
+ return mailsession_parameters(get_ancestor(session), id, value);
+ }
+}
+
+static int nntpdriver_cached_connect_stream(mailsession * session,
+ mailstream * s)
+{
+ return mailsession_connect_stream(get_ancestor(session), s);
+}
+
+static int nntpdriver_cached_login(mailsession * session,
+ char * userid, char * password)
+{
+ return mailsession_login(get_ancestor(session), userid, password);
+}
+
+static int nntpdriver_cached_logout(mailsession * session)
+{
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ return mailsession_logout(get_ancestor(session));
+}
+
+static int nntpdriver_cached_select_folder(mailsession * session, char * mb)
+{
+ int r;
+ struct nntp_session_state_data * ancestor_data;
+ struct nntp_cached_session_state_data * cached_data;
+ int res;
+ char key[PATH_MAX];
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ r = mailsession_select_folder(get_ancestor(session), mb);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ if (ancestor_data->nntp_group_name == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name);
+
+ r = generic_cache_create_dir(key);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name);
+
+ r = generic_cache_create_dir(key);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int nntpdriver_cached_check_folder(mailsession * session)
+{
+ struct nntp_session_state_data * ancestor_data;
+ struct nntp_cached_session_state_data * cached_data;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ return MAIL_NO_ERROR;
+}
+
+
+static int nntpdriver_cached_status_folder(mailsession * session,
+ char * mb, uint32_t * result_messages, uint32_t * result_recent,
+ uint32_t * result_unseen)
+{
+ int res;
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ uint32_t i;
+ int r;
+ uint32_t recent;
+ uint32_t unseen;
+ uint32_t first;
+ uint32_t last;
+ uint32_t count;
+ uint32_t additionnal;
+
+ r = nntpdriver_cached_select_folder(session, mb);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ read_article_seq(session, &first, &last);
+
+ count = 0;
+ recent = 0;
+ unseen = 0;
+
+ ancestor_data = get_ancestor_data(session);
+ cached_data = get_cached_data(session);
+ if (ancestor_data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ if (ancestor_data->nntp_group_info->grp_first > first)
+ first = ancestor_data->nntp_group_info->grp_first;
+ if (last < first)
+ last = ancestor_data->nntp_group_info->grp_last;
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ for(i = first ; i <= last ; i++) {
+ struct mail_flags * flags;
+
+ r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
+ i, &flags);
+ if (r == MAIL_NO_ERROR) {
+ if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) {
+ mail_flags_free(flags);
+ continue;
+ }
+
+ count ++;
+ if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
+ recent ++;
+ }
+ if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
+ unseen ++;
+ }
+ mail_flags_free(flags);
+ }
+ }
+
+ if ((count == 0) && (first != last)) {
+ count = last - first + 1;
+ recent = count;
+ unseen = count;
+ }
+
+ additionnal = ancestor_data->nntp_group_info->grp_last - last;
+ recent += additionnal;
+ unseen += additionnal;
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ * result_messages = count;
+ * result_recent = recent;
+ * result_unseen = unseen;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
+
+static int nntpdriver_cached_messages_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = nntpdriver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = messages;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_recent_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = nntpdriver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = recent;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_unseen_number(mailsession * session,
+ char * mb,
+ uint32_t * result)
+{
+ uint32_t messages;
+ uint32_t recent;
+ uint32_t unseen;
+ int r;
+
+ r = nntpdriver_cached_status_folder(session, mb,
+ &messages, &recent, &unseen);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = unseen;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ return mailsession_list_folders(get_ancestor(session), mb, result);
+}
+
+static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
+ struct mail_list ** result)
+{
+ return mailsession_lsub_folders(get_ancestor(session), mb, result);
+}
+
+static int nntpdriver_cached_subscribe_folder(mailsession * session,
+ char * mb)
+{
+ return mailsession_subscribe_folder(get_ancestor(session), mb);
+}
+
+static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
+ char * mb)
+{
+ return mailsession_unsubscribe_folder(get_ancestor(session), mb);
+}
+
+
+
+/* messages operations */
+
+static int nntpdriver_cached_append_message(mailsession * session,
+ char * message, size_t size)
+{
+ return mailsession_append_message(get_ancestor(session), message, size);
+}
+
+static int nntpdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ return nntpdriver_cached_append_message(session, message, size);
+}
+
+
+
+static int
+get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields ** result)
+{
+ char keyname[PATH_MAX];
+ int r;
+ struct mailimf_fields * fields;
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%i-envelope", num);
+
+ r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = fields;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+static int
+write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
+ mailsession * session, uint32_t num,
+ struct mailimf_fields * fields)
+{
+ int r;
+ int res;
+ char keyname[PATH_MAX];
+
+ snprintf(keyname, PATH_MAX, "%i-envelope", num);
+
+ r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+#define SEQ_FILENAME "articles-seq"
+
+static void read_article_seq(mailsession * session,
+ uint32_t * pfirst, uint32_t * plast)
+{
+ FILE * f;
+ struct nntp_session_state_data * ancestor_data;
+ uint32_t first;
+ uint32_t last;
+ char seq_filename[PATH_MAX];
+ struct nntp_cached_session_state_data * cached_data;
+ int r;
+
+ first = 0;
+ last = 0;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ if (ancestor_data->nntp_group_name == NULL)
+ return;
+
+ snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, SEQ_FILENAME);
+ f = fopen(seq_filename, "r");
+
+ if (f != NULL) {
+ int fd;
+
+ fd = fileno(f);
+
+ r = maillock_read_lock(seq_filename, fd);
+ if (r == 0) {
+ MMAPString * mmapstr;
+ size_t cur_token;
+ char buf[sizeof(uint32_t) * 2];
+ size_t read_size;
+
+ read_size = fread(buf, 1, sizeof(uint32_t) * 2, f);
+ mmapstr = mmap_string_new_len(buf, read_size);
+ if (mmapstr != NULL) {
+ cur_token = 0;
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &first);
+ r = mailimf_cache_int_read(mmapstr, &cur_token, &last);
+
+ mmap_string_free(mmapstr);
+ }
+
+ maillock_read_unlock(seq_filename, fd);
+ }
+ fclose(f);
+ }
+
+ * pfirst = first;
+ * plast = last;
+}
+
+static void write_article_seq(mailsession * session,
+ uint32_t first, uint32_t last)
+{
+ FILE * f;
+ struct nntp_session_state_data * ancestor_data;
+ char seq_filename[PATH_MAX];
+ struct nntp_cached_session_state_data * cached_data;
+ int r;
+ int fd;
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ if (ancestor_data->nntp_group_name == NULL)
+ return;
+
+ snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, SEQ_FILENAME);
+
+ fd = creat(seq_filename, S_IRUSR | S_IWUSR);
+ if (fd < 0)
+ return;
+
+ f = fdopen(fd, "w");
+ if (f != NULL) {
+ r = maillock_write_lock(seq_filename, fd);
+ if (r == 0) {
+ MMAPString * mmapstr;
+ size_t cur_token;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr != NULL) {
+ r = mail_serialize_clear(mmapstr, &cur_token);
+ if (r == MAIL_NO_ERROR) {
+ r = mailimf_cache_int_write(mmapstr, &cur_token, first);
+ r = mailimf_cache_int_write(mmapstr, &cur_token, last);
+
+ fwrite(mmapstr->str, 1, mmapstr->len, f);
+ }
+
+ mmap_string_free(mmapstr);
+ }
+
+ maillock_write_unlock(seq_filename, fd);
+ }
+ fclose(f);
+ }
+ else
+ close(fd);
+}
+
+
+static void get_uid_from_filename(char * filename)
+{
+ char * p;
+
+ if (strcmp(filename, SEQ_FILENAME) == 0)
+ * filename = 0;
+
+ p = strstr(filename, "-header");
+ if (p != NULL)
+ * p = 0;
+}
+
+static int
+nntpdriver_cached_get_envelopes_list(mailsession * session,
+ struct mailmessage_list * env_list)
+{
+ int r;
+ unsigned int i;
+ struct nntp_cached_session_state_data * cached_data;
+ uint32_t first;
+ uint32_t last;
+ struct nntp_session_state_data * ancestor_data;
+ char filename_env[PATH_MAX];
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_env;
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ int res;
+ char cache_dir[PATH_MAX];
+
+ cached_data = get_cached_data(session);
+ ancestor_data = get_ancestor_data(session);
+
+ nntp_flags_store_process(cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name,
+ cached_data->nntp_flags_store);
+
+ if (ancestor_data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ /* read articles sequence */
+
+ read_article_seq(session, &first, &last);
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ snprintf(filename_env, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, ENV_NAME);
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name, FLAGS_NAME);
+
+ /* fill with cached */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+ struct mailimf_fields * fields;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if ((msg->msg_index < first) || (msg->msg_index > last))
+ continue;
+
+ if (msg->msg_fields == NULL) {
+ r = get_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, &fields);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_fields = fields;
+ msg->msg_cached = TRUE;
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+
+ r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
+
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ /* add flags */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_flags == NULL) {
+ struct mail_flags * flags;
+
+ r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_index, &flags);
+ if (r == MAIL_NO_ERROR) {
+ msg->msg_flags = flags;
+ }
+ else {
+ msg->msg_flags = mail_flags_new_empty();
+ if (msg->msg_fields == NULL) {
+ msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED;
+ mailmessage_check(msg);
+ }
+ }
+ }
+ }
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ r = mail_cache_db_open_lock(filename_env, &cache_db_env);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_env;
+ }
+
+ /* must write cache */
+
+ for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, i);
+
+ if (msg->msg_fields != NULL) {
+ if (!msg->msg_cached) {
+ r = write_cached_envelope(cache_db_env, mmapstr,
+ session, msg->msg_index, msg->msg_fields);
+ }
+ }
+
+ if (msg->msg_flags != NULL) {
+ r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
+ msg->msg_index, msg->msg_flags);
+ }
+ }
+
+ first = 0;
+ last = 0;
+ if (carray_count(env_list->msg_tab) > 0) {
+ mailmessage * msg;
+
+ msg = carray_get(env_list->msg_tab, 0);
+ first = msg->msg_index;
+
+ msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1);
+ last = msg->msg_index;
+ }
+
+ /* write articles sequence */
+
+ write_article_seq(session, first, last);
+
+ /* flush cache */
+
+ maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
+
+ /* remove cache files */
+
+ snprintf(cache_dir, PATH_MAX, "%s/%s",
+ cached_data->nntp_cache_directory, ancestor_data->nntp_group_name);
+
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ mmap_string_free(mmapstr);
+
+ maildriver_message_cache_clean_up(cache_dir, env_list,
+ get_uid_from_filename);
+
+ return MAIL_NO_ERROR;
+
+ close_db_env:
+ mail_cache_db_close_unlock(filename_env, cache_db_env);
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ err:
+ return res;
+}
+
+static int
+nntpdriver_cached_get_messages_list(mailsession * session,
+ struct mailmessage_list ** result)
+{
+ return nntp_get_messages_list(get_ancestor(session), session,
+ nntp_cached_message_driver, result);
+}
+
+static int nntpdriver_cached_get_message(mailsession * session,
+ uint32_t num, mailmessage ** result)
+{
+ mailmessage * msg_info;
+ int r;
+
+ msg_info = mailmessage_new();
+ if (msg_info == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg_info);
+ return r;
+ }
+
+ * result = msg_info;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntpdriver_cached_noop(mailsession * session)
+{
+ return mailsession_noop(get_ancestor(session));
+}
+
+static int nntpdriver_cached_get_message_by_uid(mailsession * session,
+ const char * uid,
+ mailmessage ** result)
+{
+ uint32_t num;
+ char * p;
+
+ if (uid == NULL)
+ return MAIL_ERROR_INVAL;
+
+ num = strtoul(uid, &p, 10);
+ if ((p == uid) || (* p != '\0'))
+ return MAIL_ERROR_INVAL;
+
+ return nntpdriver_cached_get_message(session, num, result);
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h
new file mode 100644
index 0000000..c0264de
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef NNTPDRIVER_CACHED_H
+
+#define NNTPDRIVER_CACHED_H
+
+#include <libetpan/nntpdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailsession_driver * nntp_cached_session_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
new file mode 100644
index 0000000..131b689
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
@@ -0,0 +1,365 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "nntpdriver_cached_message.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "mail_cache_db.h"
+
+#include "mailmessage.h"
+#include "mailmessage_tools.h"
+#include "nntpdriver.h"
+#include "nntpdriver_tools.h"
+#include "nntpdriver_cached.h"
+#include "nntpdriver_message.h"
+#include "generic_cache.h"
+
+static int nntp_prefetch(mailmessage * msg_info);
+
+static void nntp_prefetch_free(struct generic_message_t * msg);
+
+static int nntp_initialize(mailmessage * msg_info);
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static void nntp_uninitialize(mailmessage * msg_info);
+
+static void nntp_flush(mailmessage * msg_info);
+
+static void nntp_check(mailmessage * msg_info);
+
+static int nntp_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result);
+
+static mailmessage_driver local_nntp_cached_message_driver = {
+ .msg_name = "nntp-cached",
+
+ .msg_initialize = nntp_initialize,
+ .msg_uninitialize = nntp_uninitialize,
+
+ .msg_flush = nntp_flush,
+ .msg_check = nntp_check,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = nntp_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = nntp_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = nntp_get_flags,
+};
+
+mailmessage_driver * nntp_cached_message_driver =
+&local_nntp_cached_message_driver;
+
+static inline struct nntp_cached_session_state_data *
+get_cached_session_data(mailmessage * msg)
+{
+ return msg->msg_session->sess_data;
+}
+
+static inline mailsession * get_ancestor_session(mailmessage * msg)
+{
+ return get_cached_session_data(msg)->nntp_ancestor;
+}
+
+static inline struct nntp_session_state_data *
+get_ancestor_session_data(mailmessage * msg)
+{
+ return get_ancestor_session(msg)->sess_data;
+}
+
+static inline newsnntp *
+get_nntp_session(mailmessage * msg)
+{
+ return get_ancestor_session_data(msg)->nntp_session;
+}
+
+static int nntp_prefetch(mailmessage * msg_info)
+{
+ char * msg_content;
+ size_t msg_length;
+ struct generic_message_t * msg;
+ int r;
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+ char filename[PATH_MAX];
+
+ /* we try the cached message */
+
+ cached_data = get_cached_session_data(msg_info);
+
+ ancestor_data = get_ancestor_session_data(msg_info);
+
+ snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, msg_info->msg_index);
+
+ r = generic_cache_read(filename, &msg_content, &msg_length);
+ if (r == MAIL_NO_ERROR) {
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+ }
+
+ /* we get the message through the network */
+
+ r = nntpdriver_article(get_ancestor_session(msg_info),
+ msg_info->msg_index, &msg_content,
+ &msg_length);
+
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ /* we write the message cache */
+
+ generic_cache_store(filename, msg_content, msg_length);
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void nntp_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int nntp_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[20];
+
+ snprintf(static_uid, 20, "%u", msg_info->msg_index);
+ uid = strdup(static_uid);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = nntp_prefetch;
+ msg->msg_prefetch_free = nntp_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+
+static void nntp_uninitialize(mailmessage * msg_info)
+{
+ mailmessage_generic_uninitialize(msg_info);
+}
+
+#define FLAGS_NAME "flags.db"
+
+static void nntp_flush(mailmessage * msg_info)
+{
+ mailmessage_generic_flush(msg_info);
+}
+
+
+static void nntp_check(mailmessage * msg_info)
+{
+ int r;
+
+ if (msg_info->msg_flags != NULL) {
+ r = mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store,
+ msg_info);
+ /* ignore errors */
+ }
+}
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ char * headers;
+ size_t headers_length;
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+ int r;
+ char filename[PATH_MAX];
+
+ msg = msg_info->msg_data;
+
+ if (msg->msg_message != NULL)
+ return mailmessage_generic_fetch_header(msg_info,
+ result, result_len);
+
+ /* we try the cached message */
+
+ cached_data = get_cached_session_data(msg_info);
+
+ ancestor_data = get_ancestor_session_data(msg_info);
+
+ snprintf(filename, PATH_MAX, "%s/%s/%i-header",
+ cached_data->nntp_cache_directory,
+ ancestor_data->nntp_group_name, msg_info->msg_index);
+
+ r = generic_cache_read(filename, &headers, &headers_length);
+ if (r == MAIL_NO_ERROR) {
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+ }
+
+ /* we get the message through the network */
+
+ r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index,
+ &headers, &headers_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ /* we write the message cache */
+
+ generic_cache_store(filename, headers, headers_length);
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ return nntpdriver_size(get_ancestor_session(msg_info),
+ msg_info->msg_index, result);
+}
+
+static int nntp_get_flags(mailmessage * msg_info,
+ struct mail_flags ** result)
+{
+ int r;
+ struct mail_flags * flags;
+ struct mail_cache_db * cache_db_flags;
+ char filename_flags[PATH_MAX];
+ int res;
+ MMAPString * mmapstr;
+
+ if (msg_info->msg_flags != NULL) {
+ * result = msg_info->msg_flags;
+
+ return MAIL_NO_ERROR;
+ }
+
+ flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index);
+
+ if (flags == NULL) {
+ struct nntp_cached_session_state_data * cached_data;
+ struct nntp_session_state_data * ancestor_data;
+
+ cached_data = get_cached_session_data(msg_info);
+
+ ancestor_data = get_ancestor_session_data(msg_info);
+ if (ancestor_data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ cached_data->nntp_flags_directory,
+ ancestor_data->nntp_group_name, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto close_db_flags;
+ }
+
+ r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
+ msg_info->msg_index, &flags);
+ if (r != MAIL_NO_ERROR) {
+ flags = mail_flags_new_empty();
+ if (flags == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_mmapstr;
+ }
+ }
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ }
+
+ msg_info->msg_flags = flags;
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ free_mmapstr:
+ mmap_string_free(mmapstr);
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h
new file mode 100644
index 0000000..f515d48
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include <libetpan/mailmessage_types.h>
+
+#ifndef NNTPDRIVER_CACHED_MESSAGE_H
+
+#define NNTPDRIVER_CACHED_MESSAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern mailmessage_driver * nntp_cached_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
new file mode 100644
index 0000000..117bc56
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
@@ -0,0 +1,169 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "nntpdriver_message.h"
+
+#include "mailmessage_tools.h"
+#include "nntpdriver_tools.h"
+#include "nntpdriver.h"
+#include "newsnntp.h"
+#include <string.h>
+#include <stdlib.h>
+
+static int nntp_prefetch(mailmessage * msg_info);
+
+static void nntp_prefetch_free(struct generic_message_t * msg);
+
+static int nntp_initialize(mailmessage * msg_info);
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len);
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result);
+
+static mailmessage_driver local_nntp_message_driver = {
+ .msg_name = "nntp",
+
+ .msg_initialize = nntp_initialize,
+ .msg_uninitialize = mailmessage_generic_uninitialize,
+
+ .msg_flush = mailmessage_generic_flush,
+ .msg_check = NULL,
+
+ .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
+
+ .msg_fetch = mailmessage_generic_fetch,
+ .msg_fetch_header = nntp_fetch_header,
+ .msg_fetch_body = mailmessage_generic_fetch_body,
+ .msg_fetch_size = nntp_fetch_size,
+ .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
+ .msg_fetch_section = mailmessage_generic_fetch_section,
+ .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
+ .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
+ .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
+ .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
+
+ .msg_get_flags = NULL,
+};
+
+mailmessage_driver * nntp_message_driver = &local_nntp_message_driver;
+
+static int nntp_prefetch(mailmessage * msg_info)
+{
+ char * msg_content;
+ size_t msg_length;
+ struct generic_message_t * msg;
+ int r;
+
+ r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index,
+ &msg_content, &msg_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ msg = msg_info->msg_data;
+
+ msg->msg_message = msg_content;
+ msg->msg_length = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static void nntp_prefetch_free(struct generic_message_t * msg)
+{
+ if (msg->msg_message != NULL) {
+ mmap_string_unref(msg->msg_message);
+ msg->msg_message = NULL;
+ }
+}
+
+static int nntp_initialize(mailmessage * msg_info)
+{
+ struct generic_message_t * msg;
+ int r;
+ char * uid;
+ char static_uid[20];
+
+ snprintf(static_uid, 20, "%u", msg_info->msg_index);
+ uid = strdup(static_uid);
+ if (uid == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ r = mailmessage_generic_initialize(msg_info);
+ if (r != MAIL_NO_ERROR) {
+ free(uid);
+ return r;
+ }
+
+ msg = msg_info->msg_data;
+ msg->msg_prefetch = nntp_prefetch;
+ msg->msg_prefetch_free = nntp_prefetch_free;
+ msg_info->msg_uid = uid;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntp_fetch_header(mailmessage * msg_info,
+ char ** result,
+ size_t * result_len)
+{
+ struct generic_message_t * msg;
+ char * headers;
+ size_t headers_length;
+ int r;
+
+ msg = msg_info->msg_data;
+
+ if (msg->msg_message != NULL)
+ return mailmessage_generic_fetch_header(msg_info,
+ result, result_len);
+
+ r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index,
+ &headers, &headers_length);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+static int nntp_fetch_size(mailmessage * msg_info,
+ size_t * result)
+{
+ return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result);
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_message.h
new file mode 100644
index 0000000..15e80b7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_message.h
@@ -0,0 +1,52 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef NNTPDRIVER_MESSAGE_H
+
+#define NNTPDRIVER_MESSAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libetpan/nntpdriver_types.h>
+
+extern mailmessage_driver * nntp_message_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
new file mode 100644
index 0000000..eef0953
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
@@ -0,0 +1,563 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "nntpdriver_tools.h"
+
+#include "mail.h"
+#include "nntpdriver.h"
+#include "nntpdriver_cached.h"
+#include "newsnntp.h"
+#include "maildriver_types.h"
+#include "generic_cache.h"
+#include "imfcache.h"
+#include "mailmessage.h"
+#include "mail_cache_db.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+int nntpdriver_nntp_error_to_mail_error(int error)
+{
+ switch (error) {
+ case NEWSNNTP_NO_ERROR:
+ return MAIL_NO_ERROR;
+
+ case NEWSNNTP_ERROR_STREAM:
+ return MAIL_ERROR_STREAM;
+
+ case NEWSNNTP_ERROR_UNEXPECTED:
+ return MAIL_ERROR_PROGRAM_ERROR;
+
+ case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED:
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED:
+ case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER:
+ case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND:
+ return MAIL_ERROR_MSG_NOT_FOUND;
+
+ case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE:
+ case NEWSNNTP_ERROR_INVALID_RESPONSE:
+ return MAIL_ERROR_PARSE;
+
+ case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP:
+ return MAIL_ERROR_FOLDER_NOT_FOUND;
+
+ case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED:
+ return MAIL_ERROR_READONLY;
+
+ case NEWSNNTP_ERROR_POSTING_FAILED:
+ return MAIL_ERROR_APPEND;
+
+ case NEWSNNTP_ERROR_PROGRAM_ERROR:
+ return MAIL_ERROR_PROGRAM_ERROR;
+
+ case NEWSNNTP_ERROR_NO_PERMISSION:
+ return MAIL_ERROR_NO_PERMISSION;
+
+ case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD:
+ case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED:
+ return MAIL_ERROR_COMMAND_NOT_SUPPORTED;
+
+ case NEWSNNTP_ERROR_CONNECTION_REFUSED:
+ return MAIL_ERROR_CONNECT;
+
+ case NEWSNNTP_ERROR_MEMORY:
+ return MAIL_ERROR_MEMORY;
+
+ case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED:
+ return MAIL_ERROR_LOGIN;
+
+ case NEWSNNTP_ERROR_BAD_STATE:
+ return MAIL_ERROR_BAD_STATE;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ default:
+ return MAIL_ERROR_INVAL;
+ }
+}
+
+static inline struct nntp_session_state_data *
+session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline newsnntp * session_get_nntp_session(mailsession * session)
+{
+ return session_get_data(session)->nntp_session;
+}
+
+static inline struct nntp_cached_session_state_data *
+cached_session_get_data(mailsession * session)
+{
+ return session->sess_data;
+}
+
+static inline mailsession * cached_session_get_ancestor(mailsession * session)
+{
+ return cached_session_get_data(session)->nntp_ancestor;
+}
+
+static inline struct nntp_session_state_data *
+cached_session_get_ancestor_data(mailsession * session)
+{
+ return session_get_data(cached_session_get_ancestor(session));
+}
+
+static inline newsnntp * cached_session_get_nntp_session(mailsession * session)
+{
+ return session_get_nntp_session(cached_session_get_ancestor(session));
+}
+
+
+int nntpdriver_authenticate_password(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+ int r;
+
+ data = session_get_data(session);
+
+ if (data->nntp_password == NULL)
+ return MAIL_ERROR_LOGIN;
+
+ r = newsnntp_authinfo_password(session_get_nntp_session(session),
+ data->nntp_password);
+
+ return nntpdriver_nntp_error_to_mail_error(r);
+}
+
+int nntpdriver_mode_reader(mailsession * session)
+{
+ int done;
+ int r;
+
+ done = FALSE;
+
+ do {
+ r = newsnntp_mode_reader(session_get_nntp_session(session));
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ done = TRUE;
+ break;
+ }
+ }
+ while (!done);
+
+ return MAIL_NO_ERROR;
+}
+
+int nntpdriver_authenticate_user(mailsession * session)
+{
+ struct nntp_session_state_data * data;
+ int r;
+
+ data = session_get_data(session);
+
+ if (data->nntp_userid == NULL)
+ return MAIL_ERROR_LOGIN;
+
+ r = newsnntp_authinfo_username(session_get_nntp_session(session),
+ data->nntp_userid);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ return nntpdriver_authenticate_password(session);
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+}
+
+int nntpdriver_article(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len)
+{
+ char * msg_content;
+ size_t msg_length;
+ int r;
+ int done;
+
+ done = FALSE;
+ do {
+ r = newsnntp_article(session_get_nntp_session(session),
+ index, &msg_content, &msg_length);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ * result = msg_content;
+ * result_len = msg_length;
+
+ return MAIL_NO_ERROR;
+}
+
+int nntpdriver_head(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len)
+{
+ char * headers;
+ size_t headers_length;
+ int r;
+ int done;
+
+ done = FALSE;
+ do {
+ r = newsnntp_head(session_get_nntp_session(session),
+ index, &headers, &headers_length);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ * result = headers;
+ * result_len = headers_length;
+
+ return MAIL_NO_ERROR;
+}
+
+int nntpdriver_size(mailsession * session, uint32_t index,
+ size_t * result)
+{
+ newsnntp * nntp;
+ struct newsnntp_xover_resp_item * item;
+ int r;
+ int done;
+
+ nntp = session_get_nntp_session(session);
+
+ done = FALSE;
+ do {
+ r = newsnntp_xover_single(nntp, index, &item);
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+ }
+ while (!done);
+
+ * result = item->ovr_size;
+
+ xover_resp_item_free(item);
+
+ return MAIL_NO_ERROR;
+}
+
+int
+nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags ** result)
+{
+ int r;
+ char keyname[PATH_MAX];
+ struct mail_flags * flags;
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%u-flags", num);
+
+ r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ * result = flags;
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+int
+nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags * flags)
+{
+ int r;
+ char keyname[PATH_MAX];
+ int res;
+
+ snprintf(keyname, PATH_MAX, "%u-flags", num);
+
+ r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ return MAIL_NO_ERROR;
+
+ err:
+ return res;
+}
+
+
+
+int nntpdriver_select_folder(mailsession * session, char * mb)
+{
+ int r;
+ struct newsnntp_group_info * info;
+ newsnntp * nntp_session;
+ struct nntp_session_state_data * data;
+ char * new_name;
+ int done;
+
+ data = session_get_data(session);
+
+ if (!data->nntp_mode_reader) {
+ r = nntpdriver_mode_reader(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+
+ data->nntp_mode_reader = TRUE;
+ }
+
+ if (data->nntp_group_name != NULL)
+ if (strcmp(data->nntp_group_name, mb) == 0)
+ return MAIL_NO_ERROR;
+
+ nntp_session = session_get_nntp_session(session);
+
+ done = FALSE;
+ do {
+ r = newsnntp_group(nntp_session, mb, &info);
+
+ switch (r) {
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
+ r = nntpdriver_authenticate_user(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
+ r = nntpdriver_authenticate_password(session);
+ if (r != MAIL_NO_ERROR)
+ return r;
+ break;
+
+ case NEWSNNTP_NO_ERROR:
+ done = TRUE;
+ break;
+
+ default:
+ return nntpdriver_nntp_error_to_mail_error(r);
+ }
+
+ }
+ while (!done);
+
+ new_name = strdup(mb);
+ if (new_name == NULL)
+ return MAIL_ERROR_MEMORY;
+
+ if (data->nntp_group_name != NULL)
+ free(data->nntp_group_name);
+ data->nntp_group_name = new_name;
+ if (data->nntp_group_info != NULL)
+ newsnntp_group_free(data->nntp_group_info);
+ data->nntp_group_info = info;
+
+ return MAIL_NO_ERROR;
+}
+
+
+int nntp_get_messages_list(mailsession * nntp_session,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result)
+{
+ carray * tab;
+ struct mailmessage_list * env_list;
+ uint32_t i;
+ int res;
+ int r;
+ struct nntp_session_state_data * data;
+ struct newsnntp_group_info * group_info;
+ uint32_t max;
+ unsigned int cur;
+
+ data = session_get_data(nntp_session);
+
+ if (data->nntp_group_name == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ r = nntpdriver_select_folder(nntp_session, data->nntp_group_name);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto err;
+ }
+
+ group_info = data->nntp_group_info;
+
+ if (group_info == NULL) {
+ res = MAIL_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ max = group_info->grp_first;
+ if (data->nntp_max_articles != 0) {
+ if (group_info->grp_last - data->nntp_max_articles + 1 > max)
+ max = group_info->grp_last - data->nntp_max_articles + 1;
+ }
+
+ tab = carray_new(128);
+ if (tab == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ for(i = max ; i <= group_info->grp_last ; i++) {
+ mailmessage * msg;
+
+ msg = mailmessage_new();
+ if (msg == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ r = mailmessage_init(msg, session, driver, i, 0);
+ if (r != MAIL_NO_ERROR) {
+ mailmessage_free(msg);
+ res = r;
+ goto free_list;
+ }
+
+ r = carray_add(tab, msg, NULL);
+ if (r < 0) {
+ mailmessage_free(msg);
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+ }
+
+ env_list = mailmessage_list_new(tab);
+ if (env_list == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_list;
+ }
+
+ * result = env_list;
+
+ return MAIL_NO_ERROR;
+
+ free_list:
+ for(cur = 0 ; cur < carray_count(tab) ; cur ++)
+ mailmessage_free(carray_get(tab, cur));
+ carray_free(tab);
+ err:
+ return res;
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
new file mode 100644
index 0000000..8ca9d16
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
@@ -0,0 +1,88 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef NNTPDRIVER_TOOLS_H
+
+#define NNTPDRIVER_TOOLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mail_cache_db_types.h"
+#include "nntpdriver_types.h"
+
+int nntpdriver_nntp_error_to_mail_error(int error);
+
+int nntpdriver_authenticate_password(mailsession * session);
+
+int nntpdriver_authenticate_user(mailsession * session);
+
+int nntpdriver_article(mailsession * session, uint32_t index,
+ char ** result, size_t * result_len);
+
+int nntpdriver_head(mailsession * session, uint32_t index,
+ char ** result,
+ size_t * result_len);
+
+int nntpdriver_size(mailsession * session, uint32_t index,
+ size_t * result);
+
+int
+nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags ** result);
+
+int
+nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
+ MMAPString * mmapstr,
+ uint32_t num,
+ struct mail_flags * flags);
+
+int nntpdriver_select_folder(mailsession * session, char * mb);
+
+int nntp_get_messages_list(mailsession * nntp_session,
+ mailsession * session,
+ mailmessage_driver * driver,
+ struct mailmessage_list ** result);
+
+int nntpdriver_mode_reader(mailsession * session);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_types.h b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
new file mode 100644
index 0000000..7d4b74d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
@@ -0,0 +1,146 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef NNTPDRIVER_TYPES_H
+
+#define NNTPDRIVER_TYPES_H
+
+#include <libetpan/libetpan-config.h>
+
+#include <libetpan/maildriver_types.h>
+#include <libetpan/newsnntp.h>
+#include <libetpan/clist.h>
+#include <libetpan/generic_cache_types.h>
+#include <libetpan/mailstorage_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NNTP driver for session */
+
+enum {
+ NNTPDRIVER_SET_MAX_ARTICLES = 1,
+};
+
+struct nntp_session_state_data {
+ newsnntp * nntp_session;
+ char * nntp_userid;
+ char * nntp_password;
+
+ struct newsnntp_group_info * nntp_group_info;
+ char * nntp_group_name;
+
+ clist * nntp_subscribed_list;
+
+ uint32_t nntp_max_articles;
+
+ int nntp_mode_reader;
+};
+
+/* cached NNTP driver for session */
+
+enum {
+ /* the mapping of the parameters should be the same as for nntp */
+ NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1,
+ /* cache specific */
+ NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+};
+
+struct nntp_cached_session_state_data {
+ mailsession * nntp_ancestor;
+ char nntp_cache_directory[PATH_MAX];
+ char nntp_flags_directory[PATH_MAX];
+ struct mail_flags_store * nntp_flags_store;
+};
+
+
+/* nntp storage */
+
+/*
+ nntp_mailstorage is the state data specific to the IMAP4rev1 storage.
+
+ - storage this is the storage to initialize.
+
+ - servername this is the name of the NNTP server
+
+ - port is the port to connect to, on the server.
+ you give 0 to use the default port.
+
+ - connection_type is the type of socket layer to use.
+ The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS.
+
+ - auth_type is the authenticate mechanism to use.
+ The value can be NNTP_AUTH_TYPE_PLAIN.
+
+ - login is the login of the POP3 account.
+
+ - password is the password of the POP3 account.
+
+ - cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ - cache_directory is the location of the cache
+
+ - flags_directory is the location of the flags
+*/
+
+struct nntp_mailstorage {
+ char * nntp_servername;
+ uint16_t nntp_port;
+ char * nntp_command;
+ int nntp_connection_type;
+
+ int nntp_auth_type;
+ char * nntp_login;
+ char * nntp_password;
+
+ int nntp_cached;
+ char * nntp_cache_directory;
+ char * nntp_flags_directory;
+};
+
+/* this is the type of NNTP authentication */
+
+enum {
+ NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.c b/libetpan/src/driver/implementation/nntp/nntpstorage.c
new file mode 100644
index 0000000..8d0e4ff
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.c
@@ -0,0 +1,267 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "nntpstorage.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "maildriver.h"
+#include "nntpdriver.h"
+#include "nntpdriver_cached.h"
+#include "mailstorage_tools.h"
+#include "mail.h"
+
+/* nntp storage */
+
+#define NNTP_DEFAULT_PORT 119
+#define NNTPS_DEFAULT_PORT 563
+
+static int nntp_mailstorage_connect(struct mailstorage * storage);
+static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result);
+static void nntp_mailstorage_uninitialize(struct mailstorage * storage);
+
+static mailstorage_driver nntp_mailstorage_driver = {
+ .sto_name = "nntp",
+ .sto_connect = nntp_mailstorage_connect,
+ .sto_get_folder_session = nntp_mailstorage_get_folder_session,
+ .sto_uninitialize = nntp_mailstorage_uninitialize,
+};
+
+int nntp_mailstorage_init(struct mailstorage * storage,
+ char * nn_servername, uint16_t nn_port,
+ char * nn_command,
+ int nn_connection_type, int nn_auth_type,
+ char * nn_login, char * nn_password,
+ int nn_cached, char * nn_cache_directory, char * nn_flags_directory)
+{
+ struct nntp_mailstorage * nntp_storage;
+ int res;
+
+ nntp_storage = malloc(sizeof(* nntp_storage));
+ if (nntp_storage == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto err;
+ }
+
+ nntp_storage->nntp_servername = strdup(nn_servername);
+ if (nntp_storage->nntp_servername == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free;
+ }
+
+ nntp_storage->nntp_connection_type = nn_connection_type;
+
+ if (nn_port == 0) {
+ switch (nn_connection_type) {
+ case CONNECTION_TYPE_PLAIN:
+ case CONNECTION_TYPE_COMMAND:
+ nn_port = NNTP_DEFAULT_PORT;
+ break;
+
+ case CONNECTION_TYPE_TLS:
+ case CONNECTION_TYPE_COMMAND_TLS:
+ nn_port = NNTPS_DEFAULT_PORT;
+ break;
+
+ default:
+ res = MAIL_ERROR_INVAL;
+ goto free_servername;
+ }
+ }
+
+ nntp_storage->nntp_port = nn_port;
+
+ if (nn_command != NULL) {
+ nntp_storage->nntp_command = strdup(nn_command);
+ if (nntp_storage->nntp_command == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_servername;
+ }
+ }
+ else
+ nntp_storage->nntp_command = NULL;
+
+ nntp_storage->nntp_auth_type = nn_auth_type;
+
+ if (nn_login != NULL) {
+ nntp_storage->nntp_login = strdup(nn_login);
+ if (nntp_storage->nntp_login == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_command;
+ }
+ }
+ else
+ nntp_storage->nntp_login = NULL;
+
+ if (nn_password != NULL) {
+ nntp_storage->nntp_password = strdup(nn_password);
+ if (nntp_storage->nntp_password == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_login;
+ }
+ }
+ else
+ nntp_storage->nntp_password = NULL;
+
+ nntp_storage->nntp_cached = nn_cached;
+
+ if (nn_cached && (nn_cache_directory != NULL) &&
+ (nn_flags_directory != NULL)) {
+ nntp_storage->nntp_cache_directory = strdup(nn_cache_directory);
+ if (nntp_storage->nntp_cache_directory == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_password;
+ }
+ nntp_storage->nntp_flags_directory = strdup(nn_flags_directory);
+ if (nntp_storage->nntp_flags_directory == NULL) {
+ res = MAIL_ERROR_MEMORY;
+ goto free_cache_directory;
+ }
+ }
+ else {
+ nntp_storage->nntp_cached = FALSE;
+ nntp_storage->nntp_cache_directory = NULL;
+ nntp_storage->nntp_flags_directory = NULL;
+ }
+
+ storage->sto_data = nntp_storage;
+ storage->sto_driver = &nntp_mailstorage_driver;
+
+ return MAIL_NO_ERROR;
+
+ free_cache_directory:
+ free(nntp_storage->nntp_cache_directory);
+ free_password:
+ free(nntp_storage->nntp_password);
+ free_login:
+ free(nntp_storage->nntp_login);
+ free_command:
+ free(nn_command);
+ free_servername:
+ free(nntp_storage->nntp_servername);
+ free:
+ free(nntp_storage);
+ err:
+ return res;
+}
+
+static void nntp_mailstorage_uninitialize(struct mailstorage * storage)
+{
+ struct nntp_mailstorage * nntp_storage;
+
+ nntp_storage = storage->sto_data;
+
+ if (nntp_storage->nntp_flags_directory != NULL)
+ free(nntp_storage->nntp_flags_directory);
+ if (nntp_storage->nntp_cache_directory != NULL)
+ free(nntp_storage->nntp_cache_directory);
+ if (nntp_storage->nntp_password != NULL)
+ free(nntp_storage->nntp_password);
+ if (nntp_storage->nntp_login != NULL)
+ free(nntp_storage->nntp_login);
+ if (nntp_storage->nntp_command != NULL)
+ free(nntp_storage->nntp_command);
+ free(nntp_storage->nntp_servername);
+ free(nntp_storage);
+
+ storage->sto_data = NULL;
+}
+
+static int nntp_mailstorage_connect(struct mailstorage * storage)
+{
+ struct nntp_mailstorage * nntp_storage;
+ mailsession_driver * driver;
+ int r;
+ int res;
+ mailsession * session;
+
+ nntp_storage = storage->sto_data;
+
+ if (nntp_storage->nntp_cached)
+ driver = nntp_cached_session_driver;
+ else
+ driver = nntp_session_driver;
+
+ r = mailstorage_generic_connect(driver,
+ nntp_storage->nntp_servername,
+ nntp_storage->nntp_port, nntp_storage->nntp_command,
+ nntp_storage->nntp_connection_type,
+ NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
+ nntp_storage->nntp_cache_directory,
+ NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
+ nntp_storage->nntp_flags_directory,
+ &session);
+ switch (r) {
+ case MAIL_NO_ERROR_NON_AUTHENTICATED:
+ case MAIL_NO_ERROR_AUTHENTICATED:
+ case MAIL_NO_ERROR:
+ break;
+ default:
+ res = r;
+ goto err;
+ }
+
+ r = mailstorage_generic_auth(session, r,
+ nntp_storage->nntp_connection_type,
+ nntp_storage->nntp_login,
+ nntp_storage->nntp_password);
+ if (r != MAIL_NO_ERROR) {
+ res = r;
+ goto free;
+ }
+
+ storage->sto_session = session;
+
+ return MAIL_NO_ERROR;
+
+ free:
+ mailsession_free(session);
+ err:
+ return res;
+}
+
+static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
+ char * pathname, mailsession ** result)
+{
+ int r;
+
+ r = mailsession_select_folder(storage->sto_session, pathname);
+
+ * result = storage->sto_session;
+
+ return MAIL_NO_ERROR;
+}
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.h b/libetpan/src/driver/implementation/nntp/nntpstorage.h
new file mode 100644
index 0000000..7b046f4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.h
@@ -0,0 +1,93 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef NNTPSTORAGE_H
+
+#define NNTPSTORAGE_H
+
+#include <libetpan/nntpdriver_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ nntp_mailstorage_init is the constructor for a NNTP storage
+
+ @param storage this is the storage to initialize.
+
+ @param servername this is the name of the NNTP server
+
+ @param port is the port to connect to, on the server.
+ you give 0 to use the default port.
+
+ @param command the command used to connect to the server instead of
+ allowing normal TCP connections to be used.
+
+ @param connection_type is the type of socket layer to use.
+ The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
+ CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
+ CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
+ CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
+
+ @param auth_type is the authenticate mechanism to use.
+ The value can be NNTP_AUTH_TYPE_PLAIN.
+
+ @param login is the login of the POP3 account.
+
+ @param password is the password of the POP3 account.
+
+ @param cached if this value is != 0, a persistant cache will be
+ stored on local system.
+
+ @param cache_directory is the location of the cache
+
+ @param flags_directory is the location of the flags
+*/
+
+int nntp_mailstorage_init(struct mailstorage * storage,
+ char * nntp_servername, uint16_t nntp_port,
+ char * nntp_command,
+ int nntp_connection_type, int nntp_auth_type,
+ char * nntp_login, char * nntp_password,
+ int nntp_cached, char * nntp_cache_directory,
+ char * nntp_flags_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif