LCOV - code coverage report
Current view: top level - libgnucash/app-utils - gnc-state.c (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 0.0 % 122 0
Test Date: 2026-11-02 18:19:43 Functions: 0.0 % 5 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /********************************************************************\
       2              :  * file-utils.c -- simple file utilities                            *
       3              :  * Copyright (C) 1997 Robin D. Clark <rclark@cs.hmc.edu>            *
       4              :  * Copyright (C) 1998 Rob Browning                                  *
       5              :  * Copyright (C) 1998-2000 Linas Vepstas <linas@linas.org>          *
       6              :  *                                                                  *
       7              :  * This program is free software; you can redistribute it and/or    *
       8              :  * modify it under the terms of the GNU General Public License as   *
       9              :  * published by the Free Software Foundation; either version 2 of   *
      10              :  * the License, or (at your option) any later version.              *
      11              :  *                                                                  *
      12              :  * This program is distributed in the hope that it will be useful,  *
      13              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      14              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      15              :  * GNU General Public License for more details.                     *
      16              :  *                                                                  *
      17              :  * You should have received a copy of the GNU General Public License*
      18              :  * along with this program; if not, write to the Free Software      *
      19              :  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        *
      20              : \********************************************************************/
      21              : 
      22              : #include <config.h>
      23              : 
      24              : #include <glib.h>
      25              : //#include <glib/gstdio.h>
      26              : //#include <errno.h>
      27              : 
      28              : #include "gnc-state.h"
      29              : //#include "gnc-engine.h"
      30              : #include "gnc-filepath-utils.h"
      31              : #include "gnc-gkeyfile-utils.h"
      32              : #include "gnc-uri-utils.h"
      33              : #include "qof.h"
      34              : 
      35              : /* This static indicates the debugging module that this .o belongs to.  */
      36              : static QofLogModule log_module = G_LOG_DOMAIN;
      37              : 
      38              : /* Absolute path to the state file for the current book
      39              :  * Before 2.4.1, this file didn't have an extension.
      40              :  * The code will look for such pre 2.4.0 file if no post 2.4.1
      41              :  * version is found. If there is an old style file, save the
      42              :  * name here as well. The old style state file will then be
      43              :  * converted into a new style one the next time state is saved.
      44              :  */
      45              : static gchar* state_file_name = NULL;
      46              : static gchar* state_file_name_pre_241 = NULL;
      47              : /* State file data for current book */
      48              : static GKeyFile *state_file = NULL;
      49              : 
      50              : /* Determine which file name to use for the state file. This name is based
      51              :  * the current book's uri and guid.
      52              :  *
      53              :  * The state files will be searched for in the books directory in GnuCash'
      54              :  * private configuration directory. This configuration directory is
      55              :  * platform dependent and can be overridden with environment variable
      56              :  * DOT_GNUCASH_DIR. On linux for example this is ~/.gnucash by default.
      57              :  *
      58              :  * The URL is used to compute the base name of the state file and the
      59              :  * guid is used to differentiate when the user has multiple data files
      60              :  * with the same name.
      61              :  *
      62              :  * As of GnuCash 2.4.1 state files will have their own extension to
      63              :  * differentiate them from data files saved by the user. New state
      64              :  * files will always be created with such an extension. But GnuCash
      65              :  * will continue to search for state files without an extension if
      66              :  * no proper state file with extension is found. */
      67              : 
      68              : 
      69              : static void
      70            0 : gnc_state_set_base (const QofSession *session)
      71              : {
      72            0 :     gchar *basename, *original = NULL, *filename, *file_guid;
      73            0 :     gchar *sf_extension = NULL;
      74              :     const gchar *uri;
      75              :     gchar guid_string[GUID_ENCODING_LENGTH+1];
      76              :     QofBook *book;
      77              :     const GncGUID *guid;
      78            0 :     GKeyFile *key_file = NULL;
      79              :     gint i;
      80              : 
      81              :     /* Reset filenames possibly found in a previous run */
      82            0 :     g_free (state_file_name);
      83            0 :     g_free (state_file_name_pre_241);
      84            0 :     state_file_name = NULL;
      85            0 :     state_file_name_pre_241 = NULL;
      86              : 
      87            0 :     uri = qof_session_get_url (session);
      88            0 :     ENTER("session %p (%s)", session, uri ? uri : "(null)");
      89            0 :     if (!strlen (uri))
      90              :     {
      91            0 :         LEAVE("no uri, nothing to do");
      92            0 :         return;
      93              :     }
      94              : 
      95              :     /* Get the book GncGUID */
      96            0 :     book = qof_session_get_book(session);
      97            0 :     guid = qof_entity_get_guid(QOF_INSTANCE(book));
      98            0 :     guid_to_string_buff(guid, guid_string);
      99              : 
     100            0 :     if (gnc_uri_targets_local_fs (uri))
     101              :     {
     102              :         /* The book_uri is a true file, use its basename. */
     103            0 :         gchar *path = gnc_uri_get_path (uri);
     104            0 :         basename = g_path_get_basename (path);
     105            0 :         g_free (path);
     106              :     }
     107              :     else
     108              :     {
     109              :         /* The book_uri is composed of database connection parameters. */
     110            0 :         gchar* scheme = NULL;
     111            0 :         gchar* host = NULL;
     112            0 :         gchar* dbname = NULL;
     113            0 :         gchar* username = NULL;
     114            0 :         gchar* password = NULL;
     115            0 :         gint portnum = 0;
     116            0 :         gnc_uri_get_components (uri, &scheme, &host, &portnum,
     117              :                                 &username, &password, &dbname);
     118              : 
     119            0 :         basename = g_strjoin ("_", scheme, host, username, dbname, NULL);
     120            0 :         g_free (scheme);
     121            0 :         g_free (host);
     122            0 :         g_free (username);
     123            0 :         g_free (password);
     124            0 :         g_free (dbname);
     125              :     }
     126              : 
     127            0 :     DEBUG ("Basename %s", basename);
     128            0 :     original = gnc_build_book_path (basename);
     129            0 :     g_free (basename);
     130            0 :     DEBUG ("Original %s", original);
     131              : 
     132            0 :     sf_extension = g_strdup (STATE_FILE_EXT);
     133            0 :     i = 1;
     134              :     while (1)
     135              :     {
     136            0 :         if (i == 1)
     137            0 :             filename = g_strconcat (original, sf_extension, NULL);
     138              :         else
     139            0 :             filename = g_strdup_printf ("%s_%d%s", original, i, sf_extension);
     140            0 :         DEBUG ("Trying %s", filename);
     141            0 :         key_file = gnc_key_file_load_from_file (filename, TRUE, FALSE, NULL);
     142            0 :         DEBUG ("Result %p", key_file);
     143              : 
     144            0 :         if (!key_file)
     145              :         {
     146            0 :             DEBUG ("No key file by that name");
     147            0 :             if (g_strcmp0 (sf_extension, STATE_FILE_EXT) == 0)
     148              :             {
     149            0 :                 DEBUG ("Trying old state file names for compatibility");
     150            0 :                 i = 1;
     151            0 :                 g_free (sf_extension);
     152            0 :                 sf_extension = g_strdup ("");
     153              : 
     154              :                 /* Regardless of whether or not an old state file is found,
     155              :                  * the currently tested name should be used for the future
     156              :                  * state file.
     157              :                  */
     158            0 :                 state_file_name = filename;
     159            0 :                 continue;
     160              :             }
     161              : 
     162              :             /* No old style file found. We'll return with the new file name
     163              :              * we set earlier, and no existing key file. */
     164            0 :             g_free (filename);
     165            0 :             break;
     166              :         }
     167              : 
     168            0 :         file_guid = g_key_file_get_string (key_file,
     169              :                                            STATE_FILE_TOP, STATE_FILE_BOOK_GUID,
     170              :                                            NULL);
     171            0 :         DEBUG ("File GncGUID is %s", file_guid ? file_guid : "<not found>");
     172            0 :         if (g_strcmp0 (guid_string, file_guid) == 0)
     173              :         {
     174            0 :             DEBUG ("Matched !!!");
     175              :             /* Save the found file for later use. Which name to save to
     176              :              * depends on whether it was an old or new style file name
     177              :              */
     178            0 :             if (g_strcmp0 (sf_extension, STATE_FILE_EXT) == 0)
     179            0 :                 state_file_name = filename;
     180              :             else
     181            0 :                 state_file_name_pre_241 = filename;
     182              : 
     183            0 :             g_free (file_guid);
     184            0 :             break;
     185              :         }
     186            0 :         DEBUG ("Clean up this pass");
     187            0 :         g_free (file_guid);
     188            0 :         g_key_file_free (key_file);
     189            0 :         g_free (filename);
     190            0 :         i++;
     191              :     }
     192              : 
     193            0 :     DEBUG("Clean up");
     194            0 :     g_free(sf_extension);
     195            0 :     g_free(original);
     196            0 :     if (key_file != NULL)
     197            0 :         g_key_file_free (key_file);
     198              : 
     199            0 :     LEAVE ();
     200              : }
     201              : 
     202            0 : GKeyFile *gnc_state_load (const QofSession *session)
     203              : {
     204              :     /* Drop possible previous state_file first */
     205            0 :     if (state_file)
     206              :     {
     207            0 :         g_key_file_free (state_file);
     208            0 :         state_file = NULL;
     209              :     }
     210              : 
     211            0 :     gnc_state_set_base (session);
     212              : 
     213            0 :     if (state_file_name_pre_241)
     214            0 :         state_file = gnc_key_file_load_from_file (state_file_name_pre_241,
     215              :                      TRUE, TRUE, NULL);
     216            0 :     else if (state_file_name)
     217            0 :         state_file = gnc_key_file_load_from_file (state_file_name,
     218              :                      TRUE, TRUE, NULL);
     219              : 
     220            0 :     return gnc_state_get_current ();
     221              : }
     222              : 
     223            0 : void gnc_state_save (const QofSession *session)
     224              : {
     225            0 :     GError *error = NULL;
     226              : 
     227            0 :     if (!strlen (qof_session_get_url(session)))
     228              :     {
     229            0 :         DEBUG("No file associated with session - skip state saving");
     230            0 :         return;
     231              :     }
     232              : 
     233            0 :     gnc_state_set_base (session);
     234              : 
     235              :     /* Write it all out to disk */
     236            0 :     if (state_file_name)
     237            0 :         gnc_key_file_save_to_file(state_file_name, state_file, &error);
     238              :     else
     239            0 :         PWARN ("No state file name set, can't save state");
     240              : 
     241            0 :     if (error)
     242              :     {
     243            0 :         PERR ("Error: Cannot open state file %s", error->message);
     244            0 :         g_error_free (error);
     245              :     }
     246              : }
     247              : 
     248            0 : GKeyFile *gnc_state_get_current (void)
     249              : {
     250            0 :     if (!state_file)
     251              :     {
     252            0 :         PINFO ("No pre-existing state found, creating new one");
     253            0 :         state_file = g_key_file_new ();
     254              :     }
     255              : 
     256            0 :     return state_file;
     257              : 
     258              : }
     259              : 
     260            0 : gint gnc_state_drop_sections_for (const gchar *partial_name)
     261              : {
     262              :     gchar **groups;
     263            0 :     gint found_count = 0, dropped_count = 0;
     264              :     gsize i, num_groups;
     265            0 :     GError *error = NULL;
     266              : 
     267            0 :     if (!state_file)
     268              :     {
     269            0 :         PWARN ("No pre-existing state found, ignoring drop request");
     270            0 :         return 0;
     271              :     }
     272              : 
     273            0 :     ENTER("");
     274              : 
     275            0 :     groups = g_key_file_get_groups (state_file, &num_groups);
     276            0 :     for (i = 0; i < num_groups; i++)
     277              :     {
     278            0 :         if (g_strstr_len (groups[i], -1, partial_name))
     279              :         {
     280            0 :             DEBUG ("Section \"%s\" matches \"%s\", removing", groups[i], partial_name);
     281            0 :             found_count++;
     282            0 :             if (!g_key_file_remove_group (state_file, groups[i], &error))
     283              :             {
     284            0 :                 PWARN ("Warning: unable to remove section %s.\n  %s",
     285              :                         groups[i],
     286              :                         error->message);
     287            0 :                 g_error_free (error);
     288              :             }
     289              :             else
     290            0 :                 dropped_count++;
     291              : 
     292              :         }
     293              :     }
     294            0 :     g_strfreev (groups);
     295              : 
     296            0 :     LEAVE("Found %i sections matching \"%s\", successfully removed %i",
     297              :             found_count, partial_name, dropped_count);
     298            0 :     return dropped_count;
     299              : 
     300              : }
     301              : 
        

Generated by: LCOV version 2.0-1