Пример #1
0
static void default_mode_radio_button_cb(GtkToggleButton *button, gpointer data)
{
	guint mode;
	gboolean is_url;

	if (gtk_toggle_button_get_active(button) != TRUE)
		return;

	mode = *((guint *)data);
	is_url = (mode == DEF_MODE_URL)? TRUE: FALSE;

	gtk_widget_set_sensitive(libravatarprefs_page.defm_url_text, is_url);
	if (is_url) /* custom URL requires following redirects */
		gtk_toggle_button_set_active(
			GTK_TOGGLE_BUTTON(libravatarprefs_page.allow_redirects_check),
			TRUE);

	if (mode == DEF_MODE_NONE) {
		prefs_common_get_prefs()->enable_avatars = AVATARS_ENABLE_BOTH;
	} else {
		/* don't waste time with headers that won't be displayed */
		prefs_common_get_prefs()->enable_avatars = AVATARS_DISABLE;
		/* empty missing cache when switching to generated */
		g_hash_table_remove_all(libravatarmisses);
	}
}
Пример #2
0
static guchar *_make_key_deriv(const gchar *passphrase, guint rounds,
		guint length)
{
	guchar *kd, *salt;
	gchar *saltpref = prefs_common_get_prefs()->master_passphrase_salt;
	gsize saltlen;
	gint ret;

	/* Grab our salt, generating and saving a new random one if needed. */
	if (saltpref == NULL || strlen(saltpref) == 0) {
		_generate_salt();
		saltpref = prefs_common_get_prefs()->master_passphrase_salt;
	}
	salt = g_base64_decode(saltpref, &saltlen);
	kd = g_malloc0(length);

	START_TIMING("PBKDF2");
	ret = pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltlen,
			kd, length, rounds);
	END_TIMING();

	g_free(salt);

	if (ret == 0) {
		return kd;
	}

	g_free(kd);
	return NULL;
}
Пример #3
0
const gboolean master_passphrase_is_set()
{
	if (prefs_common_get_prefs()->master_passphrase == NULL
			|| strlen(prefs_common_get_prefs()->master_passphrase) == 0)
		return FALSE;

	return TRUE;
}
Пример #4
0
static AttachWarnerMention *aw_matcherlist_string_match(MatcherList *matchers, gchar *str, gchar *sig_separator)
{
	MsgInfo info;
	int i = 0;
	gboolean ret = FALSE;
	gchar **lines = NULL;
	AttachWarnerMention *awm = NULL; 

	if (str == NULL || *str == '\0') {
		return awm;
	}
	
	lines = g_strsplit(str, "\n", -1);
	if (attwarnerprefs.skip_quotes
		&& *prefs_common_get_prefs()->quote_chars != '\0') {
		debug_print("checking without quotes\n");
		for (i = 0; lines[i] != NULL && ret == FALSE; i++) {
			if(attwarnerprefs.skip_signature
				&& sig_separator != NULL
				&& *sig_separator != '\0'
				&& strcmp(lines[i], sig_separator) == 0) {
				debug_print("reached signature delimiter at line %d\n", i);
				break;
			}
			if (line_has_quote_char(lines[i], 
				prefs_common_get_prefs()->quote_chars) == NULL) {
				debug_print("testing line %d\n", i);
				info.subject = lines[i];
				ret = matcherlist_match(matchers, &info);
				debug_print("line %d: %d\n", i, ret);
			}
		}
	} else {
		debug_print("checking with quotes\n");
		for (i = 0; lines[i] != NULL && ret == FALSE; i++) {
			if(attwarnerprefs.skip_signature
				&& sig_separator != NULL
				&& *sig_separator != '\0'
				&& strcmp(lines[i], sig_separator) == 0) {
				debug_print("reached signature delimiter at line %d\n", i);
				break;
			}
			debug_print("testing line %d\n", i);
			info.subject = lines[i];
			ret = matcherlist_match(matchers, &info);
			debug_print("line %d: %d\n", i, ret);
		}
	}
	if (ret != FALSE) {
                awm = g_new0(AttachWarnerMention, 1);
		awm->line = i; /* usual humans count lines from 1 */
		awm->context = g_strdup(lines[i - 1]);
		debug_print("found at line %d, context \"%s\"\n", awm->line, awm->context);
	}
	g_strfreev(lines);

	return awm;
}
Пример #5
0
void master_passphrase_change(const gchar *oldp, const gchar *newp)
{
	guchar *kd;
	gchar *base64_kd;
	guint rounds = prefs_common_get_prefs()->master_passphrase_pbkdf2_rounds;

	g_return_if_fail(rounds > 0);

	if (oldp == NULL) {
		/* If oldp is NULL, make sure the user has to enter the
		 * current master passphrase before being able to change it. */
		master_passphrase_forget();
		oldp = master_passphrase();
	}
	g_return_if_fail(oldp != NULL);

	/* Update master passphrase hash in prefs */
	if (prefs_common_get_prefs()->master_passphrase != NULL)
		g_free(prefs_common_get_prefs()->master_passphrase);

	if (newp != NULL) {
		debug_print("Storing key derivation of new master passphrase\n");
		kd = _make_key_deriv(newp, rounds, KD_LENGTH);
		base64_kd = g_base64_encode(kd, 64);
		prefs_common_get_prefs()->master_passphrase =
			g_strdup_printf("{PBKDF2-HMAC-SHA1,%d}%s", rounds, base64_kd);
		g_free(kd);
		g_free(base64_kd);
	} else {
		debug_print("Setting master_passphrase to NULL\n");
		prefs_common_get_prefs()->master_passphrase = NULL;
	}

	/* Now go over all accounts, reencrypting their passwords using
	 * the new master passphrase. */

	if (oldp == NULL)
		oldp = PASSCRYPT_KEY;
	if (newp == NULL)
		newp = PASSCRYPT_KEY;

	debug_print("Reencrypting all account passwords...\n");
	passwd_store_reencrypt_all(oldp, newp);

	/* Now reencrypt all plugins passwords fields 
	 * FIXME: Unloaded plugins won't be able to update their stored passwords
	 */
	plugins_master_passphrase_change(oldp, newp);

	master_passphrase_forget();
}
Пример #6
0
static const gchar *master_passphrase()
{
	gchar *input;
	gboolean end = FALSE;

	if (!prefs_common_get_prefs()->use_master_passphrase) {
		return PASSCRYPT_KEY;
	}

	if (_master_passphrase != NULL) {
		debug_print("Master passphrase is in memory, offering it.\n");
		return _master_passphrase;
	}

	while (!end) {
		input = input_dialog_with_invisible(_("Input master passphrase"),
				_("Input master passphrase"), NULL);

		if (input == NULL) {
			debug_print("Cancel pressed at master passphrase dialog.\n");
			break;
		}

		if (master_passphrase_is_correct(input)) {
			debug_print("Entered master passphrase seems to be correct, remembering it.\n");
			_master_passphrase = input;
			end = TRUE;
		} else {
			alertpanel_error(_("Incorrect master passphrase."));
		}
	}

	return _master_passphrase;
}
Пример #7
0
static void notification_trayicon_on_popup_menu(GtkStatusIcon *status_icon,
						guint button, guint activate_time,
						gpointer user_data)
{
  MainWindow *mainwin = mainwindow_get_mainwindow();

  if(!mainwin)
    return;

  /* tell callbacks to skip any event */
  updating_menu = TRUE;
  /* initialize checkitems according to current states */
	cm_toggle_menu_set_active("SysTrayiconPopup/ToggleOffline", prefs_common_get_prefs()->work_offline);
#ifdef HAVE_LIBNOTIFY
	cm_toggle_menu_set_active("SysTrayiconPopup/ShowBubbles", notify_config.trayicon_popup_enabled);
#endif
	cm_menu_set_sensitive("SysTrayiconPopup/GetMail", mainwin->lock_count == 0);

  updating_menu = FALSE;

#ifndef G_OS_WIN32
  gtk_menu_popup(GTK_MENU(traymenu_popup), NULL, NULL, NULL, NULL,
		 button, activate_time);
#else
  /* http://bugzilla.gnome.org/show_bug.cgi?id=552642 */
  gtk_menu_popup(GTK_MENU(traymenu_popup), NULL, NULL, NULL, NULL,
		 0, activate_time);
#endif
}
Пример #8
0
static void _generate_salt()
{
	guchar salt[KD_SALT_LENGTH];

	if (prefs_common_get_prefs()->master_passphrase_salt != NULL) {
		g_free(prefs_common_get_prefs()->master_passphrase_salt);
	}

	if (!get_random_bytes(salt, KD_SALT_LENGTH)) {
		debug_print("Could not get random bytes for kd salt.\n");
		return;
	}

	prefs_common_get_prefs()->master_passphrase_salt =
		g_base64_encode(salt, KD_SALT_LENGTH);
}
Пример #9
0
static GtkWidget *p_create_frame_network(struct LibravatarPrefsPage *page)
{
	GtkWidget *vbox, *chk_redirects, *spinner, *hbox;
	GtkAdjustment *adj;
#if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
	GtkWidget *chk_federated;
#endif

	vbox =  gtk_vbox_new(FALSE, 6);

	chk_redirects = create_checkbox(_("_Allow redirects to other sites"),
				   _("Follow redirect responses received from "
				     "libravatar server to other avatar "
				     "services like gravatar.com"));
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_redirects),
				     libravatarprefs.allow_redirects);
	page->allow_redirects_check = chk_redirects;
	gtk_box_pack_start(GTK_BOX(vbox), chk_redirects, FALSE, FALSE, 0);

