gint lock_mbox(const gchar *base, LockType type) { #ifdef G_OS_UNIX gint retval = 0; if (type == LOCK_FILE) { gchar *lockfile, *locklink; gint retry = 0; FILE *lockfp; lockfile = g_strdup_printf("%s.%d", base, getpid()); if ((lockfp = g_fopen(lockfile, "wb")) == NULL) { FILE_OP_ERROR(lockfile, "fopen"); g_warning("can't create lock file %s\n", lockfile); g_warning("use 'flock' instead of 'file' if possible.\n"); g_free(lockfile); return -1; } if (fprintf(lockfp, "%d\n", getpid()) < 0) { FILE_OP_ERROR(lockfile, "fprintf"); g_free(lockfile); fclose(lockfp); return -1; } if (fclose(lockfp) == EOF) { FILE_OP_ERROR(lockfile, "fclose"); g_free(lockfile); return -1; } locklink = g_strconcat(base, ".lock", NULL); while (link(lockfile, locklink) < 0) { FILE_OP_ERROR(lockfile, "link"); if (retry >= 5) { g_warning("can't create %s\n", lockfile); claws_unlink(lockfile); g_free(lockfile); return -1; } if (retry == 0) g_warning("mailbox is owned by another" " process, waiting...\n"); retry++; sleep(5); } claws_unlink(lockfile); g_free(lockfile); } else if (type == LOCK_FLOCK) { gint lockfd; gboolean fcntled = FALSE; #if HAVE_FCNTL_H && !defined(G_OS_WIN32) struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; #endif #if HAVE_FLOCK if ((lockfd = g_open(base, O_RDWR, 0)) < 0) { #else if ((lockfd = g_open(base, O_RDWR, 0)) < 0) { #endif FILE_OP_ERROR(base, "open"); return -1; } #if HAVE_FCNTL_H && !defined(G_OS_WIN32) if (fcntl(lockfd, F_SETLK, &fl) == -1) { g_warning("can't fnctl %s (%s)", base, strerror(errno)); return -1; } else { fcntled = TRUE; } #endif #if HAVE_FLOCK if (flock(lockfd, LOCK_EX|LOCK_NB) < 0 && !fcntled) { perror("flock"); #else #if HAVE_LOCKF if (lockf(lockfd, F_TLOCK, 0) < 0 && !fcntled) { perror("lockf"); #else { #endif #endif /* HAVE_FLOCK */ g_warning("can't lock %s\n", base); if (close(lockfd) < 0) perror("close"); return -1; } retval = lockfd; } else { g_warning("invalid lock type\n"); return -1; } return retval; #else return -1; #endif /* G_OS_UNIX */ } gint unlock_mbox(const gchar *base, gint fd, LockType type) { if (type == LOCK_FILE) { gchar *lockfile; lockfile = g_strconcat(base, ".lock", NULL); if (claws_unlink(lockfile) < 0) { FILE_OP_ERROR(lockfile, "unlink"); g_free(lockfile); return -1; } g_free(lockfile); return 0; } else if (type == LOCK_FLOCK) { gboolean fcntled = FALSE; #if HAVE_FCNTL_H && !defined(G_OS_WIN32) struct flock fl; fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; if (fcntl(fd, F_SETLK, &fl) == -1) { g_warning("can't fnctl %s", base); } else { fcntled = TRUE; } #endif #if HAVE_FLOCK if (flock(fd, LOCK_UN) < 0 && !fcntled) { perror("flock"); #else #if HAVE_LOCKF if (lockf(fd, F_ULOCK, 0) < 0 && !fcntled) { perror("lockf"); #else { #endif #endif /* HAVE_FLOCK */ g_warning("can't unlock %s\n", base); if (close(fd) < 0) perror("close"); return -1; } if (close(fd) < 0) { perror("close"); return -1; } return 0; } g_warning("invalid lock type\n"); return -1; } gint copy_mbox(gint srcfd, const gchar *dest) { FILE *dest_fp; ssize_t n_read; gchar buf[BUFSIZ]; gboolean err = FALSE; int save_errno = 0; if (srcfd < 0) { return -1; } if ((dest_fp = g_fopen(dest, "wb")) == NULL) { FILE_OP_ERROR(dest, "fopen"); return -1; } if (change_file_mode_rw(dest_fp, dest) < 0) { FILE_OP_ERROR(dest, "chmod"); g_warning("can't change file mode\n"); } while ((n_read = read(srcfd, buf, sizeof(buf))) > 0) { if (n_read == -1 && errno != 0) { save_errno = errno; break; } if (fwrite(buf, 1, n_read, dest_fp) < n_read) { g_warning("writing to %s failed.\n", dest); fclose(dest_fp); claws_unlink(dest); return -1; } } if (save_errno != 0) { g_warning("error %d reading mbox: %s\n", save_errno, strerror(save_errno)); err = TRUE; } if (fclose(dest_fp) == EOF) { FILE_OP_ERROR(dest, "fclose"); err = TRUE; } if (err) { claws_unlink(dest); return -1; } return 0; } void empty_mbox(const gchar *mbox) { FILE *fp; if ((fp = g_fopen(mbox, "wb")) == NULL) { FILE_OP_ERROR(mbox, "fopen"); g_warning("can't truncate mailbox to zero.\n"); return; } fclose(fp); } gint export_list_to_mbox(GSList *mlist, const gchar *mbox) /* return values: -2 skipped, -1 error, 0 OK */ { GSList *cur; MsgInfo *msginfo; FILE *msg_fp; FILE *mbox_fp; gchar buf[BUFFSIZE]; int err = 0; gint msgs = 1, total = g_slist_length(mlist); if (g_file_test(mbox, G_FILE_TEST_EXISTS) == TRUE) { if (alertpanel_full(_("Overwrite mbox file"), _("This file already exists. Do you want to overwrite it?"), GTK_STOCK_CANCEL, _("Overwrite"), NULL, FALSE, NULL, ALERT_WARNING, G_ALERTDEFAULT) != G_ALERTALTERNATE) { return -2; } } if ((mbox_fp = g_fopen(mbox, "wb")) == NULL) { FILE_OP_ERROR(mbox, "fopen"); alertpanel_error(_("Could not create mbox file:\n%s\n"), mbox); return -1; } #ifdef HAVE_FGETS_UNLOCKED flockfile(mbox_fp); #endif statuswindow_print_all(_("Exporting to mbox...")); for (cur = mlist; cur != NULL; cur = cur->next) { int len; gchar buft[BUFFSIZE]; msginfo = (MsgInfo *)cur->data; msg_fp = procmsg_open_message(msginfo); if (!msg_fp) { continue; } #ifdef HAVE_FGETS_UNLOCKED flockfile(msg_fp); #endif strncpy2(buf, msginfo->from ? msginfo->from : cur_account && cur_account->address ? cur_account->address : "unknown", sizeof(buf)); extract_address(buf); if (fprintf(mbox_fp, "From %s %s", buf, ctime_r(&msginfo->date_t, buft)) < 0) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } buf[0] = '\0'; /* write email to mboxrc */ while (SC_FGETS(buf, sizeof(buf), msg_fp) != NULL) { /* quote any From, >From, >>From, etc., according to mbox format specs */ int offset; offset = 0; /* detect leading '>' char(s) */ while ((buf[offset] == '>')) { offset++; } if (!strncmp(buf+offset, "From ", 5)) { if (SC_FPUTC('>', mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } } if (SC_FPUTS(buf, mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } } /* force last line to end w/ a newline */ len = strlen(buf); if (len > 0) { len--; if ((buf[len] != '\n') && (buf[len] != '\r')) { if (SC_FPUTC('\n', mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } } } /* add a trailing empty line */ if (SC_FPUTC('\n', mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); statusbar_progress_all(msgs++,total, 500); if (msgs%500 == 0) GTK_EVENTS_FLUSH(); } out: statusbar_progress_all(0,0,0); statuswindow_pop_all(); #ifdef HAVE_FGETS_UNLOCKED funlockfile(mbox_fp); #endif fclose(mbox_fp); return err; }
static gboolean mail_filtering_hook(gpointer source, gpointer data) { MailFilteringData *mail_filtering_data = (MailFilteringData *) source; MsgInfo *msginfo = mail_filtering_data->msginfo; gboolean is_spam = FALSE, error = FALSE; static gboolean warned_error = FALSE; FILE *fp = NULL; int pid = 0; int status; /* SPAMASSASSIN_DISABLED : keep test for compatibility purpose */ if (!config.enable || config.transport == SPAMASSASSIN_DISABLED) { log_warning(LOG_PROTOCOL, _("SpamAssassin plugin is disabled by its preferences.\n")); return FALSE; } debug_print("Filtering message %d\n", msginfo->msgnum); if (message_callback != NULL) message_callback(_("SpamAssassin: filtering message...")); if ((fp = procmsg_open_message(msginfo)) == NULL) { debug_print("failed to open message file\n"); return FALSE; } if (config.whitelist_ab) { gchar *ab_folderpath; gboolean whitelisted = FALSE; if (*config.whitelist_ab_folder == '\0' || strcasecmp(config.whitelist_ab_folder, "Any") == 0) { /* match the whole addressbook */ ab_folderpath = NULL; } else { /* match the specific book/folder of the addressbook */ ab_folderpath = config.whitelist_ab_folder; } start_address_completion(ab_folderpath); if (msginfo->from && sa_found_in_addressbook(msginfo->from)) whitelisted = TRUE; end_address_completion(); if (whitelisted) { debug_print("message is ham (whitelisted)\n"); fclose(fp); return FALSE; } } pid = fork(); if (pid == 0) { _exit(msg_is_spam(fp)); } else { gint running = 0; running |= CHILD_RUNNING; g_timeout_add(50, timeout_func, &running); running |= TIMEOUT_RUNNING; while(running & CHILD_RUNNING) { int ret; ret = waitpid(pid, &status, WNOHANG); if (ret == pid) { if (WIFEXITED(status)) { MsgStatus result = MSG_IS_HAM; running &= ~CHILD_RUNNING; result = WEXITSTATUS(status); is_spam = (result == MSG_IS_SPAM) ? TRUE : FALSE; error = (result == MSG_FILTERING_ERROR); } } if (ret < 0) { running &= ~CHILD_RUNNING; } /* ret == 0 continue */ g_main_context_iteration(NULL, TRUE); } while (running & TIMEOUT_RUNNING) g_main_context_iteration(NULL, TRUE); } fclose(fp); if (is_spam) { debug_print("message is spam\n"); procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0); if (config.receive_spam) { FolderItem *save_folder = NULL; if ((!config.save_folder) || (config.save_folder[0] == '\0') || ((save_folder = folder_find_item_from_identifier(config.save_folder)) == NULL)) { if (mail_filtering_data->account && mail_filtering_data->account->set_trash_folder) { save_folder = folder_find_item_from_identifier( mail_filtering_data->account->trash_folder); if (save_folder) debug_print("found trash folder from account's advanced settings\n"); } if (save_folder == NULL && mail_filtering_data->account && mail_filtering_data->account->folder) { save_folder = mail_filtering_data->account->folder->trash; if (save_folder) debug_print("found trash folder from account's trash\n"); } if (save_folder == NULL && mail_filtering_data->account && !mail_filtering_data->account->folder) { if (mail_filtering_data->account->inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->inbox); if (item && item->folder->trash) { save_folder = item->folder->trash; debug_print("found trash folder from account's inbox\n"); } } if (!save_folder && mail_filtering_data->account->local_inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->local_inbox); if (item && item->folder->trash) { save_folder = item->folder->trash; debug_print("found trash folder from account's local_inbox\n"); } } } if (save_folder == NULL) { debug_print("using default trash folder\n"); save_folder = folder_get_default_trash(); } } if (config.mark_as_read) procmsg_msginfo_unset_flags(msginfo, ~0, 0); procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0); msginfo->filter_op = IS_MOVE; msginfo->to_filter_folder = save_folder; } else { folder_item_remove_msg(msginfo->folder, msginfo->msgnum); } return TRUE; } else { debug_print("message is ham\n"); procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0); } if (error) { gchar *msg = _("The SpamAssassin plugin couldn't filter " "a message. The probable cause of the error " "is an unreachable spamd daemon. Please make " "sure spamd is running and accessible."); if (!prefs_common_get_prefs()->no_recv_err_panel) { if (!warned_error) { alertpanel_error("%s", msg); } warned_error = TRUE; } else { log_error(LOG_PROTOCOL, "%s\n", msg); } } return FALSE; }
void procmsg_get_filter_keyword(MsgInfo *msginfo, gchar **header, gchar **key, PrefsFilterType type) { static HeaderEntry hentry[] = {{"X-BeenThere:", NULL, TRUE}, {"X-ML-Name:", NULL, TRUE}, {"X-List:", NULL, TRUE}, {"X-Mailing-list:", NULL, TRUE}, {"List-Id:", NULL, TRUE}, {"X-Sequence:", NULL, TRUE}, {NULL, NULL, FALSE}}; enum { H_X_BEENTHERE = 0, H_X_ML_NAME = 1, H_X_LIST = 2, H_X_MAILING_LIST = 3, H_LIST_ID = 4, H_X_SEQUENCE = 5 }; FILE *fp; g_return_if_fail(msginfo != NULL); g_return_if_fail(header != NULL); g_return_if_fail(key != NULL); *header = NULL; *key = NULL; switch (type) { case FILTER_BY_NONE: return; case FILTER_BY_AUTO: if ((fp = procmsg_open_message(msginfo)) == NULL) return; procheader_get_header_fields(fp, hentry); fclose(fp); #define SET_FILTER_KEY(hstr, idx) \ { \ *header = g_strdup(hstr); \ *key = hentry[idx].body; \ hentry[idx].body = NULL; \ } if (hentry[H_X_BEENTHERE].body != NULL) { SET_FILTER_KEY("header \"X-BeenThere\"", H_X_BEENTHERE); } else if (hentry[H_X_ML_NAME].body != NULL) { SET_FILTER_KEY("header \"X-ML-Name\"", H_X_ML_NAME); } else if (hentry[H_X_LIST].body != NULL) { SET_FILTER_KEY("header \"X-List\"", H_X_LIST); } else if (hentry[H_X_MAILING_LIST].body != NULL) { SET_FILTER_KEY("header \"X-Mailing-List\"", H_X_MAILING_LIST); } else if (hentry[H_LIST_ID].body != NULL) { SET_FILTER_KEY("header \"List-Id\"", H_LIST_ID); extract_list_id_str(*key); } else if (hentry[H_X_SEQUENCE].body != NULL) { guchar *p; SET_FILTER_KEY("X-Sequence", H_X_SEQUENCE); p = *key; while (*p != '\0') { while (*p != '\0' && !isspace(*p)) p++; while (isspace(*p)) p++; if (isdigit(*p)) { *p = '\0'; break; } } g_strstrip(*key); } else if (msginfo->subject) { *header = g_strdup("subject"); *key = g_strdup(msginfo->subject); } #undef SET_FILTER_KEY g_free(hentry[H_X_BEENTHERE].body); hentry[H_X_BEENTHERE].body = NULL; g_free(hentry[H_X_ML_NAME].body); hentry[H_X_ML_NAME].body = NULL; g_free(hentry[H_X_LIST].body); hentry[H_X_LIST].body = NULL; g_free(hentry[H_X_MAILING_LIST].body); hentry[H_X_MAILING_LIST].body = NULL; g_free(hentry[H_LIST_ID].body); hentry[H_LIST_ID].body = NULL; break; case FILTER_BY_FROM: *header = g_strdup("from"); *key = g_strdup(msginfo->from); break; case FILTER_BY_TO: *header = g_strdup("to"); *key = g_strdup(msginfo->to); break; case FILTER_BY_SUBJECT: *header = g_strdup("subject"); *key = g_strdup(msginfo->subject); break; default: break; } }
static void messageview_show_cb(GObject *obj, gpointer msgview, MsgInfo *msginfo, gboolean all_headers) { MessageView *messageview = NULL; MimeInfo *mimeinfo, *partial; FILE *msg_file, *input = NULL; gchar *html_buf = NULL; size_t n_size; #if defined(USE_WEBKITGTK) WebKitWebSettings *settings = NULL; #elif defined(USE_GTKHTML) #else #error "Not Implemented" #endif SYLPF_START_FUNC; g_return_if_fail(msgview != NULL); messageview = (MessageView*)msgview; g_return_if_fail(messageview != NULL); SYLPF_OPTION.is_show_attach_tab = SYLPF_GET_RC_SHOW_ATTACH_TAB; if (SYLPF_OPTION.is_show_attach_tab == 0) { gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->notebook), 0); SYLPF_RETURN; } if (SYLPF_OPTION.html_view == NULL) { #if defined(USE_WEBKITGTK) SYLPF_OPTION.html_view = (WebKitWebView*)create_htmlview(GTK_NOTEBOOK(messageview->notebook)); #elif defined(USE_GTKHTML) SYLPF_OPTION.html_view = create_htmlview(GTK_NOTEBOOK(messageview->notebook)); #endif } mimeinfo = procmime_scan_message(msginfo); msg_file = procmsg_open_message(msginfo); partial = mimeinfo; while (partial && partial->mime_type != MIME_TEXT_HTML) { partial = procmime_mimeinfo_next(partial); } if (partial && partial->mime_type == MIME_TEXT_HTML) { partial->mime_type = MIME_TEXT; input = procmime_get_text_content(partial, msg_file, NULL); html_buf = calloc(partial->size+1, 1); n_size = fread(html_buf, partial->size, 1, input); #if defined(USE_WEBKITGTK) settings = webkit_web_view_get_settings(SYLPF_OPTION.html_view); g_object_set(G_OBJECT(settings), ENABLE_IMAGES, SYLPF_OPTION.image_flag, NULL); g_object_set(G_OBJECT(settings), ENABLE_SCRIPTS, SYLPF_OPTION.script_flag, NULL); g_object_set(G_OBJECT(settings), ENABLE_PRIVATE_BROWSING, SYLPF_OPTION.private_flag, NULL); g_object_set(G_OBJECT(settings), DEFAULT_FONT_SIZE, SYLPF_OPTION.font_size, NULL); webkit_web_view_set_settings(SYLPF_OPTION.html_view, settings); webkit_web_view_load_string(SYLPF_OPTION.html_view, html_buf, NULL, NULL, ""); #elif defined(USE_GTKHTML) gtk_html_load_from_string(GTK_HTML(SYLPF_OPTION.html_view), html_buf, -1); #endif if (SYLPF_OPTION.switch_tab_flag != FALSE) { gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->notebook), 2); } fclose(input); free(html_buf); } else { gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->notebook), 0); } SYLPF_END_FUNC; }