示例#1
0
文件: mbox.c 项目: wcremeika/thesis
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;
}
示例#2
0
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;
}
示例#3
0
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;
	}
}
示例#4
0
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;
}