#if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
	chk_federated = create_checkbox(_("_Enable federated servers"),
				_("Try to get avatar from sender's domain "
				  "libravatar server"));
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_federated),
				     libravatarprefs.allow_federated);
	page->allow_federated_check = chk_federated;
	gtk_box_pack_start(GTK_BOX(vbox), chk_federated, FALSE, FALSE, 0);
#endif

	adj = (GtkAdjustment *) gtk_adjustment_new(
					libravatarprefs.timeout,
					TIMEOUT_MIN_S,
					(prefs_common_get_prefs()->io_timeout_secs > 0)
					? (prefs_common_get_prefs()->io_timeout_secs - 1)
					: 0,
					1.0, 0.0, 0.0);
	spinner = gtk_spin_button_new(adj, 1.0, 0);
	gtk_widget_show(spinner);
	hbox = labeled_spinner_box(_("Request timeout"), spinner, _("seconds"),
		_("Set to 0 to use global socket I/O timeout. "
                  "Maximum value must be also less than global socket "
                  "I/O timeout."));
	page->timeout = spinner;
	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

	return vbox;
}
Пример #10
0
static void trayicon_toggle_offline_cb(GtkAction *action, gpointer data)
{
  /* toggle offline mode if menu checkitem has been clicked */
  if(!updating_menu) {
    MainWindow *mainwin = mainwindow_get_mainwindow();
    main_window_toggle_work_offline(mainwin, !prefs_common_get_prefs()->work_offline, TRUE);
  }
}
Пример #11
0
static void app_exit_cb(MainWindow *mainwin, guint action, GtkWidget *widget)
{
  if(prefs_common_get_prefs()->confirm_on_exit) {
    if(alertpanel(_("Exit"), _("Exit Claws Mail?"),
		  GTK_STOCK_CANCEL, GTK_STOCK_OK,
		  NULL) != G_ALERTALTERNATE) {
      return;
    }
    manage_window_focus_in(mainwin->window, NULL, NULL);
  }

  if (prefs_common_get_prefs()->clean_on_exit) {
    if (!main_window_empty_trash(mainwin, prefs_common_get_prefs()->ask_on_clean, TRUE))
      return;
  }

  app_will_exit(NULL, mainwin);
}
Пример #12
0
const gboolean master_passphrase_is_correct(const gchar *input)
{
	guchar *kd, *input_kd;
	gchar **tokens;
	gchar *stored_kd = prefs_common_get_prefs()->master_passphrase;
	gsize kd_len;
	guint rounds = 0;
	gint ret;

	g_return_val_if_fail(stored_kd != NULL && strlen(stored_kd) > 0, FALSE);
	g_return_val_if_fail(input != NULL, FALSE);

	if (stored_kd == NULL)
		return FALSE;

	tokens = g_strsplit_set(stored_kd, "{}", 3);
	if (tokens[0] == NULL ||
			strlen(tokens[0]) != 0 || /* nothing before { */
			tokens[1] == NULL ||
			strncmp(tokens[1], "PBKDF2-HMAC-SHA1,", 17) || /* correct tag */
			strlen(tokens[1]) <= 17 || /* something after , */
			(rounds = atoi(tokens[1] + 17)) <= 0 || /* valid rounds # */
			tokens[2] == NULL ||
			strlen(tokens[2]) == 0) { /* string continues after } */
		debug_print("Mangled master_passphrase format in config, can not use it.\n");
		g_strfreev(tokens);
		return FALSE;
	}

	stored_kd = tokens[2];
	kd = g_base64_decode(stored_kd, &kd_len); /* should be 64 */
	g_strfreev(tokens);

	if (kd_len != KD_LENGTH) {
		debug_print("master_passphrase is %ld bytes long, should be %d.\n",
				kd_len, KD_LENGTH);
		g_free(kd);
		return FALSE;
	}

	input_kd = _make_key_deriv(input, rounds, KD_LENGTH);
	ret = memcmp(kd, input_kd, kd_len);

	g_free(input_kd);
	g_free(kd);

	if (ret == 0)
		return TRUE;

	return FALSE;
}
Пример #13
0
static gboolean libravatar_image_render_hook(gpointer source, gpointer data)
{
	AvatarRender *ar = (AvatarRender *)source;
	GtkWidget *image = NULL;
	gchar *a = NULL, *url = NULL;
	gchar md5sum[33];

	debug_print("libravatar avatar_image_render invoked\n");

	a = procmsg_msginfo_get_avatar(ar->full_msginfo, AVATAR_LIBRAVATAR);
	if (a != NULL) {
		gchar *base;

		md5_hex_digest(md5sum, a);
		/* try missing cache */
		if (is_missing_md5(libravatarmisses, md5sum)) {
			return FALSE;
		}
		/* try disk cache */
		image = image_widget_from_cached_md5(md5sum);
		if (image != NULL) {
			if (ar->image) /* previous plugin set one */
				gtk_widget_destroy(ar->image);
			ar->image = image;
			ar->type  = AVATAR_LIBRAVATAR;
			return FALSE;
		}
		/* not cached copy: try network */
		if (prefs_common_get_prefs()->work_offline) {
			debug_print("working off-line: libravatar network retrieval skipped\n");
			return FALSE;
		}
		base = federated_base_url_from_address(a);
		url = libravatar_url_for_md5(base, md5sum);
		if (url != NULL) {
			image = image_widget_from_url(url, md5sum);
			g_free(url);
			if (image != NULL) {
				if (ar->image) /* previous plugin set one */
					gtk_widget_destroy(ar->image);
				ar->image = image;
				ar->type  = AVATAR_LIBRAVATAR;
			}
		}
		g_free(base);

		return TRUE;
	}

	return FALSE; /* keep rendering */
}
Пример #14
0
gchar *password_encrypt_gnutls(const gchar *password,
		const gchar *encryption_passphrase)
{
	/* Another, slightly inferior combination is AES-128-CBC + SHA-256.
	 * Any block cipher in CBC mode with keysize N and a hash algo with
	 * digest length 2*N would do. */
	gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_256_CBC;
	gnutls_cipher_hd_t handle;
	gnutls_datum_t key, iv;
	int keylen, blocklen, ret;
	unsigned char *buf, *encbuf, *base, *output;
	guint rounds = prefs_common_get_prefs()->master_passphrase_pbkdf2_rounds;

	g_return_val_if_fail(password != NULL, NULL);
	g_return_val_if_fail(encryption_passphrase != NULL, NULL);

/*	ivlen = gnutls_cipher_get_iv_size(algo);*/
	keylen = gnutls_cipher_get_key_size(algo);
	blocklen = gnutls_cipher_get_block_size(algo);
/*	digestlen = gnutls_hash_get_len(digest); */

	/* Take the passphrase and compute a key derivation of suitable
	 * length to be used as encryption key for our block cipher. */
	key.data = _make_key_deriv(encryption_passphrase, rounds, keylen);
	key.size = keylen;

	/* Prepare random IV for cipher */
	iv.data = malloc(IVLEN);
	iv.size = IVLEN;
	if (!get_random_bytes(iv.data, IVLEN)) {
		g_free(key.data);
		g_free(iv.data);
		return NULL;
	}

	/* Initialize the encryption */
	ret = gnutls_cipher_init(&handle, algo, &key, &iv);
	if (ret < 0) {
		g_free(key.data);
		g_free(iv.data);
		return NULL;
	}

	/* Fill buf with one block of random data, our password, pad the
	 * rest with zero bytes. */
	buf = malloc(BUFSIZE + blocklen);
	memset(buf, 0, BUFSIZE);
	if (!get_random_bytes(buf, blocklen)) {
		g_free(buf);
		g_free(key.data);
		g_free(iv.data);
		gnutls_cipher_deinit(handle);
		return NULL;
	}

	memcpy(buf + blocklen, password, strlen(password));

	/* Encrypt into encbuf */
	encbuf = malloc(BUFSIZE + blocklen);
	memset(encbuf, 0, BUFSIZE + blocklen);
	ret = gnutls_cipher_encrypt2(handle, buf, BUFSIZE + blocklen,
			encbuf, BUFSIZE + blocklen);
	if (ret < 0) {
		g_free(key.data);
		g_free(iv.data);
		g_free(buf);
		g_free(encbuf);
		gnutls_cipher_deinit(handle);
		return NULL;
	}

	/* Cleanup */
	gnutls_cipher_deinit(handle);
	g_free(key.data);
	g_free(iv.data);
	g_free(buf);

	/* And finally prepare the resulting string:
	 * "{algorithm,rounds}base64encodedciphertext" */
	base = g_base64_encode(encbuf, BUFSIZE);
	g_free(encbuf);
	output = g_strdup_printf("{%s,%d}%s",
			gnutls_cipher_get_name(algo), rounds, base);
	g_free(base);

	return output;
}
Пример #15
0
static gboolean mail_filtering_hook(gpointer source, gpointer data)
{
	MailFilteringData *mail_filtering_data = (MailFilteringData *) source;
	MsgInfo *msginfo = mail_filtering_data->msginfo;
	GSList *msglist = mail_filtering_data->msglist;
	GSList *cur = NULL;
	static gboolean warned_error = FALSE;
	int status = 0;
	int total = 0, curnum = 0;
	GSList *new_hams = NULL, *new_spams = NULL;
	GSList *new_unsure, *whitelisted_new_spams = NULL;
	gchar *bogo_exec = (config.bogopath && *config.bogopath) ? config.bogopath:"bogofilter";
	gchar *bogo_args[4];
	gboolean ok_to_thread = TRUE;

	bogo_args[0] = bogo_exec;
	bogo_args[1] = "-T";
	bogo_args[2] = "-b";
	bogo_args[3] = NULL;
	
	if (!config.process_emails) {
		return FALSE;
	}
	
	if (msglist == NULL && msginfo != NULL) {
		g_warning("wrong call to bogofilter mail_filtering_hook");
		return FALSE;
	}
	
	total = g_slist_length(msglist);
	
	/* we have to make sure the mails are cached - or it'll break on IMAP */
	if (message_callback != NULL)
		message_callback(_("Bogofilter: fetching bodies..."), total, 0, FALSE);
	for (cur = msglist; cur; cur = cur->next) {
		gchar *file = procmsg_get_message_file((MsgInfo *)cur->data);
		if (file == NULL)
			ok_to_thread = FALSE;
		if (message_callback != NULL)
			message_callback(NULL, total, curnum++, FALSE);
		g_free(file);
	}
	if (message_callback != NULL)
		message_callback(NULL, 0, 0, FALSE);

	if (message_callback != NULL)
		message_callback(_("Bogofilter: filtering messages..."), total, 0, FALSE);

#ifdef USE_PTHREAD
	while (pthread_mutex_trylock(&list_mutex) != 0) {
		GTK_EVENTS_FLUSH();
		usleep(100);
	}
#endif
	to_filter_data = g_new0(BogoFilterData, 1);
	to_filter_data->msglist = msglist;
	to_filter_data->mail_filtering_data = mail_filtering_data;
	to_filter_data->new_hams = NULL;
	to_filter_data->new_unsure = NULL;
	to_filter_data->new_spams = NULL;
	to_filter_data->whitelisted_new_spams = NULL;
	to_filter_data->done = FALSE;
	to_filter_data->status = -1;
	to_filter_data->bogo_args = bogo_args;
#ifdef USE_PTHREAD
	to_filter_data->in_thread = (filter_th != 0 && ok_to_thread);
#else
	to_filter_data->in_thread = FALSE;
#endif

#ifdef USE_PTHREAD
	pthread_mutex_unlock(&list_mutex);
	
	if (filter_th != 0 && ok_to_thread) {
		debug_print("waking thread to let it filter things\n");
		pthread_mutex_lock(&wait_mutex);
		pthread_cond_broadcast(&wait_cond);
		pthread_mutex_unlock(&wait_mutex);

		while (!to_filter_data->done) {
			GTK_EVENTS_FLUSH();
			usleep(100);
		}
	}

	while (pthread_mutex_trylock(&list_mutex) != 0) {
		GTK_EVENTS_FLUSH();
		usleep(100);

	}
	if (filter_th == 0 || !ok_to_thread)
		bogofilter_do_filter(to_filter_data);
#else
	bogofilter_do_filter(to_filter_data);	
#endif

	new_hams = to_filter_data->new_hams;
	new_unsure = to_filter_data->new_unsure;
	new_spams = to_filter_data->new_spams;
	whitelisted_new_spams = to_filter_data->whitelisted_new_spams;
	status = to_filter_data->status;
	g_free(to_filter_data);
	to_filter_data = NULL;
#ifdef USE_PTHREAD
	pthread_mutex_unlock(&list_mutex);
#endif


	/* unflag hams */
	for (cur = new_hams; cur; cur = cur->next) {
		MsgInfo *msginfo = (MsgInfo *)cur->data;
		procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
		debug_print("unflagging ham: %d\n", msginfo->msgnum);
	}
	/* unflag unsure */
	for (cur = new_unsure; cur; cur = cur->next) {
		MsgInfo *msginfo = (MsgInfo *)cur->data;
		procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
		debug_print("unflagging unsure: %d\n", msginfo->msgnum);
	}
	if (config.learn_from_whitelist && whitelisted_new_spams) {
		/* flag whitelisted spams */
		for (cur = whitelisted_new_spams; cur; cur = cur->next) {
			MsgInfo *msginfo = (MsgInfo *)cur->data;
			procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0);
			debug_print("flagging whitelisted non-ham: %d\n", msginfo->msgnum);
		}
		/* correct bogo */
		bogofilter_learn(NULL, whitelisted_new_spams, FALSE);

		/* unflag them */
		for (cur = whitelisted_new_spams; cur; cur = cur->next) {
			MsgInfo *msginfo = (MsgInfo *)cur->data;
			procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
			debug_print("unflagging whitelisted non-ham: %d\n", msginfo->msgnum);
		}
	} else {
		for (cur = whitelisted_new_spams; cur; cur = cur->next) {
			MsgInfo *msginfo = (MsgInfo *)cur->data;
			procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
			debug_print("not flagging whitelisted non-ham: %d\n", msginfo->msgnum);
		}
	}

	/* flag spams and delete them if config.receive_spam == 0
	 * (if config.receive_spam is set to 1, we'll move them later,
	 * mark as spam only if set to 2) */
	for (cur = new_spams; cur; cur = cur->next) {
		MsgInfo *msginfo = (MsgInfo *)cur->data;
		if (config.receive_spam != SPAM_DELETE) {
			if (config.mark_as_read)
				procmsg_msginfo_unset_flags(msginfo, ~0, 0);
			procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0);
		} else {
			folder_item_remove_msg(msginfo->folder, msginfo->msgnum);
		}
	}
	
	if (status < 0 || status > 2) { /* I/O or other errors */
		gchar *msg = NULL;
		
		if (status == 3)
			msg =  g_strdup_printf(_("The Bogofilter plugin couldn't filter "
					   "a message. The probable cause of the "
					   "error is that it didn't learn from any mail.\n"
					   "Use \"/Mark/Mark as spam\" and \"/Mark/Mark as "
					   "ham\" to train Bogofilter with a few hundred "
					   "spam and ham messages."));
		else
			msg =  g_strdup_printf(_("The Bogofilter plugin couldn't filter "
					   "a message. The command `%s %s %s` couldn't be run."), 
					   bogo_args[0], bogo_args[1], bogo_args[2]);
		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);
		}
		g_free(msg);
	}
	if (status < 0 || status > 2) {
		g_slist_free(mail_filtering_data->filtered);
		g_slist_free(mail_filtering_data->unfiltered);
		mail_filtering_data->filtered = NULL;
		mail_filtering_data->unfiltered = NULL;
	} else {
		if (config.receive_spam == SPAM_MARK_AND_SAVE && new_spams) {
			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 (save_folder) {
				for (cur = new_spams; cur; cur = cur->next) {
					msginfo = (MsgInfo *)cur->data;
					msginfo->filter_op = IS_MOVE;
					msginfo->to_filter_folder = save_folder;
				}
			}
		}
		if (config.save_unsure && new_unsure) {
			FolderItem *save_unsure_folder = NULL;

			if ((!config.save_unsure_folder) ||
			    (config.save_unsure_folder[0] == '\0') ||
			    ((save_unsure_folder = folder_find_item_from_identifier(config.save_unsure_folder)) == NULL)) {
			 	if (mail_filtering_data->account)
					save_unsure_folder = folder_find_item_from_identifier(
						mail_filtering_data->account->inbox);
				if (save_unsure_folder == NULL && mail_filtering_data->account &&
				    mail_filtering_data->account->folder)
				    	save_unsure_folder = mail_filtering_data->account->folder->inbox;
				if (save_unsure_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) {
							save_unsure_folder = item;
						}
					} 
					if (!save_unsure_folder && mail_filtering_data->account->local_inbox) {
						FolderItem *item = folder_find_item_from_identifier(
							mail_filtering_data->account->local_inbox);
						if (item) {
							save_unsure_folder = item;
						}
					}
				}
				if (save_unsure_folder == NULL)
					save_unsure_folder = folder_get_default_inbox();
			}
			if (save_unsure_folder) {
				for (cur = new_unsure; cur; cur = cur->next) {
					msginfo = (MsgInfo *)cur->data;
					msginfo->filter_op = IS_MOVE;
					msginfo->to_filter_folder = save_unsure_folder;
				}
			}
		}
	} 
	g_slist_free(new_hams);
	g_slist_free(new_unsure);
	g_slist_free(new_spams);
	g_slist_free(whitelisted_new_spams);

	if (message_callback != NULL)
		message_callback(NULL, 0, 0, FALSE);
	mail_filtering_data->filtered   = g_slist_reverse(
		mail_filtering_data->filtered);
	mail_filtering_data->unfiltered = g_slist_reverse(
		mail_filtering_data->unfiltered);
	
	return FALSE;
}
Пример #16
0
static GtkWidget *image_widget_from_url(const gchar *url, const gchar *md5)
{
	GtkWidget *image = NULL;
	gchar *filename;
	FILE *file;
	CURL *curl;

	curl = curl_easy_init();
	if (curl == NULL) {
		g_warning("could not initialize curl to get image from URL");
		return NULL;
	}
	curl_easy_setopt(curl, CURLOPT_URL, url);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_image_data_cb);
	/* make sure timeout is less than general IO timeout */
	curl_easy_setopt(curl, CURLOPT_TIMEOUT,
			(libravatarprefs.timeout == 0
				|| libravatarprefs.timeout
					> prefs_common_get_prefs()->io_timeout_secs)
			? prefs_common_get_prefs()->io_timeout_secs
			: libravatarprefs.timeout);
	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

	filename = cache_name_for_md5(md5);
	file = fopen(filename, "wb");
	if (file != NULL) {
		long filesize;

		if (libravatarprefs.allow_redirects) {
			long maxredirs = (libravatarprefs.default_mode == DEF_MODE_URL)? 3L
				: ((libravatarprefs.default_mode == DEF_MODE_MM)? 2L: 1L);

			curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
			curl_easy_setopt(curl, CURLOPT_MAXREDIRS, maxredirs);
		}
		curl_easy_setopt(curl, CURLOPT_FILE, file);
		debug_print("retrieving URL to file: %s -> %s\n", url, filename);
		curl_easy_perform(curl);
		filesize = ftell(file);
    		fclose(file);

		if (filesize < MIN_PNG_SIZE)
			debug_print("not enough data for an avatar image: %ld bytes\n", filesize);
		else
			image = image_widget_from_filename(filename);

		if (!libravatarprefs.cache_icons || filesize == 0) {
			if (g_unlink(filename) < 0)
				g_warning("failed to delete cache file '%s'", filename);
		}

		if (filesize == 0)
			missing_add_md5(libravatarmisses, md5);
	} else {
		g_warning("could not open '%s' for writing", filename);
	}
	curl_easy_cleanup(curl);
	g_free(filename);

	return image;
}
Пример #17
0
gchar *sgpgme_sigstat_info_full(gpgme_ctx_t ctx, gpgme_verify_result_t status)
{
	gint i = 0;
	gchar *ret;
	GString *siginfo;
	gpgme_signature_t sig = NULL;

	siginfo = g_string_sized_new(64);
	if (status == NULL) {
		g_string_append_printf(siginfo,
			_("Error checking signature: no status\n"));
		goto bail;
	 }

	sig = status->signatures;
	
	while (sig) {
		char buf[100];
		struct tm lt;
		gpgme_user_id_t user = NULL;
		gpgme_key_t key;
		gpgme_error_t err;
		const gchar *keytype, *keyid, *uid;
		
		err = gpgme_get_key(ctx, sig->fpr, &key, 0);

		if (err != GPG_ERR_NO_ERROR) {
			key = NULL;
			g_string_append_printf(siginfo, 
				_("Error checking signature: %s\n"),
				gpgme_strerror(err));
			goto bail;
		}
		if (key) {
			user = key->uids;
			keytype = gpgme_pubkey_algo_name(
					key->subkeys->pubkey_algo);
			keyid = key->subkeys->keyid;
			uid = user->uid;
		} else {
			keytype = "?";
			keyid = "?";
			uid = "?";
		}

		memset(buf, 0, sizeof(buf));
		fast_strftime(buf, sizeof(buf)-1, prefs_common_get_prefs()->date_format, localtime_r(&sig->timestamp, &lt));
		g_string_append_printf(siginfo,
			_("Signature made on %s using %s key ID %s\n"),
			buf, keytype, keyid);
		
		switch (gpg_err_code(sig->status)) {
		case GPG_ERR_NO_ERROR:
			g_string_append_printf(siginfo,
				_("Good signature from uid \"%s\" (Validity: %s)\n"),
				uid, get_validity_str(user?user->validity:GPGME_VALIDITY_UNKNOWN));
			break;
		case GPG_ERR_KEY_EXPIRED:
			g_string_append_printf(siginfo,
				_("Expired key uid \"%s\"\n"),
				uid);
			break;
		case GPG_ERR_SIG_EXPIRED:
			g_string_append_printf(siginfo,
				_("Expired signature from uid \"%s\" (Validity: %s)\n"),
				uid, get_validity_str(user?user->validity:GPGME_VALIDITY_UNKNOWN));
			break;
		case GPG_ERR_CERT_REVOKED:
			g_string_append_printf(siginfo,
				_("Revoked key uid \"%s\"\n"),
				uid);
			break;
		case GPG_ERR_BAD_SIGNATURE:
			g_string_append_printf(siginfo,
				_("BAD signature from \"%s\"\n"),
				uid);
			break;
		default:
			break;
		}
		if (sig->status != GPG_ERR_BAD_SIGNATURE) {
			gint j = 1;
			user = user ? user->next : NULL;
			while (user != NULL) {
				g_string_append_printf(siginfo,
					_("                    uid \"%s\" (Validity: %s)\n"),
					user->uid,
					user->revoked==TRUE?_("Revoked"):get_validity_str(user->validity));
				j++;
				user = user->next;
			}
			g_string_append_printf(siginfo,_("Owner Trust: %s\n"),
					       get_owner_trust_str(key->owner_trust));
			g_string_append(siginfo,
				_("Primary key fingerprint:"));
			const char* primary_fpr = NULL;
			if (key && key->subkeys && key->subkeys->fpr)
				primary_fpr = key->subkeys->fpr;
			else
				g_string_append(siginfo, " ?");
			int idx; /* now pretty-print the fingerprint */
			for (idx=0; primary_fpr && *primary_fpr!='\0'; idx++, primary_fpr++) {
				if (idx%4==0)
					g_string_append_c(siginfo, ' ');
				if (idx%20==0)
					g_string_append_c(siginfo, ' ');
				g_string_append_c(siginfo, (gchar)*primary_fpr);
			}
			g_string_append_c(siginfo, '\n');
#ifdef HAVE_GPGME_PKA_TRUST
                        if (sig->pka_trust == 1 && sig->pka_address) {
                                g_string_append_printf(siginfo,
                                   _("WARNING: Signer's address \"%s\" "
                                      "does not match DNS entry\n"), 
                                   sig->pka_address);
                        }
                        else if (sig->pka_trust == 2 && sig->pka_address) {
                                g_string_append_printf(siginfo,
                                   _("Verified signer's address is \"%s\"\n"),
                                   sig->pka_address);
                                /* FIXME: Compare the address to the
                                 * From: address.  */
                        }
#endif /*HAVE_GPGME_PKA_TRUST*/
		}

		g_string_append(siginfo, "\n");
		i++;
		sig = sig->next;
	}
bail:
	ret = siginfo->str;
	g_string_free(siginfo, FALSE);
	return ret;
}
Пример #18
0
static GtkWidget *p_create_frame_missing(struct LibravatarPrefsPage *page)
{
	GtkWidget *vbox, *radio[NUM_DEF_BUTTONS], *hbox, *entry;
	gboolean enable = FALSE;
	int i, e = 0;
	gchar *radio_label[] = {
		_("None"),
		_("Mystery man"),
		_("Identicon"),
		_("MonsterID"),
		_("Wavatar"),
		_("Retro"),
		_("Custom URL")
	};
	gchar *radio_hint[] = {
		_("A blank image"),
		_("The unobtrusive low-contrast greyish silhouette"),
		_("A generated geometric pattern"),
		_("A generated full-body monster"),
		_("A generated almost unique face"),
		_("A generated 8-bit arcade-style pixelated image"),
		_("Redirect to a user provided URL")
	};

	vbox =  gtk_vbox_new(FALSE, 6);

	for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
		enable = (libravatarprefs.default_mode == radio_value[i])? TRUE: FALSE;
		e += enable? 1: 0;
		radio[i] = gtk_radio_button_new_with_label_from_widget(
				(i > 0)? GTK_RADIO_BUTTON(radio[i - 1]): NULL, radio_label[i]);
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[i]), enable);
		if (i == CUSTOM_URL_BUTTON_INDEX) {
			/* set related entry next to radio button */
			entry = gtk_entry_new_with_max_length(MAX_URL_LENGTH);
			CLAWS_SET_TIP(entry, _("Enter the URL you want to be "
				"redirected when no user icon is available. "
				"Leave an empty URL to use the default "
				"libravatar orange icon."));
			gtk_widget_show(entry);
			gtk_entry_set_text(GTK_ENTRY(entry),
				libravatarprefs.default_mode_url);
			hbox = gtk_hbox_new(FALSE, 6);
			gtk_box_pack_start(GTK_BOX(hbox), radio[i], FALSE, FALSE, 0);
			gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
			gtk_widget_set_sensitive(entry,
				(libravatarprefs.default_mode == DEF_MODE_URL)
				? TRUE: FALSE);
			page->defm_url_text = entry;
			gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
		} else {
			gtk_box_pack_start(GTK_BOX(vbox), radio[i], FALSE, FALSE, 0);
		}
		g_signal_connect(radio[i], "toggled",
				 G_CALLBACK(default_mode_radio_button_cb),
				 (gpointer) &(radio_value[i]));
		CLAWS_SET_TIP(radio[i], radio_hint[i]);
		gtk_widget_show(radio[i]);
		page->defm_radio[i] = radio[i];
	}
	if (e == 0) { /* unknown value, go default */
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE);
		libravatarprefs.default_mode = DEF_MODE_NONE;
	}
	/* don't waste time with headers that won't be displayed */
	prefs_common_get_prefs()->enable_avatars =
		(libravatarprefs.default_mode == DEF_MODE_NONE)
		? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;



	return vbox;
}
Пример #19
0
static void pgpview_show_mime_part(TextView *textview, MimeInfo *partinfo)
{
	GtkTextView *text;
	GtkTextBuffer *buffer;
	GtkTextIter iter;
	gpgme_data_t sigdata = NULL;
	gpgme_verify_result_t sigstatus = NULL;
	gpgme_ctx_t ctx = NULL;
	gpgme_key_t key = NULL;
	gpgme_signature_t sig = NULL;
	gpgme_error_t err = 0;
	gboolean imported = FALSE;

	if (!partinfo) return;
	
	textview_set_font(textview, NULL);
	textview_clear(textview);

	text = GTK_TEXT_VIEW(textview->text);
	buffer = gtk_text_view_get_buffer(text);
	gtk_text_buffer_get_start_iter(buffer, &iter);

	err = gpgme_new (&ctx);
	if (err) {
		debug_print("err : %s\n", gpgme_strerror(err));
		textview_show_mime_part(textview, partinfo);
		return;
	}
	
	sigdata = sgpgme_data_from_mimeinfo(partinfo);
	if (!sigdata) {
		g_warning("no sigdata");
		textview_show_mime_part(textview, partinfo);
		return;
	}

	/* Here we do not care about what data we attempt to verify with the
	 * signature, or about result of the verification - all we care about
	 * is that we find out ID of the key used to make this signature. */
	sigstatus = sgpgme_verify_signature(ctx, sigdata, NULL, sigdata);
	if (!sigstatus || sigstatus == GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR)) {
		g_warning("no sigstatus");
		textview_show_mime_part(textview, partinfo);
		return;
	}
	sig = sigstatus->signatures;
	if (!sig) {
		g_warning("no sig");
		textview_show_mime_part(textview, partinfo);
		return;
	}
	gpgme_get_key(ctx, sig->fpr, &key, 0);
	if (!key) {
		gchar *gpgbin = get_gpg_executable_name();
		gchar *cmd = g_strdup_printf("\"%s\" --batch --no-tty --recv-keys %s",
				(gpgbin ? gpgbin : "gpg"), sig->fpr);
		AlertValue val = G_ALERTDEFAULT;
		if (!prefs_common_get_prefs()->work_offline) {
			val = alertpanel(_("Key import"),
				_("This key is not in your keyring. Do you want "
				  "Claws Mail to try and import it from a "
				  "keyserver?"),
				  GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
			GTK_EVENTS_FLUSH();
		}
		if (val == G_ALERTDEFAULT) {
			TEXTVIEW_INSERT(_("\n  Key ID "));
			TEXTVIEW_INSERT(sig->fpr);
			TEXTVIEW_INSERT(":\n\n");
			TEXTVIEW_INSERT(_("   This key is not in your keyring.\n"));
			TEXTVIEW_INSERT(_("   It should be possible to import it "));
			if (prefs_common_get_prefs()->work_offline)
				TEXTVIEW_INSERT(_("when working online,\n   or "));
			TEXTVIEW_INSERT(_("with the following command: \n\n     "));
			TEXTVIEW_INSERT(cmd);
		} else {
			TEXTVIEW_INSERT(_("\n  Importing key ID "));
			TEXTVIEW_INSERT(sig->fpr);
			TEXTVIEW_INSERT(":\n\n");

			main_window_cursor_wait(mainwindow_get_mainwindow());
			textview_cursor_wait(textview);
			GTK_EVENTS_FLUSH();

#ifndef G_OS_WIN32
			int res = 0;
			pid_t pid = 0;

			pid = fork();
			if (pid == -1) {
				res = -1;
			} else if (pid == 0) {
				/* son */
				gchar **argv;
				argv = strsplit_with_quote(cmd, " ", 0);
				res = execvp(argv[0], argv);
				perror("execvp");
				exit(255);
			} else {
				int status = 0;
				time_t start_wait = time(NULL);
				res = -1;
				do {
					if (waitpid(pid, &status, WNOHANG) == 0 || !WIFEXITED(status)) {
						usleep(200000);
					} else {
						res = WEXITSTATUS(status);
						break;
					}
					if (time(NULL) - start_wait > 9) {
						debug_print("SIGTERM'ing gpg %d\n", pid);
						kill(pid, SIGTERM);
					}
					if (time(NULL) - start_wait > 10) {
						debug_print("SIGKILL'ing gpg %d\n", pid);
						kill(pid, SIGKILL);
						break;
					}
				} while(1);
			}
			debug_print("res %d\n", res);
			if (res == 0)
				imported = TRUE;
#else
			/* We need to call gpg in a separate thread, so that waiting for
			 * it to finish does not block the UI. */
			pthread_t pt;
			struct _ImportCtx *ctx = malloc(sizeof(struct _ImportCtx));

			ctx->done = FALSE;
			ctx->exitcode = STILL_ACTIVE;
			ctx->cmd = cmd;

			if (pthread_create(&pt, NULL,
						_import_threaded, (void *)ctx) != 0) {
				debug_print("Couldn't create thread, continuing unthreaded.\n");
				_import_threaded(ctx);
			} else {
				debug_print("Thread created, waiting for it to finish...\n");
				while (!ctx->done)
					claws_do_idle();
			}

			debug_print("Thread finished.\n");
			pthread_join(pt, NULL);

			if (ctx->exitcode == 0) {
				imported = TRUE;
			}
			g_free(ctx);
#endif
			main_window_cursor_normal(mainwindow_get_mainwindow());
			textview_cursor_normal(textview);
			if (imported) {
				TEXTVIEW_INSERT(_("   This key has been imported to your keyring.\n"));
			} else {
				TEXTVIEW_INSERT(_("   This key couldn't be imported to your keyring.\n"));
				TEXTVIEW_INSERT(_("   Key servers are sometimes slow.\n"));
				TEXTVIEW_INSERT(_("   You can try to import it manually with the command:\n\n     "));
				TEXTVIEW_INSERT(cmd);
			}
		}
		g_free(cmd);
		return;
	} else {
		TEXTVIEW_INSERT(_("\n  Key ID "));

#if defined GPGME_VERSION_NUMBER && GPGME_VERSION_NUMBER >= 0x010700
		TEXTVIEW_INSERT(key->fpr);
#else
		TEXTVIEW_INSERT(sig->fpr);
#endif

		TEXTVIEW_INSERT(":\n\n");
		TEXTVIEW_INSERT(_("   This key is in your keyring.\n"));
	}
	gpgme_data_release(sigdata);
	gpgme_release(ctx);
	textview_show_icon(textview, GTK_STOCK_DIALOG_AUTHENTICATION);
}
Пример #20
0
int spamassassin_learn(MsgInfo *msginfo, GSList *msglist, gboolean spam)
{
	gchar *cmd = NULL;
	gchar *file = NULL;
	const gchar *shell = g_getenv("SHELL");
	gchar *spamc_wrapper = NULL;

	if (msginfo == NULL && msglist == NULL) {
		return -1;
	}

	if (config.transport == SPAMASSASSIN_TRANSPORT_TCP
	&&  prefs_common_get_prefs()->work_offline
	&&  !inc_offline_should_override(TRUE,
		_("Claws Mail needs network access in order "
		  "to feed the mail to the remote learner."))) {
		return -1;
	}

	if (msginfo) {
		file = procmsg_get_message_file(msginfo);
		if (file == NULL) {
			return -1;
		}
		if (config.transport == SPAMASSASSIN_TRANSPORT_TCP) {
			spamc_wrapper = spamassassin_create_tmp_spamc_wrapper(spam);
			if (spamc_wrapper != NULL) {
				cmd = g_strconcat(shell?shell:"sh", " ",
								spamc_wrapper, " ", file, NULL);
			}
		} else {
			cmd = g_strdup_printf("sa-learn -u %s%s %s %s",
							config.username,
							prefs_common_get_prefs()->work_offline?" -L":"",
							spam?"--spam":"--ham", file);
		}
	}
	if (msglist) {
		GSList *cur = msglist;
		MsgInfo *info;

		if (config.transport == SPAMASSASSIN_TRANSPORT_TCP) {
			/* execute n-times the spamc command */
			for (; cur; cur = cur->next) {
				info = (MsgInfo *)cur->data;
				gchar *tmpcmd = NULL;
				gchar *tmpfile = get_tmp_file();

				if (spamc_wrapper == NULL) {
					spamc_wrapper = spamassassin_create_tmp_spamc_wrapper(spam);
				}

				if (spamc_wrapper && tmpfile &&
			    	copy_file(procmsg_get_message_file(info), tmpfile, TRUE) == 0) {
					tmpcmd = g_strconcat(shell?shell:"sh", " ", spamc_wrapper, " ",
										tmpfile, NULL);
					debug_print("%s\n", tmpcmd);
					execute_command_line(tmpcmd, FALSE, NULL);
					g_free(tmpcmd);
				}
				g_free(tmpfile);
			}
			g_free(spamc_wrapper);
			return 0;
		} else {
			cmd = g_strdup_printf("sa-learn -u %s%s %s",
					config.username,
					prefs_common_get_prefs()->work_offline?" -L":"",
					spam?"--spam":"--ham");

			/* concatenate all message tmpfiles to the sa-learn command-line */
			for (; cur; cur = cur->next) {
				info = (MsgInfo *)cur->data;
				gchar *tmpcmd = NULL;
				gchar *tmpfile = get_tmp_file();

				if (tmpfile &&
			    	copy_file(procmsg_get_message_file(info), tmpfile, TRUE) == 0) {			
					tmpcmd = g_strconcat(cmd, " ", tmpfile, NULL);
					g_free(cmd);
					cmd = tmpcmd;
				}
				g_free(tmpfile);
			}
		}
	}
	if (cmd == NULL) {
		return -1;
	}
	debug_print("%s\n", cmd);
	/* only run sync calls to sa-learn/spamc to prevent system lockdown */
	execute_command_line(cmd, FALSE, NULL);
	g_free(cmd);
	g_free(spamc_wrapper);

	return 0;
}
Пример #21
0
/* Create the window for selecting folders with checkboxes */
static void foldercheck_create_window(SpecificFolderArrayEntry *entry)
{
  GtkWidget *vbox;
  GtkWidget *scrolledwin;
  GtkWidget *confirm_area;
  GtkWidget *checkbox;
  GtkWidget *cancel_button;
  GtkWidget *ok_button;
  GtkTreeSelection *selection;
  GtkTreeViewColumn *column;
  GtkCellRenderer *renderer;
  static GdkGeometry geometry;

  /* Create window */
  entry->window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "notification_foldercheck");
  gtk_window_set_title(GTK_WINDOW(entry->window), _("Select folder(s)"));
  gtk_container_set_border_width(GTK_CONTAINER(entry->window), 4);
  gtk_window_set_position(GTK_WINDOW(entry->window), GTK_WIN_POS_CENTER);
  gtk_window_set_modal(GTK_WINDOW(entry->window), TRUE);
  gtk_window_set_resizable(GTK_WINDOW(entry->window), TRUE);
  gtk_window_set_wmclass
    (GTK_WINDOW(entry->window), "folder_selection", "Claws Mail");  
  g_signal_connect(G_OBJECT(entry->window), "delete_event",
		   G_CALLBACK(delete_event), entry);
  g_signal_connect(G_OBJECT(entry->window), "key_press_event",
      G_CALLBACK(key_pressed), entry);
  MANAGE_WINDOW_SIGNALS_CONNECT(entry->window);

  /* vbox */
  vbox = gtk_vbox_new(FALSE, 4);
  gtk_container_add(GTK_CONTAINER(entry->window), vbox);

  /* scrolled window */
  scrolledwin = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
				 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
				      GTK_SHADOW_IN);
  gtk_box_pack_start(GTK_BOX(vbox), scrolledwin, TRUE, TRUE, 0);

  /* pixbufs */
  if(!folder_pixbuf)
    stock_pixbuf_gdk(STOCK_PIXMAP_DIR_CLOSE,
		     &folder_pixbuf);
  if(!folderopen_pixbuf)
    stock_pixbuf_gdk(STOCK_PIXMAP_DIR_OPEN,
		     &folderopen_pixbuf);
  if(!foldernoselect_pixbuf)
    stock_pixbuf_gdk(STOCK_PIXMAP_DIR_NOSELECT_CLOSE,
		     &foldernoselect_pixbuf);
  if(!foldernoselectopen_pixbuf)
    stock_pixbuf_gdk(STOCK_PIXMAP_DIR_NOSELECT_OPEN,
		     &foldernoselectopen_pixbuf);

  /* Tree store */
  foldercheck_set_tree(entry);
  gtk_tree_model_foreach(GTK_TREE_MODEL(entry->tree_store),
			 foldercheck_foreach_update_to_list, entry);


  /* tree view */
  entry->treeview =
    gtk_tree_view_new_with_model(GTK_TREE_MODEL(entry->tree_store));
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(entry->treeview), FALSE);
  gtk_tree_view_set_search_column(GTK_TREE_VIEW(entry->treeview),
				  FOLDERCHECK_FOLDERNAME);
  gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(entry->treeview),
				  prefs_common_get_prefs()->use_stripes_everywhere);
  gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(entry->treeview), FALSE);

  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(entry->treeview));
  gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
  gtk_tree_selection_set_select_function(selection, foldercheck_selected,
					 NULL, NULL);

  gtk_container_add(GTK_CONTAINER(scrolledwin), entry->treeview);

  /* --- column 1 --- */
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, "sel");
  gtk_tree_view_column_set_spacing(column, 2);
  
  /* checkbox */
  renderer = gtk_cell_renderer_toggle_new();
  g_object_set(renderer, "xalign", 0.0, NULL);
  gtk_tree_view_column_pack_start(column, renderer, TRUE);
  g_signal_connect(renderer, "toggled", G_CALLBACK(folder_toggle_cb),entry);
  gtk_tree_view_column_set_attributes(column, renderer,
				      "active", FOLDERCHECK_CHECK,NULL);

  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(entry->treeview), column);

  /* --- column 2 --- */
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, "Folder");
  gtk_tree_view_column_set_spacing(column, 2);

  /* pixbuf */
  renderer = gtk_cell_renderer_pixbuf_new();
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  gtk_tree_view_column_set_attributes
    (column, renderer,
     "pixbuf", FOLDERCHECK_PIXBUF,
     "pixbuf-expander-open", FOLDERCHECK_PIXBUF_OPEN,
     "pixbuf-expander-closed", FOLDERCHECK_PIXBUF,
     NULL);

  /* text */
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, renderer, TRUE);
  gtk_tree_view_column_set_attributes(column, renderer,
				      "text", FOLDERCHECK_FOLDERNAME,
				      NULL);

  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(entry->treeview), column);

  /* recursive */
  checkbox = gtk_check_button_new_with_label( _("select recursively"));
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), FALSE);
  g_signal_connect(G_OBJECT(checkbox), "toggled",
		   G_CALLBACK(foldercheck_recursive_cb), entry);
  gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 10);

  gtkut_stock_button_set_create(&confirm_area,
				&cancel_button, GTK_STOCK_CANCEL,
				&ok_button,     GTK_STOCK_OK,
				NULL,           NULL);
  gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
  gtk_widget_grab_default(ok_button);

  g_signal_connect(G_OBJECT(ok_button), "clicked",
		   G_CALLBACK(foldercheck_ok), entry);
  g_signal_connect(G_OBJECT(cancel_button), "clicked",
		   G_CALLBACK(foldercheck_cancel), entry);

  if(!geometry.min_height) {
    geometry.min_width = 360;
    geometry.min_height = 360;
  }

  gtk_window_set_geometry_hints(GTK_WINDOW(entry->window), NULL, &geometry,
				GDK_HINT_MIN_SIZE);

  gtk_tree_view_expand_all(GTK_TREE_VIEW(entry->treeview));

  gtk_widget_show_all(vbox);
}
Пример #22
0
void notification_update_trayicon()
{
  gchar *buf;
  static GdkPixbuf *old_icon = NULL;
  GdkPixbuf *new_icon;
  gint offset;
  NotificationMsgCount count;
  GSList *list;

  if(!notify_config.trayicon_enabled)
    return;

  if(notify_config.trayicon_folder_specific) {
    guint id;
    id =
      notification_register_folder_specific_list
      (TRAYICON_SPECIFIC_FOLDER_ID_STR);
    list = notification_foldercheck_get_list(id);
  }
  else
    list = NULL;

  notification_core_get_msg_count(list, &count);

  if(!trayicon) {

#ifdef NOTIFICATION_HOTKEYS
    notification_hotkeys_update_bindings();
#endif

    old_icon = notification_trayicon_create();
    if(!trayicon) {
      debug_print("Notification plugin: Could not create trayicon\n");
      return;
    }
  }

  /* Tooltip */
  buf = g_strdup_printf(_("New %d, Unread: %d, Total: %d"),
			count.new_msgs, count.unread_msgs,
			count.total_msgs);
#if GTK_CHECK_VERSION(2,16,0)
  gtk_status_icon_set_tooltip_text(trayicon, buf);
#else
  gtk_status_icon_set_tooltip(trayicon, buf);
#endif
  g_free(buf);

  /* Pixmap */
  (prefs_common_get_prefs()->work_offline) ? (offset = 1) : (offset = 0);

  if((count.new_msgs > 0) && (count.unreadmarked_msgs > 0))
    new_icon =
      notification_pixbuf_get(NOTIFICATION_TRAYICON_NEWMARKEDMAIL+offset);
  else if(count.new_msgs > 0)
    new_icon =
      notification_pixbuf_get(NOTIFICATION_TRAYICON_NEWMAIL+offset);
  else if(count.unreadmarked_msgs > 0)
    new_icon =
      notification_pixbuf_get(NOTIFICATION_TRAYICON_UNREADMARKEDMAIL+offset);
  else if(count.unread_msgs > 0)
    new_icon =
      notification_pixbuf_get(NOTIFICATION_TRAYICON_UNREADMAIL+offset);
  else
    new_icon =
      notification_pixbuf_get(NOTIFICATION_TRAYICON_NOMAIL+offset);

  if(new_icon != old_icon) {
    gtk_status_icon_set_from_pixbuf(trayicon, new_icon);
    old_icon = new_icon;
  }
}
Пример #23
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;
}
Пример #24
0
static gboolean scan_func(GNode *node, gpointer data)
{
    struct clamd_result *result = (struct clamd_result *) data;
    MimeInfo *mimeinfo = (MimeInfo *) node->data;
    gchar *outfile;
    response buf;
    int max;
    GStatBuf info;
    gchar* msg;

    outfile = procmime_get_tmp_file_name(mimeinfo);
    if (procmime_get_part(outfile, mimeinfo) < 0)
        g_warning("Can't get the part of multipart message.");
    else {
        max = config.clamav_max_size * 1048576; /* maximum file size */
        if (g_stat(outfile, &info) == -1)
            g_warning("Can't determine file size");
        else {
            if (info.st_size <= max) {
                debug_print("Scanning %s\n", outfile);
                result->status = clamd_verify_email(outfile, &buf);
                debug_print("status: %d\n", result->status);
                switch (result->status) {
                case NO_SOCKET:
                    g_warning("[scanning] No socket information");
                    if (config.alert_ack) {
                        alertpanel_error(_("Scanning\nNo socket information.\nAntivirus disabled."));
                        config.alert_ack = FALSE;
                    }
                    break;
                case NO_CONNECTION:
                    g_warning("[scanning] Clamd does not respond to ping");
                    if (config.alert_ack) {
                        alertpanel_warning(_("Scanning\nClamd does not respond to ping.\nIs clamd running?"));
                        config.alert_ack = FALSE;
                    }
                    break;
                case VIRUS:
                    msg = g_strconcat(_("Detected %s virus."),
                                      clamd_get_virus_name(buf.msg), NULL);
                    g_warning("%s\n", msg);
                    debug_print("no_recv: %d\n", prefs_common_get_prefs()->no_recv_err_panel);
                    if (prefs_common_get_prefs()->no_recv_err_panel) {
                        statusbar_print_all("%s", msg);
                    }
                    else {
                        alertpanel_warning("%s\n", msg);
                    }
                    g_free(msg);
                    config.alert_ack = TRUE;
                    break;
                case SCAN_ERROR:
                    debug_print("Error: %s\n", buf.msg);
                    if (config.alert_ack) {
                        alertpanel_error(_("Scanning error:\n%s"), buf.msg);
                        config.alert_ack = FALSE;
                    }
                    break;
                case OK:
                    debug_print("No virus detected.\n");
                    config.alert_ack = TRUE;
                    break;
                }
            }
            else {
                msg = g_strdup_printf(_("File: %s. Size (%d) greater than limit (%d)\n"), outfile, (int) info.st_size, max);
                statusbar_print_all("%s", msg);
                debug_print("%s", msg);
                g_free(msg);
            }
        }
        g_unlink(outfile);
    }

    return (result->status == OK) ? FALSE : TRUE;
}