/* * 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: feeddriver.c,v 1.1 2007/01/18 09:15:01 hoa Exp $ */ #ifdef HAVE_CONFIG_H # include #endif #include "feeddriver.h" #include #include #include "mailimf_types_helper.h" #include "newsfeed.h" #include "mail.h" #include "mailmessage.h" #include "maildriver_tools.h" #include "feeddriver_message.h" #include "feeddriver_types.h" #define MIN_DELAY 5 static int feeddriver_initialize(mailsession * session); static void feeddriver_uninitialize(mailsession * session); static int feeddriver_connect_path(mailsession * session, const char * path); static int feeddriver_status_folder(mailsession * session, const char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int feeddriver_messages_number(mailsession * session, const char * mb, uint32_t * result); static int feeddriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list); static int feeddriver_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int feeddriver_get_message(mailsession * session, uint32_t num, mailmessage ** result); static int feeddriver_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result); static mailsession_driver local_feed_session_driver = { /* sess_name */ "feed", /* sess_initialize */ feeddriver_initialize, /* sess_uninitialize */ feeddriver_uninitialize, /* sess_parameters */ NULL, /* sess_connect_stream */ NULL, /* sess_connect_path */ feeddriver_connect_path, /* sess_starttls */ NULL, /* sess_login */ NULL, /* sess_logout */ NULL, /* sess_noop */ NULL, /* 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 */ NULL, /* sess_expunge_folder */ NULL, /* sess_status_folder */ feeddriver_status_folder, /* sess_messages_number */ feeddriver_messages_number, /* sess_recent_number */ feeddriver_messages_number, /* sess_unseen_number */ feeddriver_messages_number, /* sess_list_folders */ NULL, /* sess_lsub_folders */ NULL, /* sess_subscribe_folder */ NULL, /* sess_unsubscribe_folder */ NULL, /* sess_append_message */ NULL, /* sess_append_message_flags */ NULL, /* sess_copy_message */ NULL, /* sess_move_message */ NULL, /* sess_get_message */ feeddriver_get_message, /* sess_get_message_by_uid */ feeddriver_get_message_by_uid, /* sess_get_messages_list */ feeddriver_get_messages_list, /* sess_get_envelopes_list */ feeddriver_get_envelopes_list, /* sess_remove_message */ NULL, /* sess_login_sasl */ NULL, }; mailsession_driver * feed_session_driver = &local_feed_session_driver; static void update(mailsession * session); static int feeddriver_feed_error_to_mail_error(int error) { switch (error) { case NEWSFEED_NO_ERROR: return MAIL_NO_ERROR; case NEWSFEED_ERROR_CANCELLED: return MAIL_ERROR_STREAM; case NEWSFEED_ERROR_INTERNAL: return MAIL_ERROR_UNKNOWN; case NEWSFEED_ERROR_BADURL: return MAIL_ERROR_INVAL; case NEWSFEED_ERROR_RESOLVE_PROXY: case NEWSFEED_ERROR_RESOLVE_HOST: return MAIL_ERROR_CONNECT; case NEWSFEED_ERROR_CONNECT: return MAIL_ERROR_CONNECT; case NEWSFEED_ERROR_STREAM: return MAIL_ERROR_STREAM; case NEWSFEED_ERROR_PROTOCOL: case NEWSFEED_ERROR_PARSE: return MAIL_ERROR_PARSE; case NEWSFEED_ERROR_ACCESS: return MAIL_ERROR_NO_PERMISSION; case NEWSFEED_ERROR_AUTHENTICATION: return MAIL_ERROR_LOGIN; case NEWSFEED_ERROR_FTP: return MAIL_ERROR_UNKNOWN; case NEWSFEED_ERROR_PARTIAL_FILE: case NEWSFEED_ERROR_FETCH: return MAIL_ERROR_FETCH; case NEWSFEED_ERROR_HTTP: return MAIL_ERROR_UNKNOWN; case NEWSFEED_ERROR_FILE: return MAIL_ERROR_FILE; case NEWSFEED_ERROR_PUT: return MAIL_ERROR_APPEND; case NEWSFEED_ERROR_MEMORY: return MAIL_ERROR_MEMORY; case NEWSFEED_ERROR_SSL: return MAIL_ERROR_SSL; case NEWSFEED_ERROR_LDAP: return MAIL_ERROR_UNKNOWN; case NEWSFEED_ERROR_UNSUPPORTED_PROTOCOL: return MAIL_ERROR_INVAL; } return MAIL_ERROR_UNKNOWN; } static inline struct feed_session_state_data * get_data(mailsession * session) { return session->sess_data; } static inline struct newsfeed * get_feed_session(mailsession * session) { return get_data(session)->feed_session; } static int feeddriver_initialize(mailsession * session) { struct feed_session_state_data * data; struct newsfeed * feed; feed = newsfeed_new(); if (feed == NULL) goto err; data = malloc(sizeof(* data)); if (data == NULL) goto free; data->feed_session = feed; data->feed_error = MAIL_NO_ERROR; session->sess_data = data; return MAIL_NO_ERROR; free: newsfeed_free(feed); err: return MAIL_ERROR_MEMORY; } static void feeddriver_uninitialize(mailsession * session) { struct feed_session_state_data * data; data = get_data(session); newsfeed_free(data->feed_session); free(data); session->sess_data = NULL; } static int feeddriver_connect_path(mailsession * session, const char * path) { struct feed_session_state_data * data; int r; data = get_data(session); r = newsfeed_set_url(data->feed_session, path); return feeddriver_feed_error_to_mail_error(r); } static int feeddriver_status_folder(mailsession * session, const char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { uint32_t count; int r; r = feeddriver_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 feeddriver_messages_number(mailsession * session, const char * mb, uint32_t * result) { struct feed_session_state_data * data; unsigned int count; int res; update(session); data = get_data(session); if (data->feed_error != MAIL_NO_ERROR) { res = data->feed_error; goto err; } count = newsfeed_item_list_get_count(data->feed_session); * result = count; return MAIL_NO_ERROR; err: return res; } static void update(mailsession * session) { int r; struct feed_session_state_data * data; time_t value; data = get_data(session); value = time(NULL); if (data->feed_last_update != (time_t) -1) { if (value - data->feed_last_update < MIN_DELAY) return; } r = newsfeed_update(data->feed_session, -1); data->feed_error = feeddriver_feed_error_to_mail_error(r); if (data->feed_error == MAIL_NO_ERROR) { value = time(NULL); data->feed_last_update = value; } } static int feeddriver_get_envelopes_list(mailsession * session, struct mailmessage_list * env_list) { return MAIL_NO_ERROR; } static mailmessage * feed_item_to_message(mailsession * session, unsigned int num, struct newsfeed_item * item) { struct mailimf_fields * fields; struct mailimf_date_time * date_time; time_t time; struct mailimf_mailbox_list * from; mailmessage * msg; char * subject; const char * subject_const; char * msg_id; int r; const char * author_const; from = NULL; author_const = newsfeed_item_get_author(item); if (author_const != NULL) { char * author; char * addr_spec; struct mailimf_mailbox * mb; author = strdup(author_const); if (author == NULL) { goto err; } from = mailimf_mailbox_list_new_empty(); if (from == NULL) { free(author); goto err; } addr_spec = strdup("invalid@localhost.local"); if (addr_spec == NULL) { free(author); goto free_from; } /* XXX - encode author with MIME */ mb = mailimf_mailbox_new(author, addr_spec); if (mb == NULL) { free(addr_spec); free(author); goto free_from; } r = mailimf_mailbox_list_add(from, mb); if (r != MAILIMF_NO_ERROR) { mailimf_mailbox_free(mb); goto free_from; } } date_time = NULL; time = newsfeed_item_get_date_modified(item); if (time != (time_t) -1) { date_time = mailimf_get_date(time); if (date_time == NULL) { goto free_from; } } subject = NULL; subject_const = newsfeed_item_get_title(item); if (subject_const != NULL) { subject = strdup(subject_const); if (subject == NULL) { goto free_date; } } msg_id = mailimf_get_message_id(); if (msg_id == NULL) { goto free_subject; } fields = mailimf_fields_new_with_data_all(date_time, from, NULL, NULL, NULL, NULL, NULL, msg_id, NULL, NULL, subject); msg = mailmessage_new(); r = mailmessage_init(msg, session, feed_message_driver, num, 0); if (r != MAIL_NO_ERROR) { goto free_fields; } msg->msg_fields = fields; return msg; free_fields: mailimf_fields_free(fields); goto err; free_subject: free(subject); free_date: mailimf_date_time_free(date_time); free_from: mailimf_mailbox_list_free(from); err: return NULL; } static int feeddriver_get_messages_list(mailsession * session, struct mailmessage_list ** result) { unsigned int i; struct feed_session_state_data * data; unsigned int count; struct mailmessage_list * msg_list; carray * tab; int res; int r; update(session); data = get_data(session); if (data->feed_error != MAIL_NO_ERROR) { res = data->feed_error; goto err; } count = newsfeed_item_list_get_count(data->feed_session); tab = carray_new(count); if (tab == NULL) { res = MAIL_ERROR_MEMORY; goto err; } fprintf(stderr, "count: %i\n", count); for(i = 0 ; i < count ; i ++) { struct newsfeed_item * item; mailmessage * msg; item = newsfeed_get_item(data->feed_session, i); msg = feed_item_to_message(session, i, item); r = carray_add(tab, msg, NULL); if (r < 0) { res = MAIL_ERROR_MEMORY; goto free_tab; } } msg_list = mailmessage_list_new(tab); if (msg_list == NULL) { res = MAIL_ERROR_MEMORY; goto free_tab; } * result = msg_list; return MAIL_NO_ERROR; free_tab: for(i = 0 ; i < carray_count(tab) ; i ++) { mailmessage * msg; msg = carray_get(tab, i); mailmessage_free(msg); } err: return res; } static int feeddriver_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, feed_message_driver, num, 0); if (r != MAIL_NO_ERROR) { mailmessage_free(msg_info); return r; } * result = msg_info; return MAIL_NO_ERROR; } static int feeddriver_get_message_by_uid(mailsession * session, const char * uid, mailmessage ** result) { #if 0 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 feeddriver_get_message(session, num, result); #endif return MAIL_ERROR_INVAL; }