Exemple #1
0
/**
 * Completion idle function. This function is called by the main (UI) thread
 * during UI idle time while an address search is in progress. Items from the
 * display queue are processed and appended to the address list.
 *
 * \param data Target completion window to receive email addresses.
 * \return <i>TRUE</i> to ensure that idle event do not get ignored.
 */
static gboolean addrcompl_idle( gpointer data ) {
	GList *node;
	gchar *address;

	/* Process all entries in display queue */
	pthread_mutex_lock( & _completionMutex_ );
	if( _displayQueue_ ) {
		node = _displayQueue_;
		while( node ) {
			address = node->data;
			/* g_print( "address ::: %s :::\n", address ); */
			addrcompl_add_entry( _compWindow_, address );
			g_free( address );
			node = g_list_next( node );
		}
		g_list_free( _displayQueue_ );
		_displayQueue_ = NULL;
	}
	pthread_mutex_unlock( & _completionMutex_ );
	claws_do_idle();

	return TRUE;
}
Exemple #2
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);
}
Exemple #3
0
gchar *filesel_select_file_save(const gchar *title, const gchar *path)
{
	gboolean ret;
	gchar *str, *filename = NULL;
	gunichar2 *filename16, *path16, *title16;
	glong conv_items;
	GError *error = NULL;
	WinChooserCtx *ctx;
#ifdef USE_PTHREAD
	pthread_t pt;
#endif

	/* Find the filename part, if any */
	if (path == NULL || path[strlen(path)-1] == G_DIR_SEPARATOR) {
		filename = "";
	} else if ((filename = strrchr(path, G_DIR_SEPARATOR)) != NULL) {
		filename++;
	} else {
		filename = (char *) path;
	}

	/* Convert it to UTF-16. */
	filename16 = g_utf8_to_utf16(filename, -1, NULL, &conv_items, &error);
	if (error != NULL) {
		alertpanel_error(_("Could not convert attachment name to UTF-16:\n\n%s"),
				error->message);
		debug_print("filename '%s' conversion to UTF-16 failed\n", filename);
		g_error_free(error);
		return NULL;
	}

	/* Path needs to be converted to UTF-16, so that the native chooser
	 * can understand it. */
	path16 = g_utf8_to_utf16(path, -1, NULL, NULL, &error);
	if (error != NULL) {
		alertpanel_error(_("Could not convert file path to UTF-16:\n\n%s"),
				error->message);
		debug_print("file path '%s' conversion to UTF-16 failed\n", path);
		g_error_free(error);
		g_free(filename16);
		return NULL;
	}

	/* Chooser dialog title needs to be UTF-16 as well. */
	title16 = g_utf8_to_utf16(title, -1, NULL, NULL, &error);
	if (error != NULL) {
		debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
		g_error_free(error);
	}

	o.lStructSize = sizeof(OPENFILENAME);
	if (focus_window != NULL)
		o.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
	else
		o.hwndOwner = NULL;
	o.lpstrFilter = NULL;
	o.lpstrCustomFilter = NULL;
	o.lpstrFile = g_malloc0(MAXPATHLEN);
	if (path16 != NULL)
		memcpy(o.lpstrFile, filename16, conv_items * sizeof(gunichar2));
	o.nMaxFile = MAXPATHLEN;
	o.lpstrFileTitle = NULL;
	o.lpstrInitialDir = path16;
	o.lpstrTitle = title16;
	o.Flags = OFN_LONGNAMES | OFN_EXPLORER;

	ctx = g_new0(WinChooserCtx, 1);
	ctx->data = &o;
	ctx->return_value = FALSE;
	ctx->done = FALSE;

#ifdef USE_PTHREAD
	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_GetSaveFileName,
				(void *)ctx) != 0) {
		debug_print("Couldn't run in a thread, continuing unthreaded.\n");
		threaded_GetSaveFileName(ctx);
	} else {
		while (!ctx->done) {
			claws_do_idle();
		}
		pthread_join(pt, NULL);
	}
	ret = ctx->return_value;
