1 /* ************************************************************************** */
2 /*                                                                            */
3 /*     Copyright (C)    2000-2008 Cédric Auger (cedric@grisbi.org)            */
4 /*          2003-2008 Benjamin Drieu (bdrieu@april.org)	                      */
5 /*          2008-2017 Pierre Biava (grisbi@pierre.biava.name)                 */
6 /*          https://www.grisbi.org/                                            */
7 /*                                                                            */
8 /*  This program is free software; you can redistribute it and/or modify      */
9 /*  it under the terms of the GNU General Public License as published by      */
10 /*  the Free Software Foundation; either version 2 of the License, or         */
11 /*  (at your option) any later version.                                       */
12 /*                                                                            */
13 /*  This program is distributed in the hope that it will be useful,           */
14 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of            */
15 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
16 /*  GNU General Public License for more details.                              */
17 /*                                                                            */
18 /*  You should have received a copy of the GNU General Public License         */
19 /*  along with this program; if not, write to the Free Software               */
20 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21 /*                                                                            */
22 /* ************************************************************************** */
23 
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include "include.h"
30 #include <time.h>
31 #include <limits.h>
32 #include <stdlib.h>
33 #include <glib/gstdio.h>
34 #include <glib/gi18n.h>
35 
36 #ifdef G_OS_WIN32
37 #include <stdlib.h> // For realpath()
38 #endif /* WIN32 */
39 
40 /*START_INCLUDE*/
41 #include "gsb_file.h"
42 #include "accueil.h"
43 #include "dialog.h"
44 #include "etats_gtktable.h"
45 #include "grisbi_app.h"
46 #include "gsb_account_property.h"
47 #include "gsb_assistant_account.h"
48 #include "gsb_data_account.h"
49 #include "gsb_data_archive_store.h"
50 #include "gsb_dirs.h"
51 #include "gsb_file_load.h"
52 #include "gsb_file_save.h"
53 #include "gsb_file_util.h"
54 #include "gsb_real.h"
55 #include "gsb_transactions_list.h"
56 #include "menu.h"
57 #include "navigation.h"
58 #include "parametres.h"
59 #include "structures.h"
60 #include "traitement_variables.h"
61 #include "transaction_list.h"
62 #include "utils.h"
63 #include "utils_dates.h"
64 #include "utils_files.h"
65 #include "utils_str.h"
66 #include "erreur.h"
67 /*END_INCLUDE*/
68 
69 /**
70  * keep the last path used in grisbi, save in the configuration at the end */
71 static gchar *last_path_used = NULL;
72 
73 static gchar *backup_path = NULL;
74 
75 /** the timeout used to save a backup every x minutes */
76 gint id_timeout = 0;
77 
78 /*START_EXTERN*/
79 /*END_EXTERN*/
80 
81 /******************************************************************************/
82 /* Private Methods                                                            */
83 /******************************************************************************/
84 /**
85  *
86  *
87  * \param
88  *
89  * \return
90  **/
gsb_file_remove_old_backup(const gchar * filename,gint remove_backup_months)91 static void gsb_file_remove_old_backup (const gchar *filename,
92 										gint remove_backup_months)
93 {
94 	GFileEnumerator *direnum;
95 	GFile *dir;
96 	GDate *first_old_date;
97     GSList *filenames = NULL;
98     GSList *iterator;
99 	gchar *basename;
100 	gchar *name = NULL;
101 
102 	devel_debug (filename);
103 
104 	/* get name of file without extension */
105 	basename = g_path_get_basename (filename);
106 	if (g_str_has_suffix (basename, ".gsb"))
107 	{
108 		name = g_strndup (basename, strlen (basename) - 4);
109 		g_free (basename);
110 	}
111 	else
112 	{
113 		g_free (basename);
114 
115 		return;
116 	}
117 
118 	if (!name)
119 		return;
120 
121 	/* get today date and first_old_date */
122 	first_old_date = gdate_today ();
123 	g_date_subtract_months (first_old_date, remove_backup_months);
124 
125 	/* balayage du répertoire de sauvegarde */
126 	dir =  g_file_new_for_path (backup_path);
127 	direnum = g_file_enumerate_children (dir,
128 										"standard::*",
129 										G_FILE_QUERY_INFO_NONE,
130 										NULL,
131 										NULL);
132 	if (!direnum)
133 		return;
134 
135 	while (TRUE)
136 	{
137 		GFileInfo *info = NULL;
138 		const gchar *old_filename;
139 
140 		if (!g_file_enumerator_iterate (direnum, &info, NULL, NULL, NULL))
141 			break;
142 
143 		if (!info)
144 		  break;
145 
146 		old_filename = g_file_info_get_name (info);
147 		if (old_filename && strlen (old_filename))
148 		{
149 			if (g_str_has_suffix (old_filename, ".gsb"))
150 			{
151 				if (name && g_str_has_prefix (old_filename, name))
152 				{
153 					GDate *date;
154 					gchar *str_date;
155 					gchar *tmp_year;
156 					gchar *tmp_month;
157 					gchar *tmp_day;
158 					size_t long_name;
159 
160 					long_name = strlen (name);
161 					str_date = g_strndup (old_filename+long_name+1, 8);
162 					tmp_year = g_strndup (str_date, 4);
163 					if (g_date_valid_year (utils_str_atoi (tmp_year)) == FALSE)
164 					{
165 						g_free (str_date);
166 						g_free (tmp_year);
167 
168 						continue;
169 					}
170 					tmp_month = g_strndup (str_date+4, 2);
171 					if (g_date_valid_month (utils_str_atoi (tmp_month)) == FALSE)
172 					{
173 						g_free (str_date);
174 						g_free (tmp_year);
175 						g_free (tmp_month);
176 
177 						continue;
178 					}
179 					tmp_day = g_strndup (str_date+6, 2);
180 					if (g_date_valid_day (utils_str_atoi (tmp_day)) == FALSE)
181 					{
182 						g_free (str_date);
183 						g_free (tmp_year);
184 						g_free (tmp_month);
185 						g_free (tmp_day);
186 
187 						continue;
188 					}
189 					date = g_date_new_dmy (utils_str_atoi (tmp_day),
190 										   utils_str_atoi (tmp_month),
191 										   utils_str_atoi (tmp_year));
192 					if (g_date_valid (date) == FALSE)
193 					{
194 						g_date_free (date);
195 						g_free (str_date);
196 						g_free (tmp_year);
197 						g_free (tmp_month);
198 						g_free (tmp_day);
199 
200 						continue;
201 					}
202 					if (g_date_compare (date, first_old_date) < 0)
203 					{
204 						gchar *tmp_filename;
205 
206 						tmp_filename = g_build_filename (backup_path, G_DIR_SEPARATOR_S, old_filename, NULL);
207 						filenames = g_slist_append (filenames, tmp_filename);
208 					}
209 					g_date_free (date);
210 					g_free (str_date);
211 					g_free (tmp_year);
212 					g_free (tmp_month);
213 					g_free (tmp_day);
214 				}
215 			}
216 		}
217 		else
218 		{
219 			continue;
220 		}
221 	}
222 	g_object_unref (direnum);
223 	g_object_unref (dir);
224 	g_free (name);
225 
226 	if (!filenames)
227 	{
228 		g_date_free (first_old_date);
229 
230 		return;
231 	}
232 
233 	dialogue_message ("remove-backup-files", g_slist_length (filenames), gsb_format_gdate (first_old_date));
234 
235 	g_date_free (first_old_date);
236 
237 	iterator = filenames;
238 	while (iterator)
239     {
240 		GFile *file;
241 		gchar *path;
242 
243 		path = iterator->data;
244 
245 		file = g_file_new_for_path (path);
246 		g_file_delete (file, FALSE, NULL);
247 		iterator = iterator->next;
248 	}
249 
250 	g_slist_free_full (filenames, g_free);
251 }
252 
253 /**
254  * teste la validité d'un fichier
255  *
256  * \param const gchar 	filename
257  *
258  * \return TRUE if OK FALSE other
259  **/
gsb_file_test_file(const gchar * filename)260 static gboolean gsb_file_test_file (const gchar *filename)
261  {
262 	gchar* tmp_str1;
263 	gchar* tmp_str2;
264 
265 	if (!filename || !strlen (filename) || !g_file_test (filename, G_FILE_TEST_EXISTS))
266     {
267         tmp_str1 = g_strdup_printf (_("Cannot open file '%s': %s"),
268 									filename,
269 									_("File does not exist"));
270 
271         tmp_str2 = g_strdup_printf (_("Error loading file '%s'"), filename);
272         dialogue_error_hint (tmp_str1, tmp_str2);
273 
274         g_free (tmp_str1);
275         g_free (tmp_str2);
276 
277         return FALSE;
278     }
279     /* check here if it's not a regular file */
280     if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
281     {
282         tmp_str1 = g_strdup_printf (_("%s doesn't seem to be a regular file,\n"
283                                       "please check it and try again."),
284                                     filename);
285         tmp_str2 = g_strdup_printf (_("Error loading file '%s'"),
286                                     filename);
287         dialogue_error_hint (tmp_str1 , tmp_str2);
288 
289         g_free (tmp_str1);
290         g_free (tmp_str2);
291 
292         return (FALSE);
293     }
294 	return TRUE;
295  }
296 
297 /**
298  * ask the name of the file to save it
299  *
300  * \param
301  *
302  * \return a newly allocated string containing the new name
303  **/
gsb_file_dialog_ask_name(const gchar * filename)304 static gchar *gsb_file_dialog_ask_name (const gchar *filename)
305 {
306     gchar *new_name;
307     GtkWidget *dialog;
308     gint result;
309     gchar *tmp_last_directory;
310 
311     dialog = gtk_file_chooser_dialog_new (_("Name the accounts file"),
312 										  GTK_WINDOW (grisbi_app_get_active_window (NULL)),
313 										  GTK_FILE_CHOOSER_ACTION_SAVE,
314 										  "gtk-cancel", GTK_RESPONSE_CANCEL,
315 										  "gtk-save", GTK_RESPONSE_OK,
316 										  NULL);
317 
318     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), gsb_file_get_last_path ());
319     gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
320     gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
321 
322     if (!filename)
323     {
324         gchar* tmp_str;
325 		GrisbiWinEtat *w_etat;
326 
327 		w_etat = (GrisbiWinEtat *) grisbi_win_get_w_etat ();
328 
329         tmp_str = g_strconcat (w_etat->accounting_entity, ".gsb", NULL);
330         gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), tmp_str);
331         g_free (tmp_str);
332     }
333     else
334         gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog), filename);
335 
336     result = gtk_dialog_run (GTK_DIALOG (dialog));
337 
338     switch (result)
339     {
340 	case GTK_RESPONSE_OK :
341 	    new_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
342         tmp_last_directory = utils_files_selection_get_last_directory (GTK_FILE_CHOOSER (dialog), TRUE);
343         gsb_file_update_last_path (tmp_last_directory);
344         g_free (tmp_last_directory);
345 	    gtk_widget_destroy (GTK_WIDGET (dialog));
346 	    break;
347 
348 	default :
349 	    gtk_widget_destroy (GTK_WIDGET (dialog));
350 	    return NULL;
351     }
352 
353     if (!g_strrstr (new_name, "."))
354     {
355         gchar* tmp_str;
356 
357         tmp_str = new_name;
358         new_name = g_strconcat (tmp_str, ".gsb", NULL);
359         g_free (tmp_str);
360     }
361 
362     return new_name;
363 }
364 
365 /**
366  * propose to save the file if changed
367  * if the current file is not changed, return GTK_RESPONSE_NO directly, without dialog
368  *
369  * \param
370  *
371  * \return GTK_RESPONSE_OK to save, GTK_RESPONSE_NO not to save, other to cancel
372  **/
gsb_file_dialog_save(const gchar * filename,gint origine)373 static gint gsb_file_dialog_save (const gchar *filename,
374 								  gint origine)
375 {
376     GtkWidget *dialog;
377     gchar *hint = NULL;
378     gchar *message = NULL;
379     gint result;
380 
381     dialog = gtk_message_dialog_new (GTK_WINDOW (grisbi_app_get_active_window (NULL)),
382 									 GTK_DIALOG_DESTROY_WITH_PARENT,
383 									 GTK_MESSAGE_WARNING,
384 									 GTK_BUTTONS_NONE,
385 									 " ");
386 	switch (origine)
387 	{
388 		case -1:
389 		{
390 			gchar *time_elapsed;
391 			time_t now;
392 			gint difference;
393 
394 			now = time (NULL);
395 			difference = (int) (difftime (now, run.file_modification));
396 			hint = g_strdup_printf (_("Save changes to document '%s' before closing?"),
397 									(filename ? g_path_get_basename(filename) : _("unnamed")));
398 
399 
400 			gtk_dialog_add_buttons (GTK_DIALOG(dialog),
401 									_("Close without saving"), GTK_RESPONSE_NO,
402 									"gtk-cancel", GTK_RESPONSE_REJECT,
403 									"gtk-save", GTK_RESPONSE_OK,
404 									NULL);
405 			if (difference >= 120)
406 			{
407 				time_elapsed = g_strdup_printf (_("%d minutes and %d seconds"), difference / 60, difference % 60);
408 			}
409 			else if (difference >= 60)
410 			{
411 				time_elapsed = g_strdup_printf (_("1 minute and %d seconds"), difference % 60);
412 			}
413 			else
414 			{
415 				time_elapsed = g_strdup_printf (_("%d seconds"), difference);
416 			}
417 			message = g_strdup_printf (_("If you close without saving, all of your changes "
418 										 "since %s will be discarded."),
419 										time_elapsed);
420 			g_free (time_elapsed);
421 
422 
423 			break;
424 		}
425 		default:
426 		{
427 			hint = g_strdup_printf (_("Save changes in '%s' file?"),
428 									(filename ? g_path_get_basename(filename) : _("unnamed")));
429 
430 			gtk_dialog_add_buttons (GTK_DIALOG(dialog),
431 									"gtk-cancel", GTK_RESPONSE_NO,
432 									"gtk-save", GTK_RESPONSE_OK,
433 									NULL);
434 			message = g_strdup("");
435 		}
436 	}
437 	gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
438 	g_object_set (G_OBJECT (dialog), "text", hint, "secondary-text", message, NULL);
439 
440     g_free (message);
441     g_free (hint);
442 
443     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
444 
445     result = gtk_dialog_run (GTK_DIALOG (dialog));
446     gtk_widget_destroy (dialog);
447 
448     return result;
449 }
450 
451 /**
452  * save a backup of the file
453  *
454  * \param
455  *
456  * \return TRUE ok, FALSE problem
457  **/
gsb_file_save_backup(gboolean make_bakup_single_file,gboolean compress_backup)458 static gboolean gsb_file_save_backup (gboolean make_bakup_single_file,
459 									  gboolean compress_backup)
460 {
461     gboolean retour;
462 	gchar *new_filename;
463     const gchar *filename;
464     struct tm *day_time;
465     time_t temps;
466     gchar *name;
467 
468     if (!gsb_file_get_backup_path () || !gsb_file_get_modified ())
469         return FALSE;
470 
471     grisbi_win_status_bar_message (_("Saving backup"));
472 
473 	/* on récupère d'abord le nom du fichier */
474 	filename = grisbi_win_get_filename (NULL);
475     name = g_path_get_basename (filename);
476     if (g_str_has_suffix (name, ".gsb"))
477     {
478         gchar **tab_str;
479 
480         tab_str = g_strsplit (name, ".gsb", 0);
481         if (tab_str[0] && strlen (tab_str[0]))
482         {
483             g_free (name);
484             name = g_strdup (tab_str[0]);
485         }
486         g_strfreev (tab_str);
487     }
488     /* create a filename for the backup :
489      * filename_yyyymmddTmmhhss.gsb */
490     if (make_bakup_single_file)
491     {
492         new_filename =  g_strdup_printf ("%s%s%s_backup.gsb",
493 										 gsb_file_get_backup_path (),
494 										 G_DIR_SEPARATOR_S,
495 										 name);
496     }
497     else
498     {
499         time (&temps);
500         day_time = localtime (&temps);
501         new_filename =  g_strdup_printf ("%s%s%s_%d%02d%02dT%02d%02d%02d.gsb",
502 										 gsb_file_get_backup_path (),
503 										 G_DIR_SEPARATOR_S,
504 										 name,
505 										 day_time->tm_year + 1900,
506 										 day_time->tm_mon + 1,
507 										 day_time->tm_mday,
508 										 day_time->tm_hour,
509 										 day_time->tm_min,
510 										 day_time->tm_sec);
511     }
512 
513     retour = gsb_file_save_save_file (new_filename, compress_backup, 0);
514 
515     g_free (new_filename);
516     g_free (name);
517 
518     grisbi_win_status_bar_message (_("Done"));
519 
520     return (retour);
521 }
522 
523 /**
524  * called every x minutes defined by user
525  * to save a backup of the file
526  *
527  * \param null
528  *
529  * \return TRUE to continue the timeout, FALSE to stop the timeout
530  **/
gsb_file_automatic_backup(gpointer p_conf)531 static gboolean gsb_file_automatic_backup (gpointer p_conf)
532 {
533 	GrisbiAppConf *a_conf;
534 
535 	devel_debug (NULL);
536 	a_conf = (GrisbiAppConf *) p_conf;
537 
538     if (!a_conf->make_backup_every_minutes)
539 	/* stop the timeout */
540         return FALSE;
541 
542     /* we save only if there is a nb of minutes, but don't stop the timer if not */
543     if (a_conf->make_backup_nb_minutes)
544         gsb_file_save_backup (a_conf->make_bakup_single_file, a_conf->compress_backup);
545 
546     return TRUE;
547 }
548 
549 /**
550  * save the file
551  *
552  * \param origine 0 from gsb_file_save (menu), -1 from gsb_file_close, -2 from gsb_file_save_as
553  *
554  * \return TRUE if ok, FALSE if problem
555  **/
gsb_file_save_file(gint origine)556 static gboolean gsb_file_save_file (gint origine)
557 {
558     gint result = 0;
559     gchar *nouveau_nom_enregistrement;
560 	gchar *filename;
561 	GrisbiAppConf *a_conf;
562 
563     devel_debug_int (origine);
564 
565 	/* on regarde si il y a quelque chose à sauvegarder sauf pour "sauvegarder sous" */
566 	if ((!gsb_file_get_modified () && origine != -2)
567         ||
568         !gsb_data_account_get_accounts_amount ())
569     {
570         notice_debug ("nothing done in gsb_file_save_file");
571         return (TRUE);
572     }
573 
574 	a_conf = grisbi_app_get_a_conf ();
575 
576 	/* on récupère le nom du fichier */
577 	filename = g_strdup (grisbi_win_get_filename (NULL));
578 
579 	/* on vérifie que le fichier n'est pas locké si il l'est on sort */
580     if (etat.fichier_deja_ouvert && !a_conf->force_enregistrement && origine != -2)
581     {
582         gchar* tmp_str1;
583         gchar* tmp_str2;
584 
585         tmp_str1 = g_strdup_printf(_("Grisbi was unable to save this file because it is locked.\n"
586 									 "Please save it with another name or activate the \"%s\" "
587                                      "option in preferences."),
588                                    _("Force saving of locked files"));
589         tmp_str2 = g_strdup_printf(_("Can not save file \"%s\""), filename);
590         dialogue_error_hint (tmp_str1, tmp_str2);
591         g_free (tmp_str1);
592         g_free (tmp_str2);
593 
594         return (FALSE);
595     }
596 
597     /* on commence par demander si on sauvegarde ou pas sauf pour "sauvegarder sous" */
598     if (!a_conf->sauvegarde_auto && origine != -2)
599     {
600         result = gsb_file_dialog_save (filename, origine);
601         if (result == GTK_RESPONSE_NO)
602 		{
603 			gsb_file_set_modified (FALSE);
604             return (TRUE);
605 		}
606 		else if (result != GTK_RESPONSE_OK)
607 		{
608 			//~ gsb_file_set_modified (FALSE);
609             return (FALSE);
610 		}
611     }
612 
613     /* si le fichier de comptes n'a pas de nom ou si on enregistre sous un nouveau nom */
614     /*     c'est ici */
615     if (!filename || origine == -2)
616         nouveau_nom_enregistrement = gsb_file_dialog_ask_name (filename);
617     else
618         nouveau_nom_enregistrement = g_strdup (filename);
619 
620     if (!nouveau_nom_enregistrement)
621         return FALSE;
622 
623     /* make backup before saving if asked */
624     if (a_conf->sauvegarde_fermeture)
625         gsb_file_save_backup (a_conf->make_bakup_single_file, a_conf->compress_backup);
626 
627     /*  on a maintenant un nom de fichier et on sait qu'on peut sauvegarder */
628     grisbi_win_status_bar_message (_("Saving file"));
629 
630     result = gsb_file_save_save_file (nouveau_nom_enregistrement, a_conf->compress_file, 0);
631 
632     if (result)
633     {
634 		grisbi_win_set_filename (NULL, nouveau_nom_enregistrement);
635 
636 		/* on ajoute un item au menu recent_file si origine = -2 */
637 		if (origine == -2)
638 			utils_files_append_name_to_recent_array (nouveau_nom_enregistrement);
639 
640 		/* saving was right, so unlock the last name */
641         gsb_file_util_modify_lock (filename, FALSE);
642 
643         /* and lock the new name */
644         gsb_file_util_modify_lock (nouveau_nom_enregistrement, TRUE);
645 
646         /* update variables */
647         etat.fichier_deja_ouvert = 0;
648         gsb_file_set_modified (FALSE);
649         grisbi_win_set_window_title (gsb_gui_navigation_get_current_account ());
650 
651 		/* Si nettoyage des fichiers de backup on le fait ici */
652 		if (a_conf->remove_backup_files)
653 		{
654 			GrisbiWinRun *w_run;
655 
656 			w_run = (GrisbiWinRun *) grisbi_win_get_w_run ();
657 			if (!w_run->remove_backup_files)
658 			{
659 				gsb_file_remove_old_backup (nouveau_nom_enregistrement,a_conf->remove_backup_months);
660 				w_run->remove_backup_files = TRUE;
661 			}
662 		}
663     }
664 
665 	g_free (filename);
666 	g_free (nouveau_nom_enregistrement);
667     grisbi_win_status_bar_message (_("Done"));
668 
669     return (result);
670 }
671 
672 /******************************************************************************/
673 /* Public Methods                                                             */
674 /******************************************************************************/
675 /**
676  * come here to finish to create the new file
677  * at this time, categories and currencies must created
678  * this part will just launch the assistant to create a new account
679  * a finish the initialisation to lauch grisbi
680  *
681  * \param
682  *
683  * \return FALSE
684  **/
gsb_file_new_finish(void)685 gboolean gsb_file_new_finish (void)
686 {
687 	GrisbiWinRun *w_run;
688 
689     /* create the first account */
690     if (!gsb_assistant_account_run ())
691     {
692         init_variables ();
693         return FALSE;
694     }
695 
696     /* init the gui */
697     grisbi_win_new_file_gui ();
698 
699     mise_a_jour_accueil (TRUE);
700     gsb_gui_navigation_set_selection (GSB_HOME_PAGE, -1, 0);
701 
702 	/* sensibilise les préférences */
703 	w_run = (GrisbiWinRun *) grisbi_win_get_w_run ();
704 	w_run->file_is_loading = TRUE;
705 
706     gsb_file_set_modified (TRUE);
707     return FALSE;
708 }
709 
710 /**
711  * called by file->open
712  * open a new file
713  *
714  * \param
715  *
716  * \return FALSE
717  **/
gsb_file_open_menu(void)718 gboolean gsb_file_open_menu (void)
719 {
720     GtkWidget *selection_fichier;
721     GtkFileFilter * filter;
722     gboolean result = FALSE;
723     gchar *tmp_last_directory;
724 	gchar *filename;
725 
726     selection_fichier = gtk_file_chooser_dialog_new (_("Open an accounts file"),
727 												     GTK_WINDOW (grisbi_app_get_active_window (NULL)),
728 												     GTK_FILE_CHOOSER_ACTION_OPEN,
729 												     "gtk-cancel", GTK_RESPONSE_CANCEL,
730 												     "gtk-open", GTK_RESPONSE_OK,
731 												     NULL);
732 
733     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (selection_fichier), gsb_file_get_last_path ());
734     gtk_window_set_position (GTK_WINDOW (selection_fichier), GTK_WIN_POS_CENTER_ON_PARENT);
735 
736     filter = gtk_file_filter_new ();
737     gtk_file_filter_set_name (filter, _("Grisbi files (*.gsb)"));
738     gtk_file_filter_add_pattern (filter, "*.gsb");
739     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (selection_fichier), filter);
740     gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (selection_fichier), filter);
741 
742     filter = gtk_file_filter_new ();
743     gtk_file_filter_set_name (filter, _("All files"));
744     gtk_file_filter_add_pattern (filter, "*");
745     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (selection_fichier), filter);
746 
747     switch (gtk_dialog_run (GTK_DIALOG (selection_fichier)))
748     {
749 		case GTK_RESPONSE_OK:
750 			if (gsb_file_close())
751 			{
752 				gtk_widget_hide (selection_fichier);
753 				filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (selection_fichier));
754 
755 				tmp_last_directory = utils_files_selection_get_last_directory (GTK_FILE_CHOOSER (selection_fichier), TRUE);
756 				gsb_file_update_last_path (tmp_last_directory);
757 				g_free (tmp_last_directory);
758 				result = gsb_file_open_file (filename);
759 				g_free (filename);
760 			}
761 			break;
762 		  default:
763 			break;
764     }
765 
766     tmp_last_directory = utils_files_selection_get_last_directory (GTK_FILE_CHOOSER (selection_fichier), TRUE);
767     gsb_file_update_last_path (tmp_last_directory);
768     g_free (tmp_last_directory);
769     gtk_widget_destroy (selection_fichier);
770 
771     return result;
772 }
773 
774 /**
775  * init the variable last_path_used with the path given in param
776  *
777  * \param last_path
778  *
779  * \return
780  **/
gsb_file_init_last_path(const gchar * last_path)781 void gsb_file_init_last_path (const gchar *last_path)
782 {
783     devel_debug (last_path);
784 
785     if (last_path && strlen (last_path))
786     {
787         if (last_path_used)
788             g_free (last_path_used);
789 
790         last_path_used = my_strdup (last_path);
791     }
792 }
793 
794 /**
795  * update the variable last_path_used with the path given in param
796  *
797  * \param last_path
798  *
799  * \return
800  **/
gsb_file_update_last_path(const gchar * last_path)801 void gsb_file_update_last_path (const gchar *last_path)
802 {
803     devel_debug (last_path);
804 
805     if (last_path && strlen (last_path))
806     {
807         if (last_path_used)
808             g_free (last_path_used);
809         last_path_used = my_strdup (last_path);
810     }
811 }
812 
813 /**
814  * the last_path_used is local variable,
815  * that return the content of that variable
816  *
817  * \param
818  *
819  * \return a const gchar, the last path used in grisbi
820  **/
gsb_file_get_last_path(void)821 const gchar *gsb_file_get_last_path (void)
822 {
823     return last_path_used;
824 }
825 
826 /**
827  * get the backup path
828  *
829  * \param
830  *
831  * \return a const gchar with the backup path
832  **/
gsb_file_get_backup_path(void)833 const gchar *gsb_file_get_backup_path (void)
834 {
835     return backup_path;
836 }
837 
838 /**
839  * set the backup path
840  *
841  * \param bakcup path
842  *
843  * \return
844  **/
gsb_file_set_backup_path(const gchar * path)845 void gsb_file_set_backup_path (const gchar *path)
846 {
847 	/* first free backup_path */
848 	if (backup_path)
849 		g_free (backup_path);
850 
851     if (path == NULL || strlen (path) == 0)
852         backup_path = my_strdup (gsb_dirs_get_user_data_dir ());
853     else
854         backup_path = my_strdup (path);
855 
856     if (!g_file_test (path, G_FILE_TEST_EXISTS))
857     {
858         utils_files_create_XDG_dir ();
859     }
860 }
861 
862 /**
863  * open a new grisbi file, don't check anything about another opened file that must
864  * have been done before
865  *
866  * \para filename the name of the file
867  *
868  * \return TRUE ok, FALSE problem
869  **/
gsb_file_open_file(const gchar * filename)870 gboolean gsb_file_open_file (const gchar *filename)
871 {
872 	GrisbiAppConf *a_conf;
873 
874 	devel_debug (filename);
875 	a_conf = grisbi_app_get_a_conf ();
876 
877 	if (!gsb_file_test_file (filename))
878 	{
879 		grisbi_win_stack_box_show (NULL, "accueil_page");
880 		return FALSE;
881 	}
882 
883     grisbi_win_status_bar_wait (TRUE);
884     grisbi_win_status_bar_message (_("Loading accounts"));
885 
886 	/* initialise les variables d'état */
887     init_variables ();
888 
889 	/* try to load the file */
890     /* FIXME:BUG under Windows: for unknwon reason yet filename is cleared
891      * when returning from gsb_file_load_open_file!
892      * making application crashes!*/
893 
894     if (gsb_file_load_open_file (filename))
895     {
896         /* the file has been opened succesfully */
897         /* on met à jour le nom du fichier */
898         grisbi_win_set_filename (NULL, filename);
899 
900 		/* mark the file as opened */
901         gsb_file_util_modify_lock (filename, TRUE);
902 
903         /* we make a backup if necessary */
904         if (a_conf->sauvegarde_demarrage)
905         {
906 			gsb_file_save_backup (a_conf->make_bakup_single_file, a_conf->compress_backup);
907         }
908     }
909     else
910     {
911 #ifdef HAVE_SSL
912 		gchar *tmp_str1;
913 		gchar *tmp_str2;
914 		GrisbiWinRun *w_run;
915 #endif
916 
917 		/* Loading failed. */
918 		grisbi_win_status_bar_message (_("Failed to load accounts"));
919 
920 #ifdef HAVE_SSL
921 		w_run = grisbi_win_get_w_run ();
922         if (w_run->old_version)
923         {
924             dialogue_error_hint (_("The version of your file is less than 0.6. "
925                                    "This file can not be imported by Grisbi."),
926                                  _("Version of Grisbi file too old :"));
927             grisbi_win_status_bar_stop_wait (TRUE);
928 
929             return FALSE;
930         }
931 
932 		tmp_str1 = g_strdup_printf (_("Error loading file '%s'"), filename);
933 
934         if (a_conf->sauvegarde_demarrage || a_conf->sauvegarde_fermeture || a_conf->make_backup_every_minutes)
935         {
936             tmp_str2 = g_strdup_printf (_("Grisbi was unable to load file. You should find the last "
937 										  "backups in '%s', they are saved with date and time into "
938 										  "their name so you should find easily the last backup "
939 										  "saved.\n"
940 										  "Please contact the Grisbi's team on devel@listes.grisbi.org "
941 										  "to find what happened to you current file."),
942 										gsb_file_get_backup_path ());
943         }
944         else
945         {
946             if (gsb_file_get_backup_path ())
947                 tmp_str2 = g_strdup_printf ( _("Grisbi was unable to load file and the backups seem not to "
948 											   "be activated... This is a bad thing.\nYour backup path is '%s', "
949 											   "try to find if earlier you had some backups in there ?\n"
950 											   "Please contact the Grisbi's team on devel@listes.grisbi.org "
951 											   "to find what happened to you current file."),
952 											gsb_file_get_backup_path ());
953             else
954                 tmp_str2 = my_strdup (_("Grisbi was unable to load file and the backups seem not "
955 										"to be activated... This is a bad thing.\n"
956 										"Please contact the Grisbi's team on "
957 										"devel@listes.grisbi.org to find what happened to you "
958 										"current file."));
959 		}
960 		dialogue_error_hint (tmp_str2, tmp_str1);
961 		g_free (tmp_str1);
962 		g_free (tmp_str2);
963 #endif
964 		grisbi_win_status_bar_stop_wait (TRUE);
965 		grisbi_win_stack_box_show (NULL, "accueil_page");
966 		return FALSE;
967     }
968 
969     /* ok, here the file or backup is loaded */
970     grisbi_win_status_bar_message (_("Checking schedulers"));
971 
972 	/* create the archives store data, ie the transaction which will replace the archive in
973      * the list of transactions */
974     gsb_data_archive_store_create_list ();
975 
976     /* create all the gui */
977     grisbi_win_new_file_gui ();
978 
979 	/* check the amounts of all the accounts */
980     grisbi_win_status_bar_message (_("Checking amounts"));
981 	gsb_data_account_set_all_limits_of_balance ();
982 
983     /* set Grisbi title */
984     grisbi_win_set_window_title (-1);
985 
986     /* for now, the flag for modification of the file is ok, but the menu couldn't be set
987      * as sensitive/unsensitive so do it now */
988     gsb_file_set_modified (gsb_file_get_modified ());
989 
990     grisbi_win_status_bar_message (_("Done"));
991     grisbi_win_status_bar_stop_wait (TRUE);
992 
993     /* go to the home page */
994     gsb_gui_navigation_set_selection (GSB_HOME_PAGE, -1, 0);
995 
996     /* set the focus to the selection tree at left */
997     gtk_widget_grab_focus (gsb_gui_navigation_get_tree_view ());
998 
999     return TRUE;
1000 }
1001 
1002 /**
1003  * Perform the "Save" feature in menu
1004  *
1005  * \return TRUE on success.  FALSE otherwise.
1006  */
gsb_file_save(void)1007 gboolean gsb_file_save (void)
1008 {
1009     return gsb_file_save_file (0);
1010 }
1011 
1012 /**
1013  * Perform the "Save as" feature in menu
1014  *
1015  * \return TRUE on success.  FALSE otherwise.
1016  */
gsb_file_save_as(void)1017 gboolean gsb_file_save_as (void)
1018 {
1019     return gsb_file_save_file (-2);
1020 }
1021 
1022 /**
1023  * called when the user select the backup every x minutes
1024  *
1025  * \param checkbutton
1026  * \param null
1027  *
1028  * \return FALSE
1029  **/
gsb_file_automatic_backup_start(GtkWidget * checkbutton,gpointer null)1030 gboolean gsb_file_automatic_backup_start (GtkWidget *checkbutton,
1031 										  gpointer null)
1032 {
1033 	GrisbiAppConf *a_conf;
1034 
1035 	a_conf = grisbi_app_get_a_conf ();
1036 	devel_debug_int (a_conf->make_backup_every_minutes);
1037 
1038     /* if there is already a timeout, we remove it */
1039     if (id_timeout)
1040     {
1041 		g_source_remove (id_timeout);
1042 		id_timeout = 0;
1043     }
1044 
1045     /* launch the timeout only if active and if there is some minutes */
1046     if (a_conf->make_backup_every_minutes && a_conf->make_backup_nb_minutes)
1047 		id_timeout = g_timeout_add_seconds (a_conf->make_backup_nb_minutes * 60,
1048 											gsb_file_automatic_backup,
1049 											a_conf);
1050     return FALSE;
1051 }
1052 
1053 /**
1054  * called when the user change the interval of automatic backup
1055  *
1056  * \param spinbutton
1057  * \param null
1058  *
1059  * \return FALSE
1060  **/
gsb_file_automatic_backup_change_time(GtkWidget * spinbutton,gpointer null)1061 gboolean gsb_file_automatic_backup_change_time (GtkWidget *spinbutton,
1062 												gpointer null)
1063 {
1064 	GrisbiAppConf *a_conf;
1065 
1066 	a_conf = grisbi_app_get_a_conf ();
1067 	devel_debug_int (a_conf->make_backup_every_minutes);
1068 
1069     /* if there is already a timeout, we stop it */
1070     if (id_timeout)
1071     {
1072 	g_source_remove (id_timeout);
1073 	id_timeout = 0;
1074     }
1075 
1076     /* set a new timeout only if there is an interval */
1077     if (a_conf->make_backup_nb_minutes)
1078 	id_timeout = g_timeout_add_seconds (a_conf->make_backup_nb_minutes * 60,
1079 										gsb_file_automatic_backup,
1080 										a_conf);
1081 
1082     return FALSE;
1083 }
1084 
1085 /**
1086  * close the file
1087  * if no file loaded or no change, directly return TRUE
1088  *
1089  * \param
1090  *
1091  * \return FALSE if problem, TRUE if ok
1092  **/
gsb_file_close(void)1093 gboolean gsb_file_close (void)
1094 {
1095 	gchar *filename;
1096 	GrisbiAppConf *a_conf;
1097 
1098 	devel_debug (NULL);
1099     if (!assert_account_loaded ())
1100 	{
1101         return TRUE;
1102 	}
1103 
1104 	a_conf = grisbi_app_get_a_conf ();
1105 
1106 	/* on récupère le nom du fichier */
1107 	filename = g_strdup (grisbi_win_get_filename (NULL));
1108 
1109 	if (gsb_file_get_modified ())
1110     {
1111         /* try to save */
1112 	    if (!gsb_file_save_file (-1))
1113             return FALSE;
1114     }
1115     else if (a_conf->sauvegarde_auto && filename)
1116     {
1117         /* try to save */
1118 	    if (!gsb_file_save_file (-1))
1119             return FALSE;
1120     }
1121 
1122     if (!gsb_file_get_modified ())
1123     {
1124 	     /* remove the lock */
1125 	    if (!etat.fichier_deja_ouvert
1126 			&&
1127 			gsb_data_account_get_accounts_amount ()
1128 			&&
1129 			filename)
1130 		{
1131 			gsb_file_util_modify_lock (filename, FALSE);
1132 		}
1133 
1134 	    /* free all the variables */
1135 		etats_gtktable_free_table_etat (); /* set table_etat = NULL: fix crash loading a multiple accounts files */
1136  	    init_variables ();
1137         grisbi_win_free_general_vbox ();
1138         gsb_account_property_clear_config ();
1139 		grisbi_win_set_filename (NULL, NULL);
1140 
1141         grisbi_win_set_window_title (-1);
1142 
1143         /* unsensitive the necessaries menus */
1144         gsb_menu_set_menus_with_file_sensitive (FALSE);
1145         grisbi_win_menu_move_to_acc_delete ();
1146 
1147 		g_free (filename);
1148 	    return TRUE;
1149     }
1150 
1151     return FALSE;
1152 }
1153 
1154 /**
1155  * set or unset the modified flag (run structure)
1156  * and sensitive or not the menu to save the file
1157  *
1158  * \param modif TRUE to set the modified flag, FALSE to unset
1159  *
1160  * \return
1161  */
gsb_file_set_modified(gboolean modified)1162 void gsb_file_set_modified (gboolean modified)
1163 {
1164 /*     devel_debug_int (modified);  */
1165 
1166     /* If no file is loaded, do not change menu items. */
1167 	if (!gsb_data_account_get_accounts_amount ())
1168 		return;
1169 
1170 	if (modified)
1171     {
1172 		/* modification pour gerer la non modification par la recherche dans la liste des operations */
1173 		run.file_modification = time (NULL);
1174         gsb_menu_gui_sensitive_win_menu_item ("save", TRUE);
1175     }
1176     else
1177     {
1178         run.file_modification = 0;
1179         gsb_menu_gui_sensitive_win_menu_item ("save", FALSE);
1180     }
1181 }
1182 
1183 /**
1184  * Tell if the current file has been modified or not
1185  *
1186  * \return TRUE if modified, FALSE otherwise
1187  */
gsb_file_get_modified(void)1188 gboolean gsb_file_get_modified (void)
1189 {
1190     if (run.file_modification == 0)
1191         return FALSE;
1192     else
1193         return TRUE;
1194 }
1195 
1196 /**
1197  * free the last_path path
1198  *
1199  * \param
1200  *
1201  * \return
1202  **/
gsb_file_free_last_path(void)1203 void gsb_file_free_last_path (void)
1204 {
1205 	if (last_path_used)
1206     {
1207 		g_free (last_path_used);
1208 		last_path_used = NULL;
1209     }
1210 }
1211 
1212 /**
1213  * free the backup path
1214  *
1215  * \param
1216  *
1217  * \return
1218  **/
gsb_file_free_backup_path(void)1219 void gsb_file_free_backup_path (void)
1220 {
1221 	if (backup_path)
1222     {
1223 		g_free (backup_path);
1224 		backup_path = NULL;
1225     }
1226 }
1227 
1228 /**
1229  * copy an old grisbi file
1230  *
1231  * \param filename the name of the file
1232  *
1233  * \return
1234  **/
gsb_file_copy_old_file(const gchar * filename)1235 void gsb_file_copy_old_file (const gchar *filename)
1236 {
1237     if (g_str_has_suffix (filename, ".gsb"))
1238     {
1239         GFile *file_ori;
1240         GFile *file_copy;
1241         GError *error = NULL;
1242 		gchar *copy_old_filename;
1243 		gchar *tmp_str;
1244 
1245         copy_old_filename = g_path_get_basename (filename);
1246 		tmp_str = copy_old_filename;
1247         copy_old_filename = gsb_string_remplace_string (copy_old_filename, ".gsb", "-old-version.gsb");
1248 		g_free (tmp_str);
1249 		tmp_str = copy_old_filename;
1250         copy_old_filename = g_build_filename (gsb_dirs_get_user_data_dir (), copy_old_filename, NULL);
1251 		g_free (tmp_str);
1252 
1253 		file_ori = g_file_new_for_path (filename);
1254         file_copy = g_file_new_for_path (copy_old_filename);
1255 
1256 		if (!g_file_copy (file_ori, file_copy, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error))
1257         {
1258             dialogue_error (error->message);
1259             g_error_free (error);
1260         }
1261 		else
1262 		{
1263 			tmp_str = g_strdup_printf (_("The original file was saved saved as:\n"
1264 										 "\"%s\"."),
1265 									   copy_old_filename);
1266 
1267 			dialogue_warning (tmp_str);
1268 			g_free (tmp_str);
1269 		}
1270 		g_free (copy_old_filename);
1271 		g_object_unref (file_ori);
1272 		g_object_unref (file_copy);
1273     }
1274 }
1275 /**
1276  * Fonction de fermeture de grisbi sans appeler la fonction init_variables ().
1277  * Demandera une clarification de la libération des variables.
1278  *
1279  * \param
1280  *
1281  * \return
1282  **/
gsb_file_quit(void)1283 gboolean gsb_file_quit (void)
1284 {
1285 	gchar *filename;
1286 	GrisbiAppConf *a_conf;
1287 
1288 	devel_debug (NULL);
1289     if (!assert_account_loaded ())
1290 	{
1291         return TRUE;
1292 	}
1293 
1294 	a_conf = grisbi_app_get_a_conf ();
1295 
1296 	/* on récupère le nom du fichier */
1297 	filename = g_strdup (grisbi_win_get_filename (NULL));
1298 
1299 	if (gsb_file_get_modified ())
1300     {
1301         /* try to save */
1302 	    if (!gsb_file_save_file (-1))
1303             return FALSE;
1304     }
1305     else if (a_conf->sauvegarde_auto && filename)
1306     {
1307         /* try to save */
1308 	    if (!gsb_file_save_file (-1))
1309             return FALSE;
1310     }
1311 
1312     if (!gsb_file_get_modified ())
1313     {
1314 	     /* remove the lock */
1315 	    if (!etat.fichier_deja_ouvert
1316 			&&
1317 			gsb_data_account_get_accounts_amount ()
1318 			&&
1319 			filename)
1320 		{
1321 			gsb_file_util_modify_lock (filename, FALSE);
1322 		}
1323 
1324 	    /* free all the variables */
1325 		etats_gtktable_free_table_etat (); /* set table_etat = NULL: fix crash loading a multiple accounts files */
1326         grisbi_win_free_general_vbox ();
1327         gsb_account_property_clear_config ();
1328 		grisbi_win_set_filename (NULL, NULL);
1329 
1330         grisbi_win_set_window_title (-1);
1331         grisbi_win_menu_move_to_acc_delete ();
1332 
1333 		g_free (filename);
1334 	    return TRUE;
1335     }
1336 
1337     return FALSE;
1338 }
1339 
1340 /**
1341  *
1342  *
1343  * \param
1344  *
1345  * \return
1346  **/
1347 /* Local Variables: */
1348 /* c-basic-offset: 4 */
1349 /* End: */
1350