void procmsg_copy_messages(GSList *mlist) { GSList *cur, *copylist = NULL; MsgInfo *msginfo; FolderItem *dest = NULL; if (!mlist) return; folder_item_update_freeze(); for (cur = mlist; cur != NULL; cur = cur->next) { msginfo = (MsgInfo *)cur->data; if (!dest) { dest = msginfo->to_folder; copylist = g_slist_append(copylist, msginfo); } else if (dest == msginfo->to_folder) { copylist = g_slist_append(copylist, msginfo); } else { folder_item_copy_msgs(dest, copylist); g_slist_free(copylist); copylist = NULL; dest = msginfo->to_folder; copylist = g_slist_append(copylist, msginfo); } procmsg_msginfo_set_to_folder(msginfo, NULL); } if (copylist) { folder_item_copy_msgs(dest, copylist); g_slist_free(copylist); } folder_item_update_thaw(); }
void rssyl_update_format() { RUpdateFormatCtx *ctx = NULL; GSList *oldfeeds; gchar *old_feeds_xml = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, RSSYL_DIR, G_DIR_SEPARATOR_S, "feeds.xml", NULL); if (!g_file_test(old_feeds_xml, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) { g_free(old_feeds_xml); return; } debug_print("RSSyl: Old format found, updating.\n"); oldfeeds = rssyl_old_feed_metadata_parse(old_feeds_xml); /* We find all rssyl root folders and perform magic on each */ ctx = g_new0(RUpdateFormatCtx, 1); ctx->o_prev = NULL; ctx->o_parent = NULL; ctx->n_prev = NULL; ctx->n_parent = NULL; ctx->n_first = NULL; ctx->oldfeeds = oldfeeds; ctx->oldroots = NULL; ctx->reached_first_new = FALSE; folder_item_update_freeze(); /* Go through all RSSyl folders, making new copies */ folder_func_to_all_folders((FolderItemFunc)rssyl_update_format_func, ctx); g_slist_foreach(ctx->oldroots, _delete_old_roots_func, NULL); g_slist_free(ctx->oldroots); prefs_matcher_write_config(); folder_write_list(); folder_item_update_thaw(); g_free(ctx); g_remove(old_feeds_xml); g_free(old_feeds_xml); }
/* return values: -2 skipped, -1 error, 0 OK */ gint export_to_mbox(FolderItem *src, const gchar *mbox) { GSList *mlist; gint ret; cm_return_val_if_fail(src != NULL, -1); cm_return_val_if_fail(src->folder != NULL, -1); cm_return_val_if_fail(mbox != NULL, -1); debug_print("Exporting messages from %s into %s...\n", src->path, mbox); mlist = folder_item_get_msg_list(src); folder_item_update_freeze(); ret = export_list_to_mbox(mlist, mbox); folder_item_update_thaw(); procmsg_msg_list_free(mlist); return ret; }
gboolean rssyl_subscribe(FolderItem *parent, const gchar *url, gboolean verbose) { gchar *myurl = NULL, *tmpname = NULL, *tmpname2 = NULL; RFetchCtx *ctx; FolderItem *new_item; RFolderItem *ritem; gint i = 1; RSubCtx *sctx; gboolean edit_properties = FALSE; gchar *official_title = NULL; g_return_val_if_fail(parent != NULL, FALSE); g_return_val_if_fail(url != NULL, FALSE); log_print(LOG_PROTOCOL, RSSYL_LOG_SUBSCRIBING, url); myurl = my_normalize_url(url); /* Fetch the feed. */ ctx = rssyl_prep_fetchctx_from_url(myurl); g_free(myurl); g_return_val_if_fail(ctx != NULL, FALSE); rssyl_fetch_feed(ctx, verbose); debug_print("RSSyl: fetch success == %s\n", ctx->success ? "TRUE" : "FALSE"); if (!ctx->success) { /* User notification was already handled inside rssyl_fetch_feed(), * let's just return quietly. */ feed_free(ctx->feed); g_free(ctx->error); g_free(ctx); return FALSE; } if (verbose) { sctx = g_new0(RSubCtx, 1); sctx->feed = ctx->feed; sctx->edit_properties = FALSE; debug_print("RSSyl: Calling subscribe dialog routine...\n"); rssyl_subscribe_dialog(sctx); if (sctx->feed == NULL) { debug_print("RSSyl: User cancelled subscribe.\n"); g_free(sctx); return FALSE; } edit_properties = sctx->edit_properties; if (sctx->official_title != NULL) { debug_print("RSSyl: custom official title\n"); official_title = g_strdup(sctx->official_title); } if (sctx->edit_properties) debug_print("RSSyl: User wants to edit properties of the new feed.\n"); else debug_print("RSSyl: User does not want to edit properties of the new feed.\n"); g_free(sctx->official_title); g_free(sctx); } /* OK, feed is succesfully fetched and correct, let's add it to CM. */ /* Create a folder for it. */ tmpname = rssyl_format_string(ctx->feed->title, TRUE, TRUE); tmpname2 = g_strdup(tmpname); #ifdef G_OS_WIN32 /* Windows does not allow its filenames to start or end with a dot, * or to end with a space. */ if (tmpname2[0] == '.') tmpname2[0] = '_'; if (tmpname2[strlen(tmpname2) - 1] == '.') tmpname2[strlen(tmpname2) - 1] = '_'; if (tmpname2[strlen(tmpname2) - 1] == ' ') tmpname2[strlen(tmpname2) - 1] = '_'; #endif while (folder_find_child_item_by_name(parent, tmpname2) != 0 && i < 20) { debug_print("RSSyl: Folder '%s' already exists, trying another name\n", tmpname2); g_free(tmpname2); tmpname2 = g_strdup_printf("%s__%d", tmpname, ++i); } /* TODO: handle cases where i reaches 20 */ folder_item_update_freeze(); new_item = folder_create_folder(parent, tmpname2); g_free(tmpname); g_free(tmpname2); if (!new_item) { if (verbose) alertpanel_error(_("Couldn't create folder for new feed '%s'."), myurl); feed_free(ctx->feed); g_free(ctx->error); g_free(ctx); g_free(myurl); return FALSE; } debug_print("RSSyl: Adding '%s'\n", ctx->feed->url); ritem = (RFolderItem *)new_item; ritem->url = g_strdup(ctx->feed->url); if (official_title != NULL) { debug_print("RSSyl: storing official feed title '%s'\n", official_title); ritem->official_title = official_title; } if (feed_n_items(ctx->feed) > 0) feed_foreach_item(ctx->feed, rssyl_subscribe_foreach_func, (gpointer)ritem); folder_item_scan(new_item); folder_write_list(); if (edit_properties) rssyl_gtk_prop(ritem); folder_item_update_thaw(); return TRUE; }
gboolean rssyl_parse_feed(RFolderItem *ritem, Feed *feed) { gchar *tmp = NULL, *tmp2 = NULL; gint i = 1; g_return_val_if_fail(ritem != NULL, FALSE); g_return_val_if_fail(feed != NULL, FALSE); g_return_val_if_fail(feed->title != NULL, FALSE); debug_print("RSSyl: parse_feed\n"); /* Set the last_update timestamp here, so it is the same for all items */ ritem->last_update = time(NULL); /* If the upstream feed changed its title, change name of our folder * accordingly even if user has renamed it before. This makes sure that * user will be aware of the upstream title change. */ if( !ritem->ignore_title_rename && (ritem->official_title == NULL || strcmp(feed->title, ritem->official_title)) ) { g_free(ritem->official_title); ritem->official_title = g_strdup(feed->title); tmp = rssyl_format_string(feed->title, TRUE, TRUE); tmp2 = g_strdup(tmp); while (folder_item_rename(&ritem->item, tmp2) != 0 && i < 20) { g_free(tmp2); tmp2 = g_strdup_printf("%s__%d", tmp, ++i); debug_print("RSSyl: couldn't rename, trying '%s'\n", tmp2); } /* TODO: handle case when i reaches 20 */ g_free(tmp); g_free(tmp2); /* FIXME: update name in properties */ /* FIXME: store feed properties */ } folder_item_update_freeze(); /* Read contents of folder, so we can check for duplicates/updates */ rssyl_folder_read_existing(ritem); if( claws_is_exiting() ) { debug_print("RSSyl: Claws-Mail is exiting, bailing out\n"); log_print(LOG_PROTOCOL, RSSYL_LOG_ABORTED_EXITING, ritem->url); folder_item_update_thaw(); return TRUE; } /* Populate the ->deleted_items list so that we can check it when * adding each item. */ ritem->deleted_items = rssyl_deleted_update(ritem); /* Parse each item in the feed, adding or updating existing items if * necessary */ if( feed_n_items(feed) > 0 ) feed_foreach_item(feed, rssyl_foreach_parse_func, (gpointer)ritem); if( !ritem->keep_old && !ritem->fetching_comments ) { rssyl_folder_read_existing(ritem); rssyl_expire_items(ritem, feed); } rssyl_deleted_free(ritem->deleted_items); folder_item_scan(&ritem->item); folder_item_update_thaw(); if( !ritem->fetching_comments ) log_print(LOG_PROTOCOL, RSSYL_LOG_UPDATED, ritem->url); return TRUE; }
static gint inc_start(IncProgressDialog *inc_dialog) { IncSession *session; GList *qlist; Pop3Session *pop3_session; IncState inc_state; gint error_num = 0; gint new_msgs = 0; gchar *msg; gchar *fin_msg; FolderItem *processing, *inbox; GSList *msglist, *msglist_element; gboolean cancelled = FALSE; qlist = inc_dialog->queue_list; while (qlist != NULL) { GList *next = qlist->next; session = qlist->data; pop3_session = POP3_SESSION(session->session); pop3_session->user = g_strdup(pop3_session->ac_prefs->userid); if (pop3_session->ac_prefs->passwd) pop3_session->pass = g_strdup(pop3_session->ac_prefs->passwd); else { gchar *pass; if (inc_dialog->show_dialog) manage_window_focus_in (inc_dialog->dialog->window, NULL, NULL); pass = input_dialog_query_password_keep (pop3_session->ac_prefs->recv_server, pop3_session->user, &(pop3_session->ac_prefs->session_passwd)); if (inc_dialog->show_dialog) manage_window_focus_out (inc_dialog->dialog->window, NULL, NULL); if (pass) { pop3_session->pass = pass; } } qlist = next; } #define SET_PIXMAP_AND_TEXT(pix, str) \ { \ progress_dialog_list_set(inc_dialog->dialog, \ inc_dialog->cur_row, \ pix, \ NULL, \ str); \ } for (; inc_dialog->queue_list != NULL && !cancelled; inc_dialog->cur_row++) { session = inc_dialog->queue_list->data; pop3_session = POP3_SESSION(session->session); GSList *filtered, *unfiltered; if (pop3_session->pass == NULL) { SET_PIXMAP_AND_TEXT(okpix, _("Cancelled")); inc_session_destroy(session); inc_dialog->queue_list = g_list_remove(inc_dialog->queue_list, session); continue; } inc_progress_dialog_clear(inc_dialog); progress_dialog_scroll_to_row(inc_dialog->dialog, inc_dialog->cur_row); SET_PIXMAP_AND_TEXT(currentpix, _("Retrieving")); /* begin POP3 session */ inc_state = inc_pop3_session_do(session); switch (inc_state) { case INC_SUCCESS: if (pop3_session->cur_total_num > 0) msg = g_strdup_printf( ngettext("Done (%d message (%s) received)", "Done (%d messages (%s) received)", pop3_session->cur_total_num), pop3_session->cur_total_num, to_human_readable((goffset)pop3_session->cur_total_recv_bytes)); else msg = g_strdup_printf(_("Done (no new messages)")); SET_PIXMAP_AND_TEXT(okpix, msg); g_free(msg); break; case INC_CONNECT_ERROR: SET_PIXMAP_AND_TEXT(errorpix, _("Connection failed")); break; case INC_AUTH_FAILED: SET_PIXMAP_AND_TEXT(errorpix, _("Auth failed")); if (pop3_session->ac_prefs->session_passwd) { g_free(pop3_session->ac_prefs->session_passwd); pop3_session->ac_prefs->session_passwd = NULL; } break; case INC_LOCKED: SET_PIXMAP_AND_TEXT(errorpix, _("Locked")); break; case INC_ERROR: case INC_NO_SPACE: case INC_IO_ERROR: case INC_SOCKET_ERROR: case INC_EOF: SET_PIXMAP_AND_TEXT(errorpix, _("Error")); break; case INC_TIMEOUT: SET_PIXMAP_AND_TEXT(errorpix, _("Timeout")); break; case INC_CANCEL: SET_PIXMAP_AND_TEXT(okpix, _("Cancelled")); if (!inc_dialog->show_dialog) cancelled = TRUE; break; default: break; } if (pop3_session->error_val == PS_AUTHFAIL) { if(!prefs_common.no_recv_err_panel) { if((prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS) || ((prefs_common.recv_dialog_mode == RECV_DIALOG_MANUAL) && focus_window)) manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL); } } /* CLAWS: perform filtering actions on dropped message */ /* CLAWS: get default inbox (perhaps per account) */ if (pop3_session->ac_prefs->inbox) { /* CLAWS: get destination folder / mailbox */ inbox = folder_find_item_from_identifier(pop3_session->ac_prefs->inbox); if (!inbox) inbox = folder_get_default_inbox(); } else inbox = folder_get_default_inbox(); /* get list of messages in processing */ processing = folder_get_default_processing(); folder_item_scan(processing); msglist = folder_item_get_msg_list(processing); /* process messages */ folder_item_update_freeze(); procmsg_msglist_filter(msglist, pop3_session->ac_prefs, &filtered, &unfiltered, pop3_session->ac_prefs->filter_on_recv); filtering_move_and_copy_msgs(msglist); if (unfiltered != NULL) folder_item_move_msgs(inbox, unfiltered); for(msglist_element = msglist; msglist_element != NULL; msglist_element = msglist_element->next) { MsgInfo *msginfo = (MsgInfo *)msglist_element->data; procmsg_msginfo_free(msginfo); } folder_item_update_thaw(); g_slist_free(msglist); g_slist_free(filtered); g_slist_free(unfiltered); statusbar_pop_all(); new_msgs += pop3_session->cur_total_num; pop3_write_uidl_list(pop3_session); if (inc_state != INC_SUCCESS && inc_state != INC_CANCEL) { error_num++; if (inc_dialog->show_dialog) manage_window_focus_in (inc_dialog->dialog->window, NULL, NULL); inc_put_error(inc_state, pop3_session); if (inc_dialog->show_dialog) manage_window_focus_out (inc_dialog->dialog->window, NULL, NULL); if (inc_state == INC_NO_SPACE || inc_state == INC_IO_ERROR) break; } folder_item_free_cache(processing, TRUE); inc_session_destroy(session); inc_dialog->queue_list = g_list_remove(inc_dialog->queue_list, session); } #undef SET_PIXMAP_AND_TEXT if (new_msgs > 0) fin_msg = g_strdup_printf(ngettext("Finished (%d new message)", "Finished (%d new messages)", new_msgs), new_msgs); else fin_msg = g_strdup_printf(_("Finished (no new messages)")); progress_dialog_set_label(inc_dialog->dialog, fin_msg); while (inc_dialog->queue_list != NULL) { session = inc_dialog->queue_list->data; inc_session_destroy(session); inc_dialog->queue_list = g_list_remove(inc_dialog->queue_list, session); } if (prefs_common.close_recv_dialog || !inc_dialog->show_dialog) inc_progress_dialog_destroy(inc_dialog); else { gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window), fin_msg); gtk_button_set_label(GTK_BUTTON(inc_dialog->dialog->cancel_btn), GTK_STOCK_CLOSE); } g_free(fin_msg); return new_msgs; }
gint proc_mbox(FolderItem *dest, const gchar *mbox, gboolean apply_filter, PrefsAccount *account) /* return values: -1 error, >=0 number of msgs added */ { FILE *mbox_fp; gchar buf[MESSAGEBUFSIZE]; gchar *tmp_file; gint msgs = 0; gint lines; MsgInfo *msginfo; gboolean more; GSList *to_filter = NULL, *filtered = NULL, *unfiltered = NULL, *cur, *to_add = NULL; gboolean printed = FALSE; FolderItem *dropfolder; cm_return_val_if_fail(dest != NULL, -1); cm_return_val_if_fail(mbox != NULL, -1); debug_print("Getting messages from %s into %s...\n", mbox, dest->path); if ((mbox_fp = g_fopen(mbox, "rb")) == NULL) { FILE_OP_ERROR(mbox, "fopen"); alertpanel_error(_("Could not open mbox file:\n%s\n"), mbox); return -1; } /* ignore empty lines on the head */ do { if (fgets(buf, sizeof(buf), mbox_fp) == NULL) { g_warning("can't read mbox file.\n"); fclose(mbox_fp); return -1; } } while (buf[0] == '\n' || buf[0] == '\r'); if (strncmp(buf, "From ", 5) != 0) { g_warning("invalid mbox format: %s\n", mbox); fclose(mbox_fp); return -1; } tmp_file = get_tmp_file(); folder_item_update_freeze(); if (apply_filter) dropfolder = folder_get_default_processing(); else dropfolder = dest; do { FILE *tmp_fp; gint empty_lines; gint msgnum; if (msgs > 0 && msgs%500 == 0) { if (printed) statusbar_pop_all(); statusbar_print_all( ngettext("Importing from mbox... (%d mail imported)", "Importing from mbox... (%d mails imported)", msgs), msgs); printed=TRUE; GTK_EVENTS_FLUSH(); } if ((tmp_fp = g_fopen(tmp_file, "wb")) == NULL) { FILE_OP_ERROR(tmp_file, "fopen"); g_warning("can't open temporary file\n"); fclose(mbox_fp); g_free(tmp_file); return -1; } if (change_file_mode_rw(tmp_fp, tmp_file) < 0) { FILE_OP_ERROR(tmp_file, "chmod"); } empty_lines = 0; lines = 0; /* process all lines from mboxrc file */ while (fgets(buf, sizeof(buf), mbox_fp) != NULL) { int offset; /* eat empty lines */ if (buf[0] == '\n' || buf[0] == '\r') { empty_lines++; continue; } /* From separator or quoted From */ offset = 0; /* detect leading '>' char(s) */ while ((buf[offset] == '>')) { offset++; } if (!strncmp(buf+offset, "From ", 5)) { /* From separator: */ if (offset == 0) { /* expect next mbox item */ break; } /* quoted From: */ /* flush any eaten empty line */ if (empty_lines > 0) { while (empty_lines-- > 0) { FPUTS_TO_TMP_ABORT_IF_FAIL("\n"); } empty_lines = 0; } /* store the unquoted line */ FPUTS_TO_TMP_ABORT_IF_FAIL(buf + 1); continue; } /* other line */ /* flush any eaten empty line */ if (empty_lines > 0) { while (empty_lines-- > 0) { FPUTS_TO_TMP_ABORT_IF_FAIL("\n"); } empty_lines = 0; } /* store the line itself */ FPUTS_TO_TMP_ABORT_IF_FAIL(buf); } /* end of mbox item or end of mbox */ /* flush any eaten empty line (but the last one) */ if (empty_lines > 0) { while (--empty_lines > 0) { FPUTS_TO_TMP_ABORT_IF_FAIL("\n"); } } /* more emails to expect? */ more = !feof(mbox_fp); /* warn if email part is empty (it's the minimum check we can do */ if (lines == 0) { g_warning("malformed mbox: %s: message %d is empty\n", mbox, msgs); fclose(tmp_fp); fclose(mbox_fp); claws_unlink(tmp_file); return -1; } if (fclose(tmp_fp) == EOF) { FILE_OP_ERROR(tmp_file, "fclose"); g_warning("can't write to temporary file\n"); fclose(mbox_fp); claws_unlink(tmp_file); g_free(tmp_file); return -1; } if (apply_filter) { if ((msgnum = folder_item_add_msg(dropfolder, tmp_file, NULL, TRUE)) < 0) { fclose(mbox_fp); claws_unlink(tmp_file); g_free(tmp_file); return -1; } msginfo = folder_item_get_msginfo(dropfolder, msgnum); to_filter = g_slist_prepend(to_filter, msginfo); } else { MsgFileInfo *finfo = g_new0(MsgFileInfo, 1); finfo->file = tmp_file; to_add = g_slist_prepend(to_add, finfo); tmp_file = get_tmp_file(); /* flush every 500 */ if (msgs > 0 && msgs % 500 == 0) { folder_item_add_msgs(dropfolder, to_add, TRUE); procmsg_message_file_list_free(to_add); to_add = NULL; } } msgs++; } while (more); if (printed) statusbar_pop_all(); if (apply_filter) { folder_item_set_batch(dropfolder, FALSE); procmsg_msglist_filter(to_filter, account, &filtered, &unfiltered, TRUE); folder_item_set_batch(dropfolder, TRUE); filtering_move_and_copy_msgs(to_filter); for (cur = filtered; cur; cur = g_slist_next(cur)) { MsgInfo *info = (MsgInfo *)cur->data; procmsg_msginfo_free(info); } unfiltered = g_slist_reverse(unfiltered); if (unfiltered) { folder_item_move_msgs(dest, unfiltered); for (cur = unfiltered; cur; cur = g_slist_next(cur)) { MsgInfo *info = (MsgInfo *)cur->data; procmsg_msginfo_free(info); } } g_slist_free(unfiltered); g_slist_free(filtered); g_slist_free(to_filter); } else if (to_add) { folder_item_add_msgs(dropfolder, to_add, TRUE); procmsg_message_file_list_free(to_add); to_add = NULL; } folder_item_update_thaw(); g_free(tmp_file); fclose(mbox_fp); debug_print("%d messages found.\n", msgs); return msgs; }