#else
	debug_print("No threads available, continuing unthreaded.\n");
	ret = GetSaveFileName(&o);
#endif

	g_free(filename16);
	g_free(path16);
	g_free(title16);
	g_free(ctx);

	if (!ret) {
		g_free(o.lpstrFile);
		return NULL;
	}

	/* Now convert the returned file path back from UTF-16. */
	str = g_utf16_to_utf8(o.lpstrFile, o.nMaxFile, NULL, NULL, &error);
	if (error != NULL) {
		alertpanel_error(_("Could not convert file path back to UTF-8:\n\n%s"),
				error->message);
		debug_print("returned file path conversion to UTF-8 failed\n");
		g_error_free(error);
	}

	g_free(o.lpstrFile);
	return str;
}
Exemple #4
0
gchar *filesel_select_file_open_folder(const gchar *title, const gchar *path)
{
	PIDLIST_ABSOLUTE pidl;
	gchar *str;
	gunichar2 *path16, *title16;
	glong conv_items;
	GError *error = NULL;
	WinChooserCtx *ctx;
#ifdef USE_PTHREAD
	pthread_t pt;
#endif

	/* Path needs to be converted to UTF-16, so that the native chooser
	 * can understand it. */
	path16 = g_utf8_to_utf16(path ? path : "",
			-1, NULL, &conv_items, &error);
	if (error != NULL) {
		alertpanel_error(_("Could not convert file path to UTF-16:\n\n%s"),
				error->message);
		debug_print("file path '%s' conversion to UTF-16 failed\n", path);
		g_error_free(error);
		return NULL;
	}

	/* Chooser dialog title needs to be UTF-16 as well. */
	title16 = g_utf8_to_utf16(title ? title : "",
			-1, NULL, NULL, &error);
	if (error != NULL) {
		debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
		g_error_free(error);
	}

	if (focus_window != NULL)
		b.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
	else
		b.hwndOwner = NULL;
	b.pszDisplayName = g_malloc(MAXPATHLEN);
	b.lpszTitle = title16;
	b.ulFlags = 0;
	b.pidlRoot = NULL;
	b.lpfn = _open_folder_callback;
	b.lParam = (LPARAM)path16;

	CoInitialize(NULL);

	ctx = g_new0(WinChooserCtx, 1);
	ctx->data = &b;
	ctx->done = FALSE;

#ifdef USE_PTHREAD
	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_SHBrowseForFolder,
				(void *)ctx) != 0) {
		debug_print("Couldn't run in a thread, continuing unthreaded.\n");
		threaded_SHBrowseForFolder(ctx);
	} else {
		while (!ctx->done) {
			claws_do_idle();
		}
		pthread_join(pt, NULL);
	}
	pidl = ctx->return_value_pidl;
#else
	debug_print("No threads available, continuing unthreaded.\n");
	pidl = SHBrowseForFolder(&b);
#endif

	g_free(b.pszDisplayName);
	g_free(title16);
	g_free(path16);

	if (pidl == NULL) {
		CoUninitialize();
		g_free(ctx);
		return NULL;
	}

	path16 = malloc(MAX_PATH);
	if (!SHGetPathFromIDList(pidl, path16)) {
		CoTaskMemFree(pidl);
		CoUninitialize();
		g_free(path16);
		g_free(ctx);
		return NULL;
	}

	/* Now convert the returned file path back from UTF-16. */
	/* Unfortunately, there is no field in BROWSEINFO struct to indicate
	 * actual length of string in pszDisplayName, so we have to assume
	 * the string is null-terminated. */
	str = g_utf16_to_utf8(path16, -1, NULL, NULL, &error);
	if (error != NULL) {
		alertpanel_error(_("Could not convert file path back to UTF-8:\n\n%s"),
				error->message);
		debug_print("returned file path conversion to UTF-8 failed\n");
		g_error_free(error);
	}
	CoTaskMemFree(pidl);
	CoUninitialize();
	g_free(ctx);
	g_free(path16);

	return str;
}
Exemple #5
0
/* This function handles calling GetOpenFilename(), using
 * global static variable o.
 * It expects o.lpstrFile to point to an already allocated buffer,
 * of size at least MAXPATHLEN. */
