1 //  gnoMint: a graphical interface for managing a certification authority
2 //  Copyright (C) 2006-2009 David Marín Carreño <davefx@gmail.com>
3 //
4 //  This file is part of gnoMint.
5 //
6 //  gnoMint is free software; you can redistribute it and/or modify
7 //  it under the terms of the GNU General Public License as published by
8 //  the Free Software Foundation; either version 3 of the License, or
9 //  (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20 #include <libintl.h>
21 #include <glib.h>
22 #include <glib/gi18n.h>
23 #include <gtk/gtk.h>
24 
25 #include <stdlib.h>
26 
27 #include "main.h"
28 #include "ca.h"
29 #include "dialog.h"
30 #include "tls.h"
31 #include "ca_file.h"
32 #include "preferences-gui.h"
33 
34 #define GNOMINT_MIME_TYPE "application/x-gnomint"
35 
36 GtkBuilder * main_window_gtkb = NULL;
37 GtkBuilder * csr_popup_menu_gtkb = NULL;
38 GtkBuilder * cert_popup_menu_gtkb = NULL;
39 
40 gchar * gnomint_current_opened_file = NULL;
41 
42 static GtkRecentManager *recent_manager;
43 
44 void __recent_add_utf8_filename (const gchar *utf8_filename);
45 void __disable_widget (gchar *widget_name);
46 void __enable_widget (gchar *widget_name);
47 GtkWidget * __recent_create_menu (void);
48 void __recent_add_utf8_filename (const gchar *utf8_filename);
49 
50 
51 
__disable_widget(gchar * widget_name)52 void __disable_widget (gchar *widget_name)
53 {
54 	GtkWidget * widget = NULL;
55 
56 	widget = GTK_WIDGET(gtk_builder_get_object (main_window_gtkb, widget_name));
57 
58 	gtk_widget_set_sensitive (widget, FALSE);
59 }
60 
__enable_widget(gchar * widget_name)61 void __enable_widget (gchar *widget_name)
62 {
63 	GtkWidget * widget = NULL;
64 
65 	widget = GTK_WIDGET(gtk_builder_get_object (main_window_gtkb, widget_name));
66 
67 	gtk_widget_set_sensitive (widget, TRUE);
68 }
69 
70 /*****************************************************************************/
71 /* Create a menu of recent files.                                            */
72 /*****************************************************************************/
__recent_create_menu(void)73 GtkWidget * __recent_create_menu (void)
74 {
75         GtkWidget               *recent_menu;
76         GtkRecentFilter         *recent_filter;
77 
78         recent_menu = gtk_recent_chooser_menu_new_for_manager (recent_manager);
79         gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (recent_menu), FALSE);
80         gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (recent_menu), TRUE);
81         gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (recent_menu), 4);
82         gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (recent_menu), GTK_RECENT_SORT_MRU);
83         gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (recent_menu), TRUE);
84 
85         recent_filter = gtk_recent_filter_new ();
86         gtk_recent_filter_add_mime_type (recent_filter, GNOMINT_MIME_TYPE);
87         gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (recent_menu), recent_filter);
88 
89         return recent_menu;
90 }
91 
92 
main(int argc,char * argv[])93 int main (int   argc,
94 	  char *argv[])
95 {
96         gchar *defaultfile = NULL;
97 	GOptionContext *ctx;
98 	GError *err = NULL;
99 	GOptionEntry entries[] = {
100 		{ NULL }
101 	};
102 
103 	GtkWidget * recent_menu = NULL;
104         gchar     * size_str = NULL;
105 
106 #ifdef ENABLE_NLS
107 	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
108 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
109 	textdomain (GETTEXT_PACKAGE);
110 #endif
111 
112 	g_set_application_name (PACKAGE);
113 	g_set_prgname (PACKAGE);
114 
115 	tls_init ();
116 
117 	g_thread_init (NULL);
118 	gtk_init (&argc, &argv);
119 
120 	preferences_gui_set_csr_visible_callback (ca_update_csr_view);
121 	preferences_gui_set_revoked_visible_callback (ca_update_revoked_view);
122 
123         preferences_init (argc, argv);
124 
125 	ctx = g_option_context_new (_("- A graphical Certification Authority manager"));
126 	g_option_context_add_main_entries (ctx, entries, GETTEXT_PACKAGE);
127 	if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
128 		g_print (_("Failed to initialize: %s\n"), err->message);
129 		g_error_free (err);
130 		return 1;
131 	}
132 
133 	main_window_gtkb = gtk_builder_new();
134 	gtk_builder_add_from_file (main_window_gtkb,
135 				   g_build_filename (PACKAGE_DATA_DIR, "gnomint", "main_window.ui", NULL),
136 				   NULL);
137 
138 	csr_popup_menu_gtkb = gtk_builder_new();
139 	gtk_builder_add_from_file (csr_popup_menu_gtkb,
140 				   g_build_filename (PACKAGE_DATA_DIR, "gnomint", "csr_popup_menu.ui", NULL),
141 				   NULL);
142 
143 	cert_popup_menu_gtkb = gtk_builder_new();
144 	gtk_builder_add_from_file (cert_popup_menu_gtkb,
145 				   g_build_filename (PACKAGE_DATA_DIR, "gnomint", "certificate_popup_menu.ui", NULL),
146 				   NULL);
147 
148 
149         size_str = preferences_get_size ();
150         if (size_str) {
151                 gchar ** result = NULL;
152                 guint width, height;
153 
154                 result = g_strsplit_set (size_str, "(,)", -1);
155 
156                 if (result[0] && result[1]) {
157                         width = atoi (result[1]);
158                         if (result[2]) {
159                                 height = atoi (result[2]);
160                                 gtk_window_resize (GTK_WINDOW(gtk_builder_get_object(main_window_gtkb, "main_window1")), width, height);
161                         }
162 
163                 }
164 
165                 g_free (size_str);
166                 g_strfreev (result);
167         }
168         ca_update_revoked_view (preferences_get_revoked_visible(), FALSE);
169         ca_update_csr_view (preferences_get_crq_visible(), FALSE);
170 
171 
172 	gtk_builder_connect_signals (main_window_gtkb, NULL);
173 	gtk_builder_connect_signals (cert_popup_menu_gtkb, NULL);
174 	gtk_builder_connect_signals (csr_popup_menu_gtkb, NULL);
175 
176 	recent_manager = gtk_recent_manager_get_default ();
177 	recent_menu = __recent_create_menu();
178 	g_signal_connect (G_OBJECT (recent_menu), "item-activated",
179 			  G_CALLBACK (on_open_recent_activate), NULL);
180 	gtk_menu_item_set_submenu (GTK_MENU_ITEM (gtk_builder_get_object (main_window_gtkb, "openrecentsmenuitem")), recent_menu);
181 
182 
183 	__disable_widget ("new_certificate1");
184 	__disable_widget ("save_as1");
185 	__disable_widget ("properties1");
186 	__disable_widget ("preferences1");
187 
188 	dialog_establish_refresh_function (ca_refresh_model_callback);
189 
190 
191 	if (argc >= 2 && ca_open (g_strdup(argv[1]), TRUE)) {
192                 /* The file has opened OK */
193 		__recent_add_utf8_filename (argv[1]);
194         } else {
195                 /* No arguments, or failure when opening file */
196                 defaultfile = g_build_filename (g_get_home_dir(), ".gnomint", "default.gnomint", NULL);
197 		__recent_add_utf8_filename (defaultfile);
198                 ca_open (defaultfile, TRUE);
199         }
200 
201 	gtk_main ();
202 
203 	return 0;
204 }
205 
206 
207 
on_main_window1_delete(GtkWidget * widget,GdkEvent * event,gpointer user_data)208 G_MODULE_EXPORT gboolean on_main_window1_delete (GtkWidget *widget,
209 				  GdkEvent *event,
210 				  gpointer user_data)
211 {
212         GtkWindow *window = GTK_WINDOW(widget);
213         int width, height;
214         gchar *new_size_value;
215 
216         gtk_window_get_size (window, &width, &height);
217         new_size_value = g_strdup_printf ("(%d,%d)", width, height);
218 
219         preferences_set_size (new_size_value);
220 
221         g_free (new_size_value);
222         preferences_deinit();
223 
224 	exit (0);
225 	return TRUE;
226 }
227 
__recent_add_utf8_filename(const gchar * utf8_filename)228 void __recent_add_utf8_filename (const gchar *utf8_filename)
229 {
230         GtkRecentData *recent_data;
231         gchar         *filename;
232         gchar         *uri;
233 	gchar         *pwd;
234 
235         static gchar *groups[2] = {
236                 "gnomint",
237                 NULL
238         };
239 
240 
241         recent_data = g_slice_new (GtkRecentData);
242 
243         recent_data->display_name = NULL;
244         recent_data->description  = NULL;
245         recent_data->mime_type    = GNOMINT_MIME_TYPE;
246         recent_data->app_name     = (gchar *) g_get_application_name ();
247         recent_data->app_exec     = g_strjoin (" ", g_get_prgname (), "%f", NULL);
248         recent_data->groups       = groups;
249         recent_data->is_private = FALSE;
250 
251         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
252         if ( filename != NULL )
253         {
254 
255 		if (! g_path_is_absolute (filename)) {
256 			gchar *absolute_filename;
257 
258 			pwd = g_get_current_dir ();
259 			absolute_filename = g_build_filename (pwd, filename, NULL);
260 			g_free (pwd);
261 			g_free (filename);
262 			filename = absolute_filename;
263 		}
264 
265 
266                 uri = g_filename_to_uri (filename, NULL, NULL);
267                 if ( uri != NULL )
268                 {
269 
270                         gtk_recent_manager_add_full (recent_manager, uri, recent_data);
271                         g_free (uri);
272 
273                 }
274                 g_free (filename);
275 
276         }
277 
278         g_free (recent_data->app_exec);
279         g_slice_free (GtkRecentData, recent_data);
280 
281 }
282 
on_new1_activate(GtkMenuItem * menuitem,gpointer user_data)283 G_MODULE_EXPORT void on_new1_activate (GtkMenuItem *menuitem, gpointer     user_data)
284 {
285 	gchar *filename;
286         gchar *error = NULL;
287 
288 	GtkWidget *dialog, *widget;
289 
290 	widget = GTK_WIDGET(gtk_builder_get_object (main_window_gtkb, "main_window"));
291 
292 	dialog = gtk_file_chooser_dialog_new (_("Create new CA database"),
293 					      GTK_WINDOW(widget),
294 					      GTK_FILE_CHOOSER_ACTION_SAVE,
295 					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
296 					      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
297 					      NULL);
298 	gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
299 
300 
301 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
302 	{
303 		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
304 		gtk_widget_destroy (dialog);
305 	} else {
306 		gtk_widget_destroy (dialog);
307 		return;
308 	}
309 
310         if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
311                 /* The file already exists. The user has confirmed its overwriting.
312                    So we, first, rename it to "filename~", after deleting "filename~" if it already exists */
313 
314                 gchar *backup_filename = g_strdup_printf ("%s~", filename);
315                 if (g_file_test (backup_filename, G_FILE_TEST_EXISTS)) {
316                         g_remove (backup_filename);
317                 }
318 
319                 g_rename (filename, backup_filename);
320 
321                 g_free (backup_filename);
322         }
323 
324         error = ca_file_create (filename);
325         if (error) {
326 		dialog = gtk_message_dialog_new (GTK_WINDOW(widget),
327 						 GTK_DIALOG_DESTROY_WITH_PARENT,
328 						 GTK_MESSAGE_ERROR,
329 						 GTK_BUTTONS_CLOSE,
330 						 _("Problem when creating '%s' CA database:\n%s"),
331 						 filename, error);
332 
333 		gtk_dialog_run (GTK_DIALOG(dialog));
334 
335                 return;
336         }
337 
338 	if (! ca_open (filename, FALSE)) {
339 		dialog = gtk_message_dialog_new (GTK_WINDOW(widget),
340 						 GTK_DIALOG_DESTROY_WITH_PARENT,
341 						 GTK_MESSAGE_ERROR,
342 						 GTK_BUTTONS_CLOSE,
343 						 _("Problem when opening new '%s' CA database"),
344 						 filename);
345 
346 		gtk_dialog_run (GTK_DIALOG(dialog));
347 
348 		gtk_widget_destroy (dialog);
349 	} else {
350 		__recent_add_utf8_filename (filename);
351         }
352 	return;
353 
354 }
355 
on_open1_activate(GtkMenuItem * menuitem,gpointer user_data)356 G_MODULE_EXPORT void on_open1_activate  (GtkMenuItem *menuitem, gpointer     user_data)
357 {
358 	gchar *filename;
359 
360 	GtkWidget *dialog, *widget;
361 
362 	widget = GTK_WIDGET(gtk_builder_get_object (main_window_gtkb, "main_window"));
363 
364 	dialog = gtk_file_chooser_dialog_new (_("Open CA database"),
365 					      GTK_WINDOW(widget),
366 					      GTK_FILE_CHOOSER_ACTION_OPEN,
367 					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
368 					      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
369 					      NULL);
370 
371 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
372 	{
373 		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
374 		gtk_widget_destroy (dialog);
375 	} else {
376 		gtk_widget_destroy (dialog);
377 		return;
378 	}
379 
380 
381 
382 	if (! ca_open (filename, FALSE)) {
383 		dialog = gtk_message_dialog_new (GTK_WINDOW(widget),
384 						 GTK_DIALOG_DESTROY_WITH_PARENT,
385 						 GTK_MESSAGE_ERROR,
386 						 GTK_BUTTONS_CLOSE,
387 						 _("Problem when opening '%s' CA database"),
388 						 filename);
389 
390 		gtk_dialog_run (GTK_DIALOG(dialog));
391 
392 		gtk_widget_destroy (dialog);
393 	} else {
394 		__recent_add_utf8_filename (filename);
395 	}
396 	return;
397 }
398 
on_open_recent_activate(GtkRecentChooser * chooser,gpointer user_data)399 void on_open_recent_activate (GtkRecentChooser *chooser, gpointer user_data)
400 {
401         GtkRecentInfo *item;
402 	gchar *filename;
403 	gchar *utf8_filename = NULL;
404 	GtkWidget *dialog;
405 	const gchar *uri;
406 
407         g_return_if_fail (chooser && GTK_IS_RECENT_CHOOSER(chooser));
408 
409         item = gtk_recent_chooser_get_current_item (chooser);
410         if (!item)
411                 return;
412 
413 	uri = gtk_recent_info_get_uri (item);
414 
415         filename = g_filename_from_uri (uri, NULL, NULL);
416         if ( filename != NULL )
417         {
418                 utf8_filename = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
419                 g_free (filename);
420         }
421 
422         if (! utf8_filename || ! ca_open (utf8_filename, FALSE)) {
423 		dialog = gtk_message_dialog_new (NULL,
424 						 GTK_DIALOG_DESTROY_WITH_PARENT,
425 						 GTK_MESSAGE_ERROR,
426 						 GTK_BUTTONS_CLOSE,
427 						 _("Problem when opening '%s' CA database"),
428 						 utf8_filename);
429 
430 		gtk_dialog_run (GTK_DIALOG(dialog));
431 
432 		gtk_widget_destroy (dialog);
433 	} else {
434 		__recent_add_utf8_filename (utf8_filename);
435 	}
436 
437         gtk_recent_info_unref (item);
438 
439 
440 	return;
441 }
442 
443 
on_save_as1_activate(GtkMenuItem * menuitem,gpointer user_data)444 G_MODULE_EXPORT void on_save_as1_activate  (GtkMenuItem *menuitem, gpointer     user_data)
445 {
446 	gchar *filename;
447 
448 	GtkWidget *dialog, *widget;
449 
450 	widget = GTK_WIDGET(gtk_builder_get_object (main_window_gtkb, "main_window"));
451 
452 	dialog = gtk_file_chooser_dialog_new (_("Save CA database as..."),
453 					      GTK_WINDOW(widget),
454 					      GTK_FILE_CHOOSER_ACTION_SAVE,
455 					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
456 					      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
457 					      NULL);
458 	gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
459 
460 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
461 		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
462 		gtk_widget_destroy (dialog);
463 	} else {
464 		gtk_widget_destroy (dialog);
465 		return;
466 	}
467 
468 	if (ca_file_save_as (filename))
469                 __recent_add_utf8_filename (filename);
470 
471 }
472 
473 
474 
on_quit1_activate(GtkMenuItem * menuitem,gpointer user_data)475 G_MODULE_EXPORT void on_quit1_activate  (GtkMenuItem *menuitem, gpointer     user_data)
476 {
477 	on_main_window1_delete(NULL, NULL, NULL);
478 }
479 
480 
481 
482 
483 
484 /*
485  *
486  *   HELP MENU CALLBACKS
487  *
488  */
489 
on_about1_activate(GtkMenuItem * menuitem,gpointer user_data)490 G_MODULE_EXPORT void on_about1_activate  (GtkMenuItem *menuitem, gpointer     user_data)
491 {
492 
493 	GtkWidget *widget;
494 	gchar *authors[2];
495 
496 	widget = GTK_WIDGET(gtk_builder_get_object (main_window_gtkb, "main_window"));
497 
498 	authors[0] = PACKAGE_AUTHORS;
499 	authors[1] = NULL;
500 
501 	gtk_show_about_dialog (GTK_WINDOW(widget),
502 			       "version", PACKAGE_VERSION,
503 			       "copyright", PACKAGE_COPYRIGHT,
504 			       "comments", _("gnoMint is a program for creating and managing Certification Authorities, and their certificates"),
505 			       "license",  _("This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. \n\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA."),
506 			       "wrap_license", TRUE,
507 			       "website", PACKAGE_WEBSITE,
508 			       "authors", authors,
509 			       "translator_credits", _("translator-credits"),
510 			       NULL);
511 }
512