gnome-control-center/archiver/archiver-client.c

443 lines
13 KiB
C
Raw Normal View History

2001-08-20 15:47:57 +00:00
/* -*- mode: c; style: linux -*- */
/* archiver-client.c
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Written by Bradford Hovinen (hovinen@ximian.com)
*
* 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 2, or (at your option)
* any later version.
*
* This 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <libbonobo.h>
2001-08-20 15:47:57 +00:00
#include <gnome-xml/parser.h>
#include "archiver-client.h"
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
#include "util.h"
2001-08-20 15:47:57 +00:00
static void merge_xml_docs (xmlDocPtr child_doc,
xmlDocPtr parent_doc);
static void subtract_xml_doc (xmlDocPtr child_doc,
xmlDocPtr parent_doc,
gboolean strict);
static void merge_xml_nodes (xmlNodePtr node1,
xmlNodePtr node2);
static xmlNodePtr subtract_xml_node (xmlNodePtr node1,
xmlNodePtr node2,
gboolean strict);
static gboolean compare_xml_nodes (xmlNodePtr node1, xmlNodePtr node2);
/**
Added exception RollbackDataNotFound Added exception LocationNotFound 2001-08-21 Bradford Hovinen <hovinen@ximian.com> * idl/ConfigArchiver.idl: Added exception RollbackDataNotFound Added exception LocationNotFound * archive.c (archive_get_current_location_id): Use archive_create_location rather than location_new (archive_get_current_location_id): Unref the location once we have created it * archiver-client.c (location_client_load_rollback_data): Don't try to parse the XML file if there was an exception * bonobo-config-archiver.c (bonobo_config_archiver_new): Make sure to release_unref location and archive if aborting (bonobo_config_archiver_new): Reinitialize exception structure after we have succeeded * location.c (location_get_rollback_filename): Recurse on parent location if parent_chain is set to TRUE * archive.c (impl_ConfigArchiver_Archive_getLocation): Set the LocationNotFound exception if the location returned was NULL * location.c (impl_ConfigArchiver_Location_getRollbackFilename): Don't try * archive.c (impl_ConfigArchiver_Archive_getLocation): Don't try to CORBA_Object_duplicate the result if it is NULL (archive_get_location): Don't try to cast the result of location_open before we know whether it is non-NULL (impl_ConfigArchiver_Archive_createLocation): Call bonobo_object_from_servant on parent_ref->servant * location.c (location_destroy): Remove debugging message; make remaining debugging message more enlightening * archive.c (archive_get_child_locations): Rename from archive_foreach_child_location; rewrite to return a GList of child locations (impl_ConfigArchiver_Archive_getChildLocations): Use archive_get_child_locations (archive_destroy): Remove debugging message * bonobo-moniker-archiver.c (archive_resolve): Remove debugging messages * archive.c (archive_get_location): Remove debugging messages * config-log.c (dump_log): Remove debugging messages * archive.c (archive_foreach_child_location): Build a list first and then traverse it to avoid screwing up the tree traversal * mouse-properties-capplet.c (apply_settings): Use a CORBA exception structure
2001-08-22 13:56:23 +00:00
* location_client_load_rollback_data
2001-08-20 15:47:57 +00:00
* @location:
* @date:
* @steps:
* @backend_id:
* @parent_chain:
*
* Loads the XML data for rolling back as specified and returns the document
* object
**/
xmlDocPtr
location_client_load_rollback_data (ConfigArchiver_Location location,
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
const struct tm *date,
2001-08-20 15:47:57 +00:00
guint steps,
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
const gchar *backend_id,
2001-08-20 15:47:57 +00:00
gboolean parent_chain,
CORBA_Environment *opt_ev)
{
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
gchar *filename;
struct tm *date_c;
time_t time_g;
xmlDocPtr doc = NULL;
xmlDocPtr parent_doc = NULL;
ConfigArchiver_ContainmentType type = ConfigArchiver_CONTAIN_FULL;
ConfigArchiver_Location parent = CORBA_OBJECT_NIL;
CORBA_Environment my_ev;
2001-08-20 15:47:57 +00:00
g_return_val_if_fail (location != CORBA_OBJECT_NIL, NULL);
if (opt_ev == NULL) {
opt_ev = &my_ev;
CORBA_exception_init (opt_ev);
}
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
if (date != NULL) {
date_c = dup_date (date);
time_g = mktime (date_c);
#ifdef __USE_BSD
time_g += date_c->tm_gmtoff;
#endif /* __USE_BSD */
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
if (date_c->tm_isdst) time_g -= 3600;
g_free (date_c);
} else {
2001-08-20 15:47:57 +00:00
time_g = 0;
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
}
2001-08-20 15:47:57 +00:00
filename = ConfigArchiver_Location_getRollbackFilename
(location, time_g, steps, backend_id, parent_chain, opt_ev);
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
if (!BONOBO_EX (opt_ev) && filename != NULL)
DEBUG_MSG ("Loading rollback data: %s", filename);
Added exception RollbackDataNotFound Added exception LocationNotFound 2001-08-21 Bradford Hovinen <hovinen@ximian.com> * idl/ConfigArchiver.idl: Added exception RollbackDataNotFound Added exception LocationNotFound * archive.c (archive_get_current_location_id): Use archive_create_location rather than location_new (archive_get_current_location_id): Unref the location once we have created it * archiver-client.c (location_client_load_rollback_data): Don't try to parse the XML file if there was an exception * bonobo-config-archiver.c (bonobo_config_archiver_new): Make sure to release_unref location and archive if aborting (bonobo_config_archiver_new): Reinitialize exception structure after we have succeeded * location.c (location_get_rollback_filename): Recurse on parent location if parent_chain is set to TRUE * archive.c (impl_ConfigArchiver_Archive_getLocation): Set the LocationNotFound exception if the location returned was NULL * location.c (impl_ConfigArchiver_Location_getRollbackFilename): Don't try * archive.c (impl_ConfigArchiver_Archive_getLocation): Don't try to CORBA_Object_duplicate the result if it is NULL (archive_get_location): Don't try to cast the result of location_open before we know whether it is non-NULL (impl_ConfigArchiver_Archive_createLocation): Call bonobo_object_from_servant on parent_ref->servant * location.c (location_destroy): Remove debugging message; make remaining debugging message more enlightening * archive.c (archive_get_child_locations): Rename from archive_foreach_child_location; rewrite to return a GList of child locations (impl_ConfigArchiver_Archive_getChildLocations): Use archive_get_child_locations (archive_destroy): Remove debugging message * bonobo-moniker-archiver.c (archive_resolve): Remove debugging messages * archive.c (archive_get_location): Remove debugging messages * config-log.c (dump_log): Remove debugging messages * archive.c (archive_foreach_child_location): Build a list first and then traverse it to avoid screwing up the tree traversal * mouse-properties-capplet.c (apply_settings): Use a CORBA exception structure
2001-08-22 13:56:23 +00:00
if (!BONOBO_EX (opt_ev) && filename != NULL)
2001-08-20 15:47:57 +00:00
doc = xmlParseFile (filename);
else if (parent_chain)
type = ConfigArchiver_Location_contains (location, backend_id, opt_ev);
if (type == ConfigArchiver_CONTAIN_PARTIAL)
parent = ConfigArchiver_Location__get_parent (location, opt_ev);
if (parent != CORBA_OBJECT_NIL) {
parent_doc = location_client_load_rollback_data
(parent, date, steps, backend_id, TRUE, opt_ev);
bonobo_object_release_unref (parent, NULL);
}
if (doc != NULL && parent_doc != NULL)
merge_xml_docs (doc, parent_doc);
else if (parent_doc != NULL)
doc = parent_doc;
if (opt_ev == &my_ev)
CORBA_exception_free (opt_ev);
return doc;
}
/**
* location_client_store_xml:
* @location:
* @backend_id:
* @input:
* @store_type: STORE_FULL means blindly store the data, without
* modification. STORE_COMPARE_PARENT means subtract the settings the parent
* has that are different and store the result. STORE_MASK_PREVIOUS means
* store only those settings that are reflected in the previous logged data;
* if there do not exist such data, act as in STORE_COMPARE_PARENT
* @opt_ev:
*
* Store configuration data from the given XML document object in the location
* under the given backend id
**/
void
location_client_store_xml (ConfigArchiver_Location location,
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
const gchar *backend_id,
2001-08-20 15:47:57 +00:00
xmlDocPtr xml_doc,
ConfigArchiver_StoreType store_type,
CORBA_Environment *opt_ev)
{
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
xmlDocPtr parent_doc;
xmlDocPtr prev_doc = NULL;
char *filename;
ConfigArchiver_ContainmentType contain_type;
ConfigArchiver_Location parent;
CORBA_Environment my_ev;
2001-08-20 15:47:57 +00:00
g_return_if_fail (location != CORBA_OBJECT_NIL);
g_return_if_fail (xml_doc != NULL);
if (opt_ev == NULL) {
opt_ev = &my_ev;
CORBA_exception_init (opt_ev);
}
contain_type = ConfigArchiver_Location_contains (location, backend_id, opt_ev);
parent = ConfigArchiver_Location__get_parent (location, opt_ev);
if (contain_type == ConfigArchiver_CONTAIN_NONE) {
if (parent == CORBA_OBJECT_NIL) {
fprintf (stderr, "Could not find a location in the " \
"tree ancestry that stores this " \
"backend: %s.\n", backend_id);
} else {
location_client_store_xml (parent, backend_id, xml_doc, store_type, opt_ev);
bonobo_object_release_unref (parent, NULL);
}
if (opt_ev == &my_ev)
CORBA_exception_free (opt_ev);
return;
}
if (contain_type == ConfigArchiver_CONTAIN_PARTIAL && store_type != ConfigArchiver_STORE_FULL && parent != CORBA_OBJECT_NIL) {
g_assert (store_type == ConfigArchiver_STORE_MASK_PREVIOUS ||
store_type == ConfigArchiver_STORE_COMPARE_PARENT);
parent_doc = location_client_load_rollback_data
(parent, NULL, 0, backend_id, TRUE, opt_ev);
if (store_type == ConfigArchiver_STORE_MASK_PREVIOUS)
prev_doc = location_client_load_rollback_data (location, NULL, 0, backend_id, FALSE, opt_ev);
if (store_type == ConfigArchiver_STORE_COMPARE_PARENT) {
subtract_xml_doc (xml_doc, parent_doc, FALSE);
} else {
subtract_xml_doc (parent_doc, prev_doc, FALSE);
subtract_xml_doc (xml_doc, parent_doc, TRUE);
}
xmlFreeDoc (parent_doc);
if (prev_doc != NULL)
xmlFreeDoc (prev_doc);
}
if (parent != CORBA_OBJECT_NIL)
bonobo_object_release_unref (parent, NULL);
Make backend_id const 2001-09-07 Bradford Hovinen <hovinen@ximian.com> * archiver-client.c (location_client_store_xml): Make backend_id const * util.c (parse_date): Set the time zone (parse_date): Initialize tm_isdst * archiver-client.c (location_client_store_xml): Call ConfigArchiver_Location_storageComplete when done (location_client_store_xml): Don't try to save the XML file if there was an error getting the storage filename * location.c (location_storage_complete): Implement (impl_ConfigArchiver_Location_storageComplete): Implement * config-log.c (config_log_get_backend_id_for_id): Make return value const 2001-09-04 Bradford Hovinen <hovinen@ximian.com> * location.c (location_get_storage_filename): Notify listeners that new rollback data is available * bonobo-config-archiver.c (new_rollback_cb): Implement (bonobo_config_archiver_new): Connect above to event source * location.c (location_store): (location_init): Construct an event source and add its interface * Makefile.am (INCLUDES): Remove -DDEFAULTS_DIR 2001-09-03 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept complete moniker as an argument; do the parsing here * archiver-client.c (location_client_load_rollback_data): Adjust time from mktime according to time zone information * bonobo-moniker-archiver.c (is_leap_year): (mod_date_by_str): Implement (parse_name): Use correct math for computing offsets * bonobo-config-archiver.c (bonobo_config_archiver_new): Don't print an error message if the parent moniker is bad (bonobo_config_archiver_new): Remove debugging messages * archiver-client.c (location_client_load_rollback_data): Make date and backend_id const * bonobo-moniker-archiver.c (archiverdb_resolve): Determine date from moniker and pass to bonobo_config_archiver_new * bonobo-config-archiver.c (bonobo_config_archiver_new): Accept date structure as argument
2001-09-12 15:30:41 +00:00
filename = ConfigArchiver_Location_getStorageFilename
(location, backend_id, store_type == ConfigArchiver_STORE_DEFAULT, opt_ev);
if (!BONOBO_EX (opt_ev) && filename != NULL) {
xmlSaveFile (filename, xml_doc);
ConfigArchiver_Location_storageComplete (location, filename, opt_ev);
CORBA_free (filename);
}
2001-08-20 15:47:57 +00:00
if (opt_ev == &my_ev)
CORBA_exception_free (opt_ev);
}
static void
merge_xml_docs (xmlDocPtr child_doc, xmlDocPtr parent_doc)
{
merge_xml_nodes (xmlDocGetRootElement (child_doc),
xmlDocGetRootElement (parent_doc));
}
static void
subtract_xml_doc (xmlDocPtr child_doc, xmlDocPtr parent_doc, gboolean strict)
{
subtract_xml_node (xmlDocGetRootElement (child_doc),
xmlDocGetRootElement (parent_doc), strict);
}
/* Merge contents of node1 and node2, where node1 overrides node2 as
* appropriate
*
* Notes: Two XML nodes are considered to be "the same" iff their names and
* all names and values of their attributes are the same. If that is not the
* case, they are considered "different" and will both be present in the
* merged node. If nodes are "the same", then this algorithm is called
* recursively. If nodes are CDATA, then node1 overrides node2 and the
* resulting node is just node1. The node merging is order-independent; child
* node from one tree are compared with all child nodes of the other tree
* regardless of the order they appear in. Hence one may have documents with
* different node orderings and the algorithm should still run correctly. It
* will not, however, run correctly in cases when the agent using this
* facility depends on the nodes being in a particular order.
*
* This XML node merging/comparison facility requires that the following
* standard be set for DTDs:
*
* Attributes' sole purpose is to identify a node. For example, a network
* configuration DTD might have an element like <interface name="eth0"> with a
* bunch of child nodes to configure that interface. The attribute "name" does
* not specify the configuration for the interface. It differentiates the node
* from the configuration for, say, interface eth1. Conversely, a node must be
* completely identified by its attributes. One cannot include identification
* information in the node's children, since otherwise the merging and
* subtraction algorithms will not know what to look for.
*
* As a corollary to the above, all configuration information must ultimately
* be in text nodes. For example, a text string might be stored as
* <configuration-item>my-value</configuration-item> but never as
* <configuration-item value="my-value"/>. As an example, if the latter is
* used, a child location might override a parent's setting for
* configuration-item. This algorithm will interpret those as different nodes
* and include them both in the merged result, since it will not have any way
* of knowing that they are really the same node with different
* configuration.
*/
static void
merge_xml_nodes (xmlNodePtr node1, xmlNodePtr node2)
{
xmlNodePtr child, tmp, iref;
GList *node1_children = NULL, *i;
gboolean found;
if (node1->type == XML_TEXT_NODE)
return;
for (child = node1->childs; child != NULL; child = child->next)
node1_children = g_list_prepend (node1_children, child);
node1_children = g_list_reverse (node1_children);
child = node2->childs;
while (child != NULL) {
tmp = child->next;
i = node1_children; found = FALSE;
while (i != NULL) {
iref = (xmlNodePtr) i->data;
if (compare_xml_nodes (iref, child)) {
merge_xml_nodes (iref, child);
if (i == node1_children)
node1_children = node1_children->next;
g_list_remove_link (node1_children, i);
g_list_free_1 (i);
found = TRUE;
break;
} else {
i = i->next;
}
}
if (found == FALSE) {
xmlUnlinkNode (child);
xmlAddChild (node1, child);
}
child = tmp;
}
g_list_free (node1_children);
}
/* Modifies node1 so that it only contains the parts different from node2;
* returns the modified node or NULL if the node should be destroyed
*
* strict determines whether the settings themselves are compared; it should
* be set to FALSE when the trees are being compared for the purpose of
* seeing what settings should be included in a tree and TRUE when one wants
* to restrict the settings included in a tree to those that have already been
* specified
*/
static xmlNodePtr
subtract_xml_node (xmlNodePtr node1, xmlNodePtr node2, gboolean strict)
{
xmlNodePtr child, tmp, iref;
GList *node2_children = NULL, *i;
gboolean found, same, all_same = TRUE;
if (node1->type == XML_TEXT_NODE) {
if (node2->type == XML_TEXT_NODE &&
(strict || !strcmp (xmlNodeGetContent (node1),
xmlNodeGetContent (node2))))
return NULL;
else
return node1;
}
if (node1->childs == NULL && node2->childs == NULL)
return NULL;
for (child = node2->childs; child != NULL; child = child->next)
node2_children = g_list_prepend (node2_children, child);
node2_children = g_list_reverse (node2_children);
child = node1->childs;
while (child != NULL) {
tmp = child->next;
i = node2_children; found = FALSE; all_same = TRUE;
while (i != NULL) {
iref = (xmlNodePtr) i->data;
if (compare_xml_nodes (child, iref)) {
same = (subtract_xml_node
(child, iref, strict) == NULL);
all_same = all_same && same;
if (same) {
xmlUnlinkNode (child);
xmlFreeNode (child);
}
if (i == node2_children)
node2_children = node2_children->next;
g_list_remove_link (node2_children, i);
g_list_free_1 (i);
found = TRUE;
break;
} else {
i = i->next;
}
}
if (!found)
all_same = FALSE;
child = tmp;
}
g_list_free (node2_children);
if (all_same)
return NULL;
else
return node1;
}
/* Return TRUE iff node1 and node2 are "the same" in the sense defined above */
static gboolean
compare_xml_nodes (xmlNodePtr node1, xmlNodePtr node2)
{
xmlAttrPtr attr;
gint count = 0;
if (strcmp (node1->name, node2->name))
return FALSE;
/* FIXME: This is worst case O(n^2), which can add up. Could we
* optimize for the case where people have attributes in the same
* order, or does not not matter? It probably does not matter, though,
* since people don't generally have more than one or two attributes
* in a tag anyway.
*/
for (attr = node1->properties; attr != NULL; attr = attr->next) {
g_assert (xmlNodeIsText (attr->val));
if (strcmp (xmlNodeGetContent (attr->val),
xmlGetProp (node2, attr->name)))
return FALSE;
count++;
}
/* FIXME: Is checking if the two nodes have the same number of
* attributes the correct policy here? Should we instead merge the
* attribute(s) that node1 is missing?
*/
for (attr = node2->properties; attr != NULL; attr = attr->next)
count--;
if (count == 0)
return TRUE;
else
return FALSE;
}