static const gboolean _file_open_dialog(const gchar *path, const gchar *title,
		const gchar *filter, const gboolean multi)
{
	gboolean ret;
	gunichar2 *path16 = NULL;
	gunichar2 *title16 = NULL;
	gunichar2 *filter16 = NULL;
	gunichar2 *win_filter16 = NULL;
	glong conv_items, sz;
	GError *error = NULL;
	WinChooserCtx *ctx;
#ifdef USE_PTHREAD
	pthread_t pt;
#endif

	/* Path needs to be converted to UTF-16, so that the native chooser
	 * can understand it. */
	path16 = g_utf8_to_utf16(path ? path : "",
			-1, NULL, NULL, &error);
	if (error != NULL) {
		alertpanel_error(_("Could not convert file path to UTF-16:\n\n%s"),
				error->message);
		debug_print("file path '%s' conversion to UTF-16 failed\n", path);
		g_error_free(error);
		error = NULL;
		return FALSE;
	}

	/* Chooser dialog title needs to be UTF-16 as well. */
	title16 = g_utf8_to_utf16(title ? title : "",
			-1, NULL, NULL, &error);
	if (error != NULL) {
		debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
		g_error_free(error);
		error = NULL;
	}

	o.lStructSize = sizeof(OPENFILENAME);
	if (focus_window != NULL)
		o.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
	else
		o.hwndOwner = NULL;
	o.hInstance = NULL;
	o.lpstrFilter = NULL;
	o.lpstrCustomFilter = NULL;
	o.nFilterIndex = 0;
	o.nMaxFile = MAXPATHLEN;
	o.lpstrFileTitle = NULL;
	o.lpstrInitialDir = path16;
	o.lpstrTitle = title16;
	if (multi)
		o.Flags = OFN_LONGNAMES | OFN_EXPLORER | OFN_ALLOWMULTISELECT;
	else
		o.Flags = OFN_LONGNAMES | OFN_EXPLORER;

	if (filter != NULL && strlen(filter) > 0) {
		debug_print("Setting filter '%s'\n", filter);
		filter16 = g_utf8_to_utf16(filter, -1, NULL, &conv_items, &error);
		/* We're creating a UTF16 (2 bytes for each character) string:
		 * "filter\0filter\0\0"
		 * As g_utf8_to_utf16() will stop on first null byte, even if
		 * we pass string length in its second argument, we have to
		 * construct this string manually.
		 * conv_items contains number of UTF16 characters of our filter.
		 * Therefore we need enough bytes to store the filter string twice
		 * and three null chars. */
		sz = sizeof(gunichar2);
		win_filter16 = g_malloc0(conv_items*sz*2 + sz*3);
		memcpy(win_filter16, filter16, conv_items*sz);
		memcpy(win_filter16 + conv_items*sz + sz, filter16, conv_items*sz);
		g_free(filter16);

		if (error != NULL) {
			debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
			g_error_free(error);
			error = NULL;
		}
		o.lpstrFilter = (LPCTSTR)win_filter16;
		o.nFilterIndex = 1;
	}

	ctx = g_new0(WinChooserCtx, 1);
	ctx->data = &o;
	ctx->done = FALSE;

#ifdef USE_PTHREAD
	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_GetOpenFileName,
				(void *)ctx) != 0) {
		debug_print("Couldn't run in a thread, continuing unthreaded.\n");
		threaded_GetOpenFileName(ctx);
	} else {
		while (!ctx->done) {
			claws_do_idle();
		}
		pthread_join(pt, NULL);
	}
	ret = ctx->return_value;
#else
	debug_print("No threads available, continuing unthreaded.\n");
	ret = GetOpenFileName(&o);
#endif

	g_free(win_filter16);
	if (path16 != NULL) {
		g_free(path16);
	}
	g_free(title16);
	g_free(ctx);

	return ret;
}