From 106e06d33196ca124d6d27cc00a5898d6f96121d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 1 Dec 2015 22:07:32 +0100
Subject: Handled relative paths when loading and saving binary contents in
 projects.

---
 ChangeLog                    | 13 +++++++++++++
 src/analysis/content-int.h   |  2 +-
 src/analysis/content.c       | 10 ++++++----
 src/analysis/content.h       |  4 ++--
 src/analysis/contents/file.c | 26 +++++++++++++++++++-------
 src/analysis/contents/file.h |  2 +-
 src/analysis/project.c       | 17 +++++++++++++----
 src/common/xml.h             |  1 -
 8 files changed, 55 insertions(+), 20 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a06eeaf..1723878 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 15-12-01  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/analysis/content-int.h:
+	* src/analysis/content.c:
+	* src/analysis/content.h:
+	* src/analysis/contents/file.c:
+	* src/analysis/contents/file.h:
+	* src/analysis/project.c:
+	Handle relative paths when loading and saving binary contents in projects.
+
+	* src/common/xml.h:
+	Typo.
+
+15-12-01  Cyrille Bagard <nocbos@gmail.com>
+
 	* plugins/pychrysa/common/Makefile.am:
 	Add the 'pathname.[ch]' files to libpychrysacommon_la_SOURCES.
 
diff --git a/src/analysis/content-int.h b/src/analysis/content-int.h
index 36168be..d9f9ef9 100644
--- a/src/analysis/content-int.h
+++ b/src/analysis/content-int.h
@@ -33,7 +33,7 @@
 typedef const char * (* describe_content_fc) (const GBinContent *, bool);
 
 /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */
-typedef bool (* save_content_fc) (const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *);
+typedef bool (* save_content_fc) (const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *);
 
 /* Fournit une empreinte unique (SHA256) pour les données. */
 typedef const gchar * (* get_checksum_fc) (GBinContent *);
diff --git a/src/analysis/content.c b/src/analysis/content.c
index d86a351..01c9c99 100644
--- a/src/analysis/content.c
+++ b/src/analysis/content.c
@@ -63,6 +63,7 @@ static void g_binary_content_default_init(GBinContentInterface *iface)
 *                                                                             *
 *  Paramètres  : context = contexte pour les recherches XPath.                *
 *                path    = chemin d'accès au noeud XML à lire.                *
+*                base    = référence au lieu d'enregistrement du projet.      *
 *                                                                             *
 *  Description : Charge en mémoire un contenu binaire à partir d'XML.         *
 *                                                                             *
@@ -72,7 +73,7 @@ static void g_binary_content_default_init(GBinContentInterface *iface)
 *                                                                             *
 ******************************************************************************/
 
-GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr context, const char *path)
+GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr context, const char *path, const char *base)
 {
     GBinContent *result;                    /* Contenu en place à renvoyer */
     char *type;                             /* Type de binaire à charger   */
@@ -82,7 +83,7 @@ GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr context, const cha
     type = get_node_prop_value(context, path, "type");
 
     if (strcmp(type, "file") == 0)
-        result = g_file_content_new_from_xml(context, path);
+        result = g_file_content_new_from_xml(context, path, base);
 
     free(type);
 
@@ -121,6 +122,7 @@ const char *g_binary_content_describe(const GBinContent *content, bool full)
 *                xdoc    = structure XML en cours d'édition.                  *
 *                context = contexte à utiliser pour les recherches.           *
 *                path    = chemin d'accès réservé au binaire.                 *
+*                base    = référence au lieu d'enregistrement du projet.      *
 *                                                                             *
 *  Description : Ecrit une sauvegarde de contenu binaire dans un fichier XML. *
 *                                                                             *
@@ -130,13 +132,13 @@ const char *g_binary_content_describe(const GBinContent *content, bool full)
 *                                                                             *
 ******************************************************************************/
 
-bool g_binary_content_save(const GBinContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
+bool g_binary_content_save(const GBinContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *base)
 {
     GBinContentIface *iface;                /* Interface utilisée          */
 
     iface = G_BIN_CONTENT_GET_IFACE(content);
 
-    return iface->save(content, xdoc, context, path);
+    return iface->save(content, xdoc, context, path, base);
 
 }
 
diff --git a/src/analysis/content.h b/src/analysis/content.h
index 591097d..1a61cb7 100644
--- a/src/analysis/content.h
+++ b/src/analysis/content.h
@@ -55,13 +55,13 @@ typedef struct _GBinContentIface GBinContentIface;
 GType g_binary_content_get_type(void) G_GNUC_CONST;
 
 /* Charge en mémoire un contenu binaire à partir d'XML. */
-GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr, const char *);
+GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr, const char *, const char *);
 
 /* Fournit le nom associé au contenu binaire. */
 const char *g_binary_content_describe(const GBinContent *, bool);
 
 /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */
-bool g_binary_content_save(const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *);
+bool g_binary_content_save(const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *);
 
 /* Fournit une empreinte unique (SHA256) pour les données. */
 const gchar *g_binary_content_get_cheksum(GBinContent *);
diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c
index f24e930..8416348 100644
--- a/src/analysis/contents/file.c
+++ b/src/analysis/contents/file.c
@@ -35,6 +35,7 @@
 
 #include "../content-int.h"
 #include "../../common/extstr.h"
+#include "../../common/pathname.h"
 
 
 
@@ -80,7 +81,7 @@ static void g_file_content_finalize(GFileContent *);
 static const char *g_file_content_describe(const GFileContent *, bool);
 
 /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */
-static bool g_file_content_save(const GFileContent *, xmlDocPtr, xmlXPathContextPtr, const char *);
+static bool g_file_content_save(const GFileContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *);
 
 /* Fournit une empreinte unique (SHA256) pour les données. */
 static const gchar *g_file_content_get_checksum(GFileContent *);
@@ -324,6 +325,7 @@ GBinContent *g_file_content_new(const char *filename)
 *                                                                             *
 *  Paramètres  : context = contexte pour les recherches XPath.                *
 *                path    = chemin d'accès au noeud XML à lire.                *
+*                base    = référence au lieu d'enregistrement du projet.      *
 *                                                                             *
 *  Description : Charge en mémoire le contenu d'un fichier à partir d'XML.    *
 *                                                                             *
@@ -333,11 +335,12 @@ GBinContent *g_file_content_new(const char *filename)
 *                                                                             *
 ******************************************************************************/
 
-GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr context, const char *path)
+GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr context, const char *path, const char *base)
 {
     GBinContent *result;                    /* Adresse à retourner         */
     char *access;                           /* Chemin pour une sous-config.*/
     char *filename;                         /* Chemin du binaire à charger */
+    char *absolute;                         /* Chemin absolu final         */
 
     result = NULL;
 
@@ -352,10 +355,14 @@ GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr context, const char
 
     /* Chargement */
 
-    if (filename != NULL)
+    absolute = build_absolute_filename(base, filename);
+
+    if (filename != NULL) free(filename);
+
+    if (absolute != NULL)
     {
-        result = g_file_content_new(filename);
-        free(filename);
+        result = g_file_content_new(absolute);
+        free(absolute);
     }
 
     return result;
@@ -396,6 +403,7 @@ static const char *g_file_content_describe(const GFileContent *content, bool ful
 *                xdoc    = structure XML en cours d'édition.                  *
 *                context = contexte à utiliser pour les recherches.           *
 *                path    = chemin d'accès réservé au binaire.                 *
+*                base    = référence au lieu d'enregistrement du projet.      *
 *                                                                             *
 *  Description : Ecrit une sauvegarde de contenu binaire dans un fichier XML. *
 *                                                                             *
@@ -405,10 +413,11 @@ static const char *g_file_content_describe(const GFileContent *content, bool ful
 *                                                                             *
 ******************************************************************************/
 
-static bool g_file_content_save(const GFileContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
+static bool g_file_content_save(const GFileContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *base)
 {
     bool result;                            /* Bilan à faire remonter      */
     char *access;                           /* Chemin d'accès à un élément */
+    char *relative;                         /* Chemin d'accès relatif      */
 
     result = true;
 
@@ -421,8 +430,11 @@ static bool g_file_content_save(const GFileContent *content, xmlDocPtr xdoc, xml
     access = strdup(path);
     access = stradd(access, "/Filename");
 
-    result &= add_content_to_node(xdoc, context, access, content->filename);
+    relative = build_relative_filename(base, content->filename);
+
+    result &= add_content_to_node(xdoc, context, access, relative);
 
+    free(relative);
     free(access);
 
     return result;
diff --git a/src/analysis/contents/file.h b/src/analysis/contents/file.h
index 0985f6b..90e292e 100644
--- a/src/analysis/contents/file.h
+++ b/src/analysis/contents/file.h
@@ -54,7 +54,7 @@ GType g_file_content_get_type(void);
 GBinContent *g_file_content_new(const char *);
 
 /* Charge en mémoire le contenu d'un fichier à partir d'XML. */
-GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr, const char *);
+GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr, const char *, const char *);
 
 
 
diff --git a/src/analysis/project.c b/src/analysis/project.c
index ed60929..94b01a3 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -282,14 +282,20 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename)
         access = calloc(access_len, sizeof(char));
         snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%u]", i + 1);
 
-        content = g_binary_content_new_from_xml(context, access);
+        content = g_binary_content_new_from_xml(context, access, filename);
         status = get_node_prop_long_value(context, access, "state", &state);
 
         free(access);
 
+        if (content == NULL)
+        {
+            log_variadic_message(LMT_ERROR, _("Unable to load the binary content #%u ; skipping..."), i);
+            continue;
+        }
+
         if (!status)
         {
-            log_variadic_message(LMT_PROCESS, _("bad state for content '%s' ; skipping..."),
+            log_variadic_message(LMT_ERROR, _("Bad state for content '%s' ; skipping..."),
                                  g_binary_content_describe(content, true));
             continue;
         }
@@ -375,6 +381,7 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
     bool result;                            /* Bilan à retourner           */
     xmlDocPtr xdoc;                         /* Document XML à créer        */
     xmlXPathContextPtr context;             /* Contexte pour les recherches*/
+    const char *final;                      /* Lieu d'enregistrement final */
     size_t i;                               /* Boucle de parcours          */
     size_t access_len;                      /* Taille d'un chemin interne  */
     char *access;                           /* Chemin pour une sous-config.*/
@@ -383,6 +390,8 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
 
     result &= (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL);
 
+    final = filename != NULL ? filename : project->filename;
+
     /* Enregistrement des contenus binaires attachés */
 
     for (i = 0; i < project->contents_count && result; i++)
@@ -394,7 +403,7 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
         access = calloc(access_len, sizeof(char));
         snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%zu]", i + 1);
 
-        result = g_binary_content_save(project->contents[i].content, xdoc, context, access);
+        result = g_binary_content_save(project->contents[i].content, xdoc, context, access, final);
 
         if (result)
             result = add_long_attribute_to_node(xdoc, context, access, "state", project->contents[i].state);
@@ -420,7 +429,7 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
 
     /* Sauvegarde finale */
 
-    result &= save_xml_file(xdoc, filename != NULL ? filename : project->filename);
+    result &= save_xml_file(xdoc, final);
 
     if (result && filename != NULL)
     {
diff --git a/src/common/xml.h b/src/common/xml.h
index 60891f7..674bfd4 100644
--- a/src/common/xml.h
+++ b/src/common/xml.h
@@ -34,7 +34,6 @@
 
 
 
-
 /* Crée un nouveau fichier XML. */
 bool create_new_xml_file(xmlDocPtr *, xmlXPathContextPtr *);
 
-- 
cgit v0.11.2-87-g4458