QOF  0.8.7
qsf-backend.c
1 /*******************************************************************
2  * qsf-backend.c
3  *
4  * Sat Jan 1 15:07:14 2005
5  * Copyright 2005-2008 Neil Williams
6  * linux@codehelp.co.uk
7  *******************************************************************/
8 /*
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23 
24 #include "config.h"
25 #include <errno.h>
26 #include <sys/stat.h>
27 #include <glib.h>
28 #include <libxml/xmlmemory.h>
29 #include <libxml/tree.h>
30 #include <libxml/parser.h>
31 #include <libxml/xmlschemas.h>
32 #include "qof.h"
33 #include "qofobject-p.h"
34 #include "qof-backend-qsf.h"
35 #include "qsf-xml.h"
36 #include "kvputil-p.h"
37 
38 #define QSF_TYPE_BINARY "binary"
39 #define QSF_TYPE_GLIST "glist"
40 #define QSF_TYPE_FRAME "frame"
41 
42 static QofLogModule log_module = QOF_MOD_QSF;
43 
44 static void qsf_object_commitCB (gpointer key, gpointer value,
45  gpointer data);
46 
47 struct QSFBackend_s
48 {
49  QofBackend be;
50  QsfParam *params;
51  gchar *fullpath;
52 };
53 
54 typedef struct QSFBackend_s QSFBackend;
55 
56 static void
57 option_cb (QofBackendOption * option, gpointer data)
58 {
59  QsfParam *params;
60 
61  params = (QsfParam *) data;
62  g_return_if_fail (params);
63  if (0 == safe_strcmp (QSF_COMPRESS, option->option_name))
64  {
65  params->use_gz_level = (*(gint64 *) option->value);
66  PINFO (" compression=%" G_GINT64_FORMAT, params->use_gz_level);
67  }
68  if (0 == safe_strcmp (QSF_MAP_FILES, option->option_name))
69  {
70  params->map_files = g_list_copy ((GList *) option->value);
71  }
72  if (0 == safe_strcmp (QSF_ENCODING, option->option_name))
73  {
74  params->encoding = g_strdup (option->value);
75  PINFO (" encoding=%s", params->encoding);
76  }
77  if (0 == safe_strcmp (QSF_DATE_CONVERT, option->option_name))
78  {
79  params->convert = (*(double *) option->value);
80  if (params->convert > 0)
81  PINFO (" converting date into time on file write.");
82  }
83 }
84 
85 static void
86 qsf_load_config (QofBackend * be, KvpFrame * config)
87 {
88  QSFBackend *qsf_be;
89  QsfParam *params;
90 
91  ENTER (" ");
92  qsf_be = (QSFBackend *) be;
93  g_return_if_fail (qsf_be->params);
94  params = qsf_be->params;
95  qof_backend_option_foreach (config, option_cb, params);
96  LEAVE (" ");
97 }
98 
99 static KvpFrame *
100 qsf_get_config (QofBackend * be)
101 {
102  QofBackendOption *option;
103  QSFBackend *qsf_be;
104  QsfParam *params;
105 
106  if (!be)
107  {
108  return NULL;
109  }
110  ENTER (" ");
111  qsf_be = (QSFBackend *) be;
112  g_return_val_if_fail (qsf_be->params, NULL);
113  params = qsf_be->params;
115  option = g_new0 (QofBackendOption, 1);
116  option->option_name = QSF_COMPRESS;
117  option->description =
118  _("Level of compression to use: 0 for none, 9 for highest.");
119  option->tooltip =
120  _("QOF can compress QSF XML files using gzip. "
121  "Note that compression is not used when outputting to STDOUT.");
122  option->type = KVP_TYPE_GINT64;
123  /* GINT_TO_POINTER can only be used for 32bit values. */
124  option->value = (gpointer) & params->use_gz_level;
125  qof_backend_prepare_option (be, option);
126  g_free (option);
127  option = g_new0 (QofBackendOption, 1);
128  option->option_name = QSF_MAP_FILES;
129  option->description =
130  _("List of QSF map files to use for this session.");
131  option->tooltip =
132  _("QOF can convert objects within QSF XML files "
133  "using a map of the changes required.");
134  option->type = KVP_TYPE_GLIST;
135  option->value = (gpointer) params->map_files;
136  qof_backend_prepare_option (be, option);
137  g_free (option);
138  option = g_new0 (QofBackendOption, 1);
139  option->option_name = QSF_ENCODING;
140  option->description =
141  _("Encoding string to use when writing the XML file.");
142  option->tooltip =
143  _("QSF defaults to UTF-8. Other encodings are supported by "
144  "passing the encoding string in this option.");
145  option->type = KVP_TYPE_STRING;
146  option->value = (gpointer) params->encoding;
147  qof_backend_prepare_option (be, option);
148  g_free (option);
149  option = g_new0 (QofBackendOption, 1);
150  option->option_name = QSF_DATE_CONVERT;
151  option->description =
152  _("Convert deprecated date values to time values.");
153  option->tooltip =
154  _("Applications that support the new QOF time format "
155  "need to enable this option to convert older date values into time. "
156  "Applications that still use date should not set this option "
157  "until time values are supported.");
158  option->type = KVP_TYPE_GINT64;
159  option->value = &params->convert;
160  qof_backend_prepare_option (be, option);
161  g_free (option);
162  LEAVE (" ");
163  return qof_backend_complete_frame (be);
164 }
165 
166 GList **
167 qsf_map_prepare_list (GList ** maps)
168 {
169  /* Add new map filenames here. */
171  *maps = g_list_prepend (*maps, "pilot-qsf-GnuCashInvoice.xml");
172  *maps = g_list_prepend (*maps, "pilot-qsf-gncCustomer.xml");
173  return maps;
174 }
175 
176 static void
177 qsf_param_init (QsfParam * params)
178 {
179  gchar *qsf_time_string;
180  gchar *qsf_enquiry_date;
181  gchar * G_GNUC_UNUSED qsf_time_now;
182  gchar * G_GNUC_UNUSED qsf_time_precision;
183 
184  g_return_if_fail (params != NULL);
185  params->count = 0;
186  params->convert = 1;
187  params->use_gz_level = 0;
188  params->supported_types = NULL;
189  params->file_type = QSF_UNDEF;
190  params->qsf_ns = NULL;
191  params->output_doc = NULL;
192  params->output_node = NULL;
193  params->lister = NULL;
194  params->full_kvp_path = NULL;
195  params->map_ns = NULL;
196  params->map_files = NULL;
197  params->map_path = NULL;
198  params->encoding = "UTF-8";
199  params->qsf_object_list = NULL;
200  params->qsf_parameter_hash =
201  g_hash_table_new (g_str_hash, g_str_equal);
202  params->qsf_default_hash = g_hash_table_new (g_str_hash, g_str_equal);
203  params->qsf_define_hash = g_hash_table_new (g_str_hash, g_str_equal);
204  params->qsf_calculate_hash =
205  g_hash_table_new (g_str_hash, g_str_equal);
206  params->referenceList = NULL;
207  params->supported_types =
208  g_slist_append (params->supported_types, QOF_TYPE_STRING);
209  params->supported_types =
210  g_slist_append (params->supported_types, QOF_TYPE_GUID);
211  params->supported_types =
212  g_slist_append (params->supported_types, QOF_TYPE_BOOLEAN);
213  params->supported_types =
214  g_slist_append (params->supported_types, QOF_TYPE_NUMERIC);
215  params->supported_types =
216  g_slist_append (params->supported_types, QOF_TYPE_TIME);
217  params->supported_types =
218  g_slist_append (params->supported_types, QOF_TYPE_INT32);
219  params->supported_types =
220  g_slist_append (params->supported_types, QOF_TYPE_INT64);
221  params->supported_types =
222  g_slist_append (params->supported_types, QOF_TYPE_DOUBLE);
223  params->supported_types =
224  g_slist_append (params->supported_types, QOF_TYPE_CHAR);
225  params->supported_types =
226  g_slist_append (params->supported_types, QOF_TYPE_KVP);
227  params->supported_types =
228  g_slist_append (params->supported_types, QOF_TYPE_COLLECT);
229  params->supported_types =
230  g_slist_append (params->supported_types, QOF_TYPE_CHOICE);
231  qsf_time_precision = "%j";
232  qsf_enquiry_date = qof_time_stamp_now ();
233  qsf_time_string = qof_date_print (qof_date_get_current(),
235  qsf_time_now = qof_time_stamp_now ();
236 
237  g_hash_table_insert (params->qsf_default_hash, "qsf_enquiry_date",
238  qsf_enquiry_date);
239  g_hash_table_insert (params->qsf_default_hash, "qsf_time_now",
241  g_hash_table_insert (params->qsf_default_hash, "qsf_time_string",
242  qsf_time_string);
243  /* default map files */
244  params->map_files = *qsf_map_prepare_list (&params->map_files);
245  params->err_nomap = qof_error_register
246  (_("The selected QSF Object file '%s' requires a "
247  "map but it was not provided."), TRUE);
248  params->err_overflow = qof_error_register
249  (_("When converting XML strings into numbers, an "
250  "overflow has been detected. The QSF object file "
251  "'%s' contains invalid data in a field that is "
252  "meant to hold a number."), TRUE);
253 }
254 
255 static gboolean
256 qsf_determine_file_type (const gchar * path)
257 {
258  struct stat sbuf;
259 
260  if (!path)
261  return TRUE;
262  if (0 == safe_strcmp (path, QOF_STDOUT))
263  return TRUE;
264  if (stat (path, &sbuf) < 0)
265  {
266  /* in case the error is that the file does not exist */
267  FILE * f;
268  f = fopen (path, "a+");
269  if (f)
270  {
271  fclose (f);
272  return TRUE;
273  }
274  return FALSE;
275  }
276  if (sbuf.st_size == 0)
277  return TRUE;
278  if (is_our_qsf_object (path))
279  return TRUE;
280  else if (is_qsf_object (path))
281  return TRUE;
282  else if (is_qsf_map (path))
283  return TRUE;
284  return FALSE;
285 }
286 
287 static void
288 qsf_session_begin (QofBackend * be, QofSession * session,
289  const gchar * book_path, gboolean ignore_lock,
290  gboolean create_if_nonexistent)
291 {
292  QSFBackend *qsf_be;
293  gchar *p, *path;
294 
295  PINFO (" ignore_lock=%d create_if_nonexistent=%d", ignore_lock,
296  create_if_nonexistent);
297  g_return_if_fail (be != NULL);
298  g_return_if_fail (session);
299  be->fullpath = g_strdup (book_path);
300  qsf_be = (QSFBackend *) be;
301  g_return_if_fail (qsf_be->params != NULL);
302  qsf_be->fullpath = NULL;
303  if (book_path == NULL)
304  {
305  /* allow use of stdout */
306  qof_error_set_be (be, QOF_SUCCESS);
307  return;
308  }
309  p = strchr (book_path, ':');
310  if (p)
311  {
312  path = g_strdup (book_path);
313  if (!g_ascii_strncasecmp (path, "file:", 5))
314  {
315  p = g_new0 (gchar, strlen (path) - 5 + 1);
316  strcpy (p, path + 5);
317  }
318  qsf_be->fullpath = g_strdup (p);
319  g_free (path);
320  }
321  else
322  qsf_be->fullpath = g_strdup (book_path);
323  if (create_if_nonexistent)
324  {
325  FILE *f;
326 
327  f = fopen (qsf_be->fullpath, "a+");
328  if (f)
329  fclose (f);
330  else
331  {
332  qof_error_set_be (be, qof_error_register
333  (_("could not write to '%s'. "
334  "That database may be on a read-only file system, "
335  "or you may not have write permission for the "
336  "directory.\n"), TRUE));
337  return;
338  }
339  }
340  qof_error_set_be (be, QOF_SUCCESS);
341 }
342 
343 static void
344 qsf_free_params (QsfParam * params)
345 {
346  g_hash_table_destroy (params->qsf_calculate_hash);
347  g_hash_table_destroy (params->qsf_default_hash);
348  if (params->referenceList)
349  g_list_free (params->referenceList);
350  g_slist_free (params->supported_types);
351  if (params->map_ns)
352  xmlFreeNs (params->map_ns);
353  if (params->output_doc)
354  xmlFreeDoc (params->output_doc);
355 }
356 
357 static void
358 qsf_session_end (QofBackend * be)
359 {
360  QSFBackend *qsf_be;
361 
362  qsf_be = (QSFBackend *) be;
363  g_return_if_fail (qsf_be != NULL);
364  qsf_free_params (qsf_be->params);
365  g_free (qsf_be->fullpath);
366  qsf_be->fullpath = NULL;
367  xmlCleanupParser ();
368 }
369 
370 static void
371 qsf_destroy_backend (QofBackend * be)
372 {
373  g_free (be);
374 }
375 
376 static void
377 ent_ref_cb (QofEntity * ent, gpointer user_data)
378 {
379  QsfParam *params;
380  QofEntityReference *ref;
381  void (*reference_setter) (QofEntity *, QofEntity *);
382  QofEntity *reference;
383  QofCollection *coll;
384  QofIdType type;
385 
386  params = (QsfParam *) user_data;
387  g_return_if_fail (params);
388  while (params->referenceList)
389  {
390  ref = (QofEntityReference *) params->referenceList->data;
391  if (qof_object_is_choice (ent->e_type))
392  type = ref->choice_type;
393  else
394  type = ref->type;
395  coll = qof_book_get_collection (params->book, type);
396  reference = qof_collection_lookup_entity (coll, ref->ref_guid);
397  reference_setter =
398  (void (*)(QofEntity *, QofEntity *)) ref->param->param_setfcn;
399  if (reference_setter != NULL)
400  {
401  qof_util_param_edit ((QofInstance *) ent, ref->param);
402  qof_util_param_edit ((QofInstance *) reference, ref->param);
403  reference_setter (ent, reference);
404  qof_util_param_commit ((QofInstance *) ent, ref->param);
405  qof_util_param_commit ((QofInstance *) reference, ref->param);
406  }
407  params->referenceList = g_list_next (params->referenceList);
408  }
409 }
410 
411 static void
412 insert_ref_cb (QofObject * obj, gpointer user_data)
413 {
414  QsfParam *params;
415 
416  params = (QsfParam *) user_data;
417  g_return_if_fail (params);
418  qof_object_foreach (obj->e_type, params->book, ent_ref_cb, params);
419 }
420 
421 /*================================================
422  Load QofEntity into QofBook from XML in memory
423 ==================================================*/
424 
425 static gboolean
426 qsfdoc_to_qofbook (QsfParam * params)
427 {
428  QofInstance *inst;
429  struct QsfNodeIterate qiter;
430  QofBook *book;
431  GList *object_list;
432  xmlNodePtr qsf_root;
433  xmlNsPtr qsf_ns;
434 
435  g_return_val_if_fail (params != NULL, FALSE);
436  g_return_val_if_fail (params->input_doc != NULL, FALSE);
437  g_return_val_if_fail (params->book != NULL, FALSE);
438  g_return_val_if_fail (params->file_type == OUR_QSF_OBJ, FALSE);
439  qsf_root = xmlDocGetRootElement (params->input_doc);
440  if (!qsf_root)
441  return FALSE;
442  qsf_ns = qsf_root->ns;
443  qiter.ns = qsf_ns;
444  book = params->book;
445  params->referenceList =
446  (GList *) qof_book_get_data (book, ENTITYREFERENCE);
447  qsf_node_foreach (qsf_root, qsf_book_node_handler, &qiter, params);
448  object_list = g_list_copy (params->qsf_object_list);
449  while (object_list != NULL)
450  {
451  params->object_set = object_list->data;
452  object_list = g_list_next (object_list);
453  params->qsf_parameter_hash = params->object_set->parameters;
454  if (!qof_class_is_registered (params->object_set->object_type))
455  continue;
456  inst =
458  object_type, book);
459  g_return_val_if_fail (inst != NULL, FALSE);
460  params->qsf_ent = &inst->entity;
461  g_hash_table_foreach (params->qsf_parameter_hash,
462  qsf_object_commitCB, params);
463  }
464  qof_object_foreach_type (insert_ref_cb, params);
466  return TRUE;
467 }
468 
469 /* QofBackend routine to load from file - needs a map.
470 */
471 static gboolean
472 load_qsf_object (QofBook * book, const gchar * fullpath,
473  QsfParam * params)
474 {
475  xmlNodePtr qsf_root, map_root;
476  xmlDocPtr mapDoc, foreign_doc;
477  gchar *map_path, *map_file;
478 
479  map_file = params->map_path;
480  mapDoc = NULL;
481  /* use selected map */
482  if (!map_file)
483  {
484  qof_error_set_be (params->be, params->err_nomap);
485  return FALSE;
486  }
487  foreign_doc = xmlParseFile (fullpath);
488  if (foreign_doc == NULL)
489  {
490  qof_error_set_be (params->be, qof_error_register
491  (_("There was an error parsing the file '%s'.\n"), TRUE));
492  return FALSE;
493  }
494  qsf_root = NULL;
495  qsf_root = xmlDocGetRootElement (foreign_doc);
496  params->qsf_ns = qsf_root->ns;
497  params->book = book;
498  map_path = g_strdup_printf ("%s/%s", QSF_SCHEMA_DIR, map_file);
499  if (!map_path)
500  {
501  qof_error_set_be (params->be, params->err_nomap);
502  return FALSE;
503  }
504  mapDoc = xmlParseFile (map_path);
505  if (!mapDoc)
506  {
507  qof_error_set_be (params->be, params->err_nomap);
508  return FALSE;
509  }
510  map_root = xmlDocGetRootElement (mapDoc);
511  params->map_ns = map_root->ns;
512  params->input_doc = qsf_object_convert (mapDoc, qsf_root, params);
513  qsfdoc_to_qofbook (params);
514  return TRUE;
515 }
516 
517 static gboolean
518 load_our_qsf_object (const gchar * fullpath, QsfParam * params)
519 {
520  xmlNodePtr qsf_root;
521 
522  params->input_doc = xmlParseFile (fullpath);
523  if (params->input_doc == NULL)
524  {
525  qof_error_set_be (params->be, qof_error_register
526  (_("There was an error parsing the file '%s'."), TRUE));
527  return FALSE;
528  }
529  qsf_root = NULL;
530  qsf_root = xmlDocGetRootElement (params->input_doc);
531  params->qsf_ns = qsf_root->ns;
532  return qsfdoc_to_qofbook (params);
533 }
534 
535 /* Determine the type of QSF and load it into the QofBook
536 
537 - is_our_qsf_object, OUR_QSF_OBJ, QSF object file using only QOF objects known
538  to the calling process. No map is required.
539 - is_qsf_object, IS_QSF_OBJ, QSF object file that may or may not have a QSF map
540  to convert external objects. This temporary type will be set to HAVE_QSF_MAP
541  if a suitable map exists, or an error value returned: ERR_QSF_NO_MAP,
542  ERR_QSF_BAD_MAP or ERR_QSF_WRONG_MAP. This allows the calling process to inform
543  the user that the QSF itself is valid but a suitable map cannot be found.
544 - is_qsf_map, IS_QSF_MAP, QSF map file. In the backend, this generates
545  ERR_QSF_MAP_NOT_OBJ but it can be used internally when processing maps to
546  match a QSF object.
547 
548 returns NULL on error, otherwise a pointer to the QofBook. Use
549 the qof_book_merge API to merge the new data into the current
550 QofBook.
551 */
552 static void
553 qsf_file_type (QofBackend * be, QofBook * book)
554 {
555  QSFBackend *qsf_be;
556  QofErrorId parse_err;
557  QsfParam *params;
558  FILE *f;
559  gchar *path;
560  gboolean result;
561 
562  g_return_if_fail (be != NULL);
563  g_return_if_fail (book != NULL);
564  qsf_be = (QSFBackend *) be;
565  g_return_if_fail (qsf_be != NULL);
566  g_return_if_fail (qsf_be->fullpath != NULL);
567  g_return_if_fail (qsf_be->params != NULL);
568  parse_err = qof_error_register
569  (_("There was an error parsing the file '%s'."), TRUE);
570  params = qsf_be->params;
571  params->book = book;
572  DEBUG (" qsf_be->fullpath=%s", qsf_be->fullpath);
573  path = g_strdup (qsf_be->fullpath);
574  f = fopen (path, "r");
575  if (!f)
576  qof_error_set_be (be, qof_error_register
577  (_("There was an error reading the file '%s'."), TRUE));
578  else
579  fclose (f);
580  params->filepath = g_strdup (path);
581  result = is_our_qsf_object_be (params);
582  if (result)
583  {
584  params->file_type = OUR_QSF_OBJ;
585  result = load_our_qsf_object (path, params);
586  if (!result)
587  qof_error_set_be (be, parse_err);
588  return;
589  }
590  else if (is_qsf_object_be (params))
591  {
592  params->file_type = IS_QSF_OBJ;
593  result = load_qsf_object (book, path, params);
594  if (!result)
595  qof_error_set_be (be, parse_err);
596  return;
597  }
598  if (qof_error_check_be (be) == params->err_nomap)
599  {
600  /* usable QSF object but no map available */
601  params->file_type = IS_QSF_OBJ;
602  result = TRUE;
603  }
604  if (result == FALSE)
605  {
606  if (is_qsf_map_be (params))
607  {
608  params->file_type = IS_QSF_MAP;
609  qof_error_set_be (be, qof_error_register
610  (_("The selected file '%s' is a QSF map and cannot "
611  "be opened as a QSF object."), TRUE));
612  }
613  }
614 }
615 
616 static void
617 qsf_object_sequence (QofParam * qof_param, gpointer data)
618 {
619  QsfParam *params;
620  GSList *checklist, *result;
621 
622  g_return_if_fail (data != NULL);
623  params = (QsfParam *) data;
624  result = NULL;
625  checklist = NULL;
626  params->knowntype = FALSE;
627  checklist = g_slist_copy (params->supported_types);
628  for (result = checklist; result != NULL; result = result->next)
629  {
630  if (0 ==
631  safe_strcmp ((QofIdType) result->data,
632  qof_param->param_type))
633  params->knowntype = TRUE;
634  }
635  g_slist_free (checklist);
636  if (0 == safe_strcmp (qof_param->param_type, params->qof_type))
637  {
638  params->qsf_sequence =
639  g_slist_append (params->qsf_sequence, qof_param);
640  params->knowntype = TRUE;
641  }
642  /* handle params->qof_type = QOF_TYPE_GUID and qof_param->param_type != known type */
643  if (0 == safe_strcmp (params->qof_type, QOF_TYPE_GUID)
644  && (params->knowntype == FALSE))
645  {
646  params->qsf_sequence =
647  g_slist_append (params->qsf_sequence, qof_param);
648  params->knowntype = TRUE;
649  }
650 }
651 
652 /* receives each entry from supported_types in sequence
653  type = qof data type from supported list
654  user_data = params. Holds object type
655 */
656 static void
657 qsf_supported_parameters (gpointer type, gpointer user_data)
658 {
659  QsfParam *params;
660 
661  g_return_if_fail (user_data != NULL);
662  params = (QsfParam *) user_data;
663  params->qof_type = (QofIdType) type;
664  params->knowntype = FALSE;
665  qof_class_param_foreach (params->qof_obj_type, qsf_object_sequence,
666  params);
667 }
668 
669 static KvpValueType
670 qsf_to_kvp_helper (const char *type_string)
671 {
672  KvpValueType kvt;
673  kvt = qof_id_to_kvp_value_type (type_string);
674  if (kvt != 0)
675  return kvt;
676  if (0 == safe_strcmp (QSF_TYPE_BINARY, type_string))
677  return KVP_TYPE_BINARY;
678  if (0 == safe_strcmp (QSF_TYPE_GLIST, type_string))
679  return KVP_TYPE_GLIST;
680  if (0 == safe_strcmp (QSF_TYPE_FRAME, type_string))
681  return KVP_TYPE_FRAME;
682  return 0;
683 }
684 
685 static QofIdTypeConst
686 kvp_value_to_qof_type_helper (KvpValueType n)
687 {
688  QofIdTypeConst qtc;
689  qtc = kvp_value_type_to_qof_id (n);
690  if (qtc)
691  return qtc;
692  switch (n)
693  {
694  case KVP_TYPE_BINARY:
695  {
696  return QSF_TYPE_BINARY;
697  break;
698  }
699  case KVP_TYPE_GLIST:
700  {
701  return QSF_TYPE_GLIST;
702  break;
703  }
704  case KVP_TYPE_FRAME:
705  {
706  return QSF_TYPE_FRAME;
707  break;
708  }
709  default:
710  {
711  return NULL;
712  }
713  }
714 }
715 
716 
717 static void
718 qsf_from_kvp_helper (const gchar * path, KvpValue * content,
719  gpointer data)
720 {
721  QsfParam *params;
722  QofParam *qof_param;
723  xmlNodePtr node;
724  KvpValueType n;
725  gchar *full_path;
726 
727  params = (QsfParam *) data;
728  qof_param = params->qof_param;
729  full_path = NULL;
730  g_return_if_fail (params && path && content);
731  n = kvp_value_get_type (content);
732  switch (n)
733  {
734  case KVP_TYPE_GINT64:
735  case KVP_TYPE_DOUBLE:
736  case KVP_TYPE_NUMERIC:
737  case KVP_TYPE_STRING:
738  case KVP_TYPE_GUID:
739  case KVP_TYPE_TIME :
740  case KVP_TYPE_BOOLEAN :
741  case KVP_TYPE_BINARY:
742  case KVP_TYPE_GLIST:
743  {
744  node =
745  xmlAddChild (params->output_node,
746  xmlNewNode (params->qsf_ns,
747  BAD_CAST qof_param->param_type));
748  xmlNodeAddContent (node,
749  BAD_CAST kvp_value_to_bare_string (content));
750  xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
751  BAD_CAST qof_param->param_name);
752  full_path =
753  g_strconcat (params->full_kvp_path, "/", path, NULL);
754  xmlNewProp (node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST full_path);
755  xmlNewProp (node, BAD_CAST QSF_OBJECT_VALUE,
756  BAD_CAST kvp_value_to_qof_type_helper (n));
757  break;
758  }
759  case KVP_TYPE_FRAME:
760  {
761  if (!params->full_kvp_path)
762  params->full_kvp_path = g_strdup (path);
763  else
764  params->full_kvp_path = g_strconcat (params->full_kvp_path,
765  "/", path, NULL);
767  qsf_from_kvp_helper, params);
768  g_free (params->full_kvp_path);
769  params->full_kvp_path = NULL;
770  break;
771  }
772  default:
773  {
774  PERR (" unsupported value = %d", kvp_value_get_type (content));
775  break;
776  }
777  }
778 }
779 
780 static void
781 qsf_from_coll_cb (QofEntity * ent, gpointer user_data)
782 {
783  QsfParam *params;
784  QofParam *qof_param;
785  xmlNodePtr node;
786  gchar qsf_guid[GUID_ENCODING_LENGTH + 1];
787 
788  params = (QsfParam *) user_data;
789  if (!ent || !params)
790  return;
791  qof_param = params->qof_param;
792  guid_to_string_buff (qof_entity_get_guid (ent), qsf_guid);
793  node = xmlAddChild (params->output_node, xmlNewNode (params->qsf_ns,
794  BAD_CAST qof_param->param_type));
795  xmlNodeAddContent (node, BAD_CAST qsf_guid);
796  xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
797  BAD_CAST qof_param->param_name);
798 }
799 
800 /******* reference handling ***********/
801 
802 static gint
803 qof_reference_list_cb (gconstpointer a, gconstpointer b)
804 {
805  const QofEntityReference *aa;
806  const QofEntityReference *bb;
807 
808  aa = (QofEntityReference *) a;
809  bb = (QofEntityReference *) b;
810  if (aa == NULL)
811  return 1;
812  g_return_val_if_fail ((bb != NULL), 1);
813  g_return_val_if_fail ((aa->type != NULL), 1);
814  if ((0 == guid_compare (bb->ent_guid, aa->ent_guid))
815  && (0 == safe_strcmp (bb->type, aa->type))
816  && (0 == safe_strcmp (bb->param->param_name,
817  aa->param->param_name)))
818  return 0;
819  return 1;
820 }
821 
822 static QofEntityReference *
823 qof_reference_lookup (GList * referenceList, QofEntityReference * find)
824 {
825  GList *single_ref;
826  QofEntityReference *ent_ref;
827 
828  if (referenceList == NULL)
829  return NULL;
830  g_return_val_if_fail (find != NULL, NULL);
831  single_ref = NULL;
832  ent_ref = NULL;
833  single_ref =
834  g_list_find_custom (referenceList, find, qof_reference_list_cb);
835  if (single_ref == NULL)
836  return ent_ref;
837  ent_ref = (QofEntityReference *) single_ref->data;
838  g_list_free (single_ref);
839  return ent_ref;
840 }
841 
842 static void
843 reference_list_lookup (gpointer data, gpointer user_data)
844 {
845  QofEntity *ent;
846  QofParam *ref_param;
847  QofEntityReference *reference, *starter;
848  QsfParam *params;
849  const GUID *guid;
850  xmlNodePtr node, object_node;
851  xmlNsPtr ns;
852  GList *copy_list;
853  gchar qsf_guid[GUID_ENCODING_LENGTH + 1], *ref_name;
854 
855  params = (QsfParam *) user_data;
856  ref_param = (QofParam *) data;
857  object_node = params->output_node;
858  ent = params->qsf_ent;
859  ns = params->qsf_ns;
860  starter = g_new0 (QofEntityReference, 1);
861  starter->ent_guid = qof_entity_get_guid (ent);
862  starter->type = g_strdup (ent->e_type);
863  starter->param = ref_param;
864  starter->ref_guid = NULL;
865  copy_list = g_list_copy (params->referenceList);
866  reference = qof_reference_lookup (copy_list, starter);
867  g_free (starter);
868  if (reference != NULL)
869  {
870  if ((ref_param->param_getfcn == NULL)
871  || (ref_param->param_setfcn == NULL))
872  return;
873  ref_name = g_strdup (reference->param->param_name);
874  node =
875  xmlAddChild (object_node,
876  xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
877  guid_to_string_buff (reference->ref_guid, qsf_guid);
878  xmlNodeAddContent (node, BAD_CAST qsf_guid);
879  xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST ref_name);
880  g_free (ref_name);
881  }
882  else
883  {
884  ent = (QofEntity *) ref_param->param_getfcn (ent, ref_param);
885  if (!ent)
886  return;
887  if ((0 == safe_strcmp (ref_param->param_type, QOF_TYPE_COLLECT)) ||
888  (0 == safe_strcmp (ref_param->param_type, QOF_TYPE_CHOICE)))
889  return;
890  node =
891  xmlAddChild (object_node,
892  xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
893  guid = qof_entity_get_guid (ent);
894  guid_to_string_buff (guid, qsf_guid);
895  xmlNodeAddContent (node, BAD_CAST qsf_guid);
896  xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
897  BAD_CAST ref_param->param_name);
898  }
899 }
900 
901 /*=====================================
902  Convert QofEntity to QSF XML node
903 qof_param holds the parameter sequence.
904 =======================================*/
905 static void
906 qsf_entity_foreach (QofEntity * ent, gpointer data)
907 {
908  QsfParam *params;
909  GSList *param_list, *supported;
910  GList *ref;
911  xmlNodePtr node, object_node;
912  xmlNsPtr ns;
913  gchar *string_buffer;
914  QofParam *qof_param;
915  QofEntity *choice_ent;
916  KvpFrame *qsf_kvp;
917  QofCollection *qsf_coll;
918  gint param_count;
919  gboolean own_guid;
920  const GUID *cm_guid;
921  gchar cm_sa[GUID_ENCODING_LENGTH + 1];
922 
923  g_return_if_fail (data != NULL);
924  params = (QsfParam *) data;
925  param_count = ++params->count;
926  ns = params->qsf_ns;
927  qsf_kvp = NULL;
928  own_guid = FALSE;
929  choice_ent = NULL;
930  object_node = xmlNewChild (params->book_node, params->qsf_ns,
931  BAD_CAST QSF_OBJECT_TAG, NULL);
932  xmlNewProp (object_node, BAD_CAST QSF_OBJECT_TYPE,
933  BAD_CAST ent->e_type);
934  string_buffer = g_strdup_printf ("%i", param_count);
935  xmlNewProp (object_node, BAD_CAST QSF_OBJECT_COUNT,
936  BAD_CAST string_buffer);
937  g_free (string_buffer);
938  param_list = g_slist_copy (params->qsf_sequence);
939  while (param_list != NULL)
940  {
941  qof_param = (QofParam *) param_list->data;
942  g_return_if_fail (qof_param != NULL);
943  if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_GUID))
944  {
945  if (!own_guid)
946  {
947  cm_guid = qof_entity_get_guid (ent);
948  node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
949  QOF_TYPE_GUID));
950  guid_to_string_buff (cm_guid, cm_sa);
951  string_buffer = g_strdup (cm_sa);
952  xmlNodeAddContent (node, BAD_CAST string_buffer);
953  xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
954  QOF_PARAM_GUID);
955  g_free (string_buffer);
956  own_guid = TRUE;
957  }
958  params->qsf_ent = ent;
959  params->output_node = object_node;
960  ref = qof_class_get_referenceList (ent->e_type);
961  if (ref != NULL)
962  g_list_foreach (ref, reference_list_lookup, params);
963  }
964  if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_COLLECT))
965  {
966  qsf_coll = qof_param->param_getfcn (ent, qof_param);
967  if (qsf_coll)
968  {
969  params->qof_param = qof_param;
970  params->output_node = object_node;
971  if (qof_collection_count (qsf_coll) > 0)
972  qof_collection_foreach (qsf_coll, qsf_from_coll_cb,
973  params);
974  }
975  param_list = g_slist_next (param_list);
976  continue;
977  }
978  if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_CHOICE))
979  {
981  choice_ent =
982  (QofEntity *) qof_param->param_getfcn (ent, qof_param);
983  if (!choice_ent)
984  {
985  param_list = g_slist_next (param_list);
986  continue;
987  }
988  node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
989  qof_param->param_type));
990  cm_guid = qof_entity_get_guid (choice_ent);
991  guid_to_string_buff (cm_guid, cm_sa);
992  string_buffer = g_strdup (cm_sa);
993  xmlNodeAddContent (node, BAD_CAST string_buffer);
994  xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
995  qof_param->param_name);
996  xmlNewProp (node, BAD_CAST "name",
997  BAD_CAST choice_ent->e_type);
998  g_free (string_buffer);
999  param_list = g_slist_next (param_list);
1000  continue;
1001  }
1002  if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_KVP))
1003  {
1004  qsf_kvp =
1005  (KvpFrame *) qof_param->param_getfcn (ent, qof_param);
1006  if (kvp_frame_is_empty (qsf_kvp))
1007  return;
1008  params->qof_param = qof_param;
1009  params->output_node = object_node;
1010  kvp_frame_for_each_slot (qsf_kvp, qsf_from_kvp_helper, params);
1011  }
1012  if ((qof_param->param_setfcn != NULL)
1013  && (qof_param->param_getfcn != NULL))
1014  {
1015  for (supported = g_slist_copy (params->supported_types);
1016  supported != NULL; supported = g_slist_next (supported))
1017  {
1018  if (0 == safe_strcmp ((const gchar *) supported->data,
1019  (const gchar *) qof_param->param_type))
1020  {
1021  node = xmlAddChild (object_node,
1022  xmlNewNode (ns, BAD_CAST qof_param->param_type));
1023  string_buffer =
1024  g_strdup (qof_util_param_to_string
1025  (ent, qof_param));
1026  xmlNodeAddContent (node, BAD_CAST string_buffer);
1027  xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
1028  qof_param->param_name);
1029  g_free (string_buffer);
1030  }
1031  }
1032  }
1033  param_list = g_slist_next (param_list);
1034  }
1035 }
1036 
1037 static void
1038 qsf_foreach_obj_type (QofObject * qsf_obj, gpointer data)
1039 {
1040  QsfParam *params;
1041  QofBook *book;
1042  GSList *support;
1043 
1044  g_return_if_fail (data != NULL);
1045  params = (QsfParam *) data;
1046  /* Skip unsupported objects */
1047  if ((qsf_obj->create == NULL) || (qsf_obj->foreach == NULL))
1048  {
1049  PINFO (" qsf_obj QOF support failed %s", qsf_obj->e_type);
1050  return;
1051  }
1052  params->qof_obj_type = qsf_obj->e_type;
1053  params->qsf_sequence = NULL;
1054  book = params->book;
1055  support = g_slist_copy (params->supported_types);
1056  g_slist_foreach (support, qsf_supported_parameters, params);
1057  qof_object_foreach (qsf_obj->e_type, book, qsf_entity_foreach, params);
1058 }
1059 
1060 /*=====================================================
1061  Take a QofBook and prepare a QSF XML doc in memory
1062 =======================================================*/
1063 /* QSF only uses one QofBook per file - count may be removed later. */
1064 static xmlDocPtr
1065 qofbook_to_qsf (QofBook * book, QsfParam * params)
1066 {
1067  xmlNodePtr top_node, node;
1068  xmlDocPtr doc;
1069  gchar buffer[GUID_ENCODING_LENGTH + 1];
1070  const GUID *book_guid;
1071 
1072  g_return_val_if_fail (book != NULL, NULL);
1073  params->book = book;
1074  params->referenceList =
1075  g_list_copy ((GList *) qof_book_get_data (book,
1076  ENTITYREFERENCE));
1077  doc = xmlNewDoc (BAD_CAST QSF_XML_VERSION);
1078  top_node = xmlNewNode (NULL, BAD_CAST QSF_ROOT_TAG);
1079  xmlDocSetRootElement (doc, top_node);
1080  xmlSetNs (top_node, xmlNewNs (top_node, BAD_CAST QSF_DEFAULT_NS,
1081  NULL));
1082  params->qsf_ns = top_node->ns;
1083  node =
1084  xmlNewChild (top_node, params->qsf_ns, BAD_CAST QSF_BOOK_TAG,
1085  NULL);
1086  params->book_node = node;
1087  xmlNewProp (node, BAD_CAST QSF_BOOK_COUNT, BAD_CAST "1");
1088  book_guid = qof_entity_get_guid ((QofEntity*)book);
1089  guid_to_string_buff (book_guid, buffer);
1090  xmlNewChild (params->book_node, params->qsf_ns,
1091  BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
1092  params->output_doc = doc;
1093  params->book_node = node;
1094  qof_object_foreach_type (qsf_foreach_obj_type, params);
1095  return params->output_doc;
1096 }
1097 
1098 static void
1099 write_qsf_from_book (const gchar *path, QofBook * book,
1100  QsfParam * params)
1101 {
1102  xmlDocPtr qsf_doc;
1103  gint write_result;
1104  QofBackend *be;
1105 
1106  be = qof_book_get_backend (book);
1107  qsf_doc = qofbook_to_qsf (book, params);
1108  write_result = 0;
1109  PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
1110  params->use_gz_level, params->encoding);
1111  if ((params->use_gz_level > 0) && (params->use_gz_level <= 9))
1112  xmlSetDocCompressMode (qsf_doc, params->use_gz_level);
1113  g_return_if_fail (qsf_is_valid
1114  (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
1115  write_result =
1116  xmlSaveFormatFileEnc (path, qsf_doc, params->encoding, 1);
1117  if (write_result < 0)
1118  {
1119  qof_error_set_be (be, qof_error_register
1120  (_("Could not write to '%s'. Check that you have "
1121  "permission to write to this file and that there is "
1122  "sufficient space to create it."), TRUE));
1123  return;
1124  }
1125  qof_object_mark_clean (book);
1126 }
1127 
1128 static void
1129 write_qsf_to_stdout (QofBook * book, QsfParam * params)
1130 {
1131  xmlDocPtr qsf_doc;
1132 
1133  qsf_doc = qofbook_to_qsf (book, params);
1134  g_return_if_fail (qsf_is_valid
1135  (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
1136  PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
1137  params->use_gz_level, params->encoding);
1138  xmlSaveFormatFileEnc ("-", qsf_doc, params->encoding, 1);
1139  fprintf (stdout, "\n");
1140  qof_object_mark_clean (book);
1141 }
1142 
1143 static void
1144 qsf_write_file (QofBackend * be, QofBook * book)
1145 {
1146  QSFBackend *qsf_be;
1147  QsfParam *params;
1148  gchar *path;
1149 
1150  qsf_be = (QSFBackend *) be;
1151  params = qsf_be->params;
1152  /* if fullpath is blank, book_id was set to QOF_STDOUT */
1153  if (!qsf_be->fullpath || (*qsf_be->fullpath == '\0'))
1154  {
1155  write_qsf_to_stdout (book, params);
1156  return;
1157  }
1158  path = strdup (qsf_be->fullpath);
1159  write_qsf_from_book (path, book, params);
1160  g_free (path);
1161 }
1162 
1163 KvpValue *
1164 string_to_kvp_value (const gchar * content, KvpValueType type)
1165 {
1166  gchar *tail;
1167  gint64 cm_i64;
1168  gdouble cm_double;
1169  QofNumeric cm_numeric;
1170  GUID *cm_guid;
1171 
1172  switch (type)
1173  {
1174  case KVP_TYPE_GINT64:
1175  {
1176  errno = 0;
1177  cm_i64 = strtoll (content, &tail, 0);
1178  if (errno == 0)
1179  {
1180  return kvp_value_new_gint64 (cm_i64);
1181  }
1182  break;
1183  }
1184  case KVP_TYPE_DOUBLE:
1185  {
1186  errno = 0;
1187  cm_double = strtod (content, &tail);
1188  if (errno == 0)
1189  return kvp_value_new_double (cm_double);
1190  break;
1191  }
1192  case KVP_TYPE_NUMERIC:
1193  {
1194  qof_numeric_from_string (content, &cm_numeric);
1195  return kvp_value_new_numeric (cm_numeric);
1196  break;
1197  }
1198  case KVP_TYPE_STRING:
1199  {
1200  return kvp_value_new_string (content);
1201  break;
1202  }
1203  case KVP_TYPE_GUID:
1204  {
1205  cm_guid = g_new0 (GUID, 1);
1206  if (TRUE == string_to_guid (content, cm_guid))
1207  return kvp_value_new_guid (cm_guid);
1208  break;
1209  }
1210  case KVP_TYPE_TIME :
1211  {
1212  QofDate *qd;
1213  QofTime *qt;
1214  KvpValue *retval;
1215 
1216  qd = qof_date_parse (content, QOF_DATE_FORMAT_UTC);
1217  if(qd)
1218  {
1219  qt = qof_date_to_qtime (qd);
1220  retval = kvp_value_new_time (qt);
1221  qof_date_free (qd);
1222  qof_time_free (qt);
1223  return retval;
1224  }
1225  else
1226  PERR (" failed to parse date");
1227  }
1228  case KVP_TYPE_BOOLEAN :
1229  {
1230  gboolean val;
1231  val = qof_util_bool_to_int (content);
1232  return kvp_value_new_boolean (val);
1233  }
1234  case KVP_TYPE_BINARY:
1235 // return kvp_value_new_binary(value->value.binary.data,
1236 // value->value.binary.datasize);
1237  break;
1238  case KVP_TYPE_GLIST:
1239 // return kvp_value_new_glist(value->value.list);
1240  break;
1241  case KVP_TYPE_FRAME:
1242 // return kvp_value_new_frame(value->value.frame);
1243  break;
1244  }
1245  return NULL;
1246 }
1247 
1248 /* ======================================================
1249  Commit XML data from file to QofEntity in a QofBook
1250 ========================================================= */
1251 void
1252 qsf_object_commitCB (gpointer key, gpointer value, gpointer data)
1253 {
1254  QsfParam *params;
1255  QsfObject * G_GNUC_UNUSED object_set;
1256  xmlNodePtr node;
1257  QofEntityReference *reference;
1258  QofEntity *qsf_ent;
1259  QofBook * G_GNUC_UNUSED targetBook;
1260  const gchar *qof_type, *parameter_name;
1261  QofIdType obj_type, reference_type;
1262  gchar *tail;
1263  /* cm_ prefix used for variables that hold the data to commit */
1264  QofNumeric cm_numeric;
1265  gdouble cm_double;
1266  gboolean cm_boolean;
1267  gint32 cm_i32;
1268  gint64 cm_i64;
1269  gchar cm_char, (*char_getter) (xmlNodePtr);
1270  GUID *cm_guid;
1271  KvpFrame *cm_kvp;
1272  KvpValue *cm_value;
1273  KvpValueType cm_type;
1274  QofSetterFunc cm_setter;
1275  const QofParam *cm_param;
1276  void (*string_setter) (QofEntity *, const gchar *);
1277  void (*time_setter) (QofEntity *, QofTime *);
1278  void (*numeric_setter) (QofEntity *, QofNumeric);
1279  void (*double_setter) (QofEntity *, gdouble);
1280  void (*boolean_setter) (QofEntity *, gboolean);
1281  void (*i32_setter) (QofEntity *, gint32);
1282  void (*i64_setter) (QofEntity *, gint64);
1283  void (*char_setter) (QofEntity *, gchar);
1284 
1285  g_return_if_fail (data && value && key);
1286  params = (QsfParam *) data;
1287  node = (xmlNodePtr) value;
1288  parameter_name = (const gchar *) key;
1289  qof_type = (gchar *) node->name;
1290  qsf_ent = params->qsf_ent;
1291  targetBook = params->book;
1292  obj_type =
1293  (gchar *) xmlGetProp (node->parent, BAD_CAST QSF_OBJECT_TYPE);
1294  if (0 == safe_strcasecmp (obj_type, parameter_name))
1295  {
1296  return;
1297  }
1298  cm_setter = qof_class_get_parameter_setter (obj_type, parameter_name);
1299  cm_param = qof_class_get_parameter (obj_type, parameter_name);
1300  object_set = params->object_set;
1301  if (safe_strcmp (qof_type, QOF_TYPE_STRING) == 0)
1302  {
1303  string_setter = (void (*)(QofEntity *, const gchar *)) cm_setter;
1304  if (string_setter != NULL)
1305  {
1306  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1307  string_setter (qsf_ent, (gchar *) xmlNodeGetContent (node));
1308  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1309  }
1310  }
1311  if (safe_strcmp (qof_type, QOF_TYPE_TIME) == 0)
1312  {
1313  time_setter = (void (*)(QofEntity *, QofTime*)) cm_setter;
1314  if (time_setter != NULL)
1315  {
1316  QofDate *qd;
1317  QofTime *qt;
1318 
1319  qd = qof_date_parse (
1320  (const gchar*) xmlNodeGetContent (node),
1322  if(qd)
1323  {
1324  qt = qof_date_to_qtime (qd);
1325  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1326  time_setter (qsf_ent, qt);
1327  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1328  qof_date_free (qd);
1329  }
1330  else
1331  PERR (" failed to parse date string");
1332  }
1333  }
1334  if ((safe_strcmp (qof_type, QOF_TYPE_NUMERIC) == 0) ||
1335  (safe_strcmp (qof_type, QOF_TYPE_DEBCRED) == 0))
1336  {
1337  gchar *tmp;
1338  numeric_setter = (void (*)(QofEntity *, QofNumeric)) cm_setter;
1339  tmp = (char *) xmlNodeGetContent (node);
1340  qof_numeric_from_string (tmp, &cm_numeric);
1341  g_free (tmp);
1342  if (numeric_setter != NULL)
1343  {
1344  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1345  numeric_setter (qsf_ent, cm_numeric);
1346  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1347  }
1348  }
1349  if (safe_strcmp (qof_type, QOF_TYPE_GUID) == 0)
1350  {
1351  cm_guid = g_new0 (GUID, 1);
1352  if (TRUE !=
1353  string_to_guid ((gchar *) xmlNodeGetContent (node), cm_guid))
1354  {
1355  qof_error_set_be (params->be, qof_error_register(
1356  _("The selected QSF object file '%s' contains one or "
1357  "more invalid GUIDs. The file cannot be processed - "
1358  "please check the source of the file and try again."),
1359  TRUE));
1360  PINFO (" string to guid conversion failed for %s:%s:%s",
1361  xmlNodeGetContent (node), obj_type, qof_type);
1362  return;
1363  }
1364  reference_type =
1365  (gchar *) xmlGetProp (node, BAD_CAST QSF_OBJECT_TYPE);
1366  if (0 == safe_strcmp (QOF_PARAM_GUID, reference_type))
1367  {
1368  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1369  qof_entity_set_guid (qsf_ent, cm_guid);
1370  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1371  }
1372  else
1373  {
1374  reference = qof_entity_get_reference_from (qsf_ent, cm_param);
1375  if (reference)
1376  {
1377  params->referenceList =
1378  g_list_append (params->referenceList, reference);
1379  }
1380  }
1381  }
1382  if (safe_strcmp (qof_type, QOF_TYPE_INT32) == 0)
1383  {
1384  errno = 0;
1385  cm_i32 =
1386  (gint32) strtol ((char *) xmlNodeGetContent (node), &tail, 0);
1387  if (errno == 0)
1388  {
1389  i32_setter = (void (*)(QofEntity *, gint32)) cm_setter;
1390  if (i32_setter != NULL)
1391  {
1392  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1393  i32_setter (qsf_ent, cm_i32);
1394  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1395  }
1396  }
1397  else
1398  qof_error_set_be (params->be, params->err_overflow);
1399  }
1400  if (safe_strcmp (qof_type, QOF_TYPE_INT64) == 0)
1401  {
1402  errno = 0;
1403  cm_i64 = strtoll ((gchar *) xmlNodeGetContent (node), &tail, 0);
1404  if (errno == 0)
1405  {
1406  i64_setter = (void (*)(QofEntity *, gint64)) cm_setter;
1407  if (i64_setter != NULL)
1408  {
1409  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1410  i64_setter (qsf_ent, cm_i64);
1411  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1412  }
1413  }
1414  else
1415  qof_error_set_be (params->be, params->err_overflow);
1416  }
1417  if (safe_strcmp (qof_type, QOF_TYPE_DOUBLE) == 0)
1418  {
1419  errno = 0;
1420  cm_double = strtod ((gchar *) xmlNodeGetContent (node), &tail);
1421  if (errno == 0)
1422  {
1423  double_setter = (void (*)(QofEntity *, gdouble)) cm_setter;
1424  if (double_setter != NULL)
1425  {
1426  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1427  double_setter (qsf_ent, cm_double);
1428  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1429  }
1430  }
1431  }
1432  if (safe_strcmp (qof_type, QOF_TYPE_BOOLEAN) == 0)
1433  {
1434  if (0 == safe_strcasecmp ((gchar *) xmlNodeGetContent (node),
1436  cm_boolean = TRUE;
1437  else
1438  cm_boolean = FALSE;
1439  boolean_setter = (void (*)(QofEntity *, gboolean)) cm_setter;
1440  if (boolean_setter != NULL)
1441  {
1442  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1443  boolean_setter (qsf_ent, cm_boolean);
1444  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1445  }
1446  }
1447  if (safe_strcmp (qof_type, QOF_TYPE_KVP) == 0)
1448  {
1449  cm_type =
1450  qsf_to_kvp_helper ((gchar *)
1451  xmlGetProp (node, BAD_CAST QSF_OBJECT_VALUE));
1452  if (!cm_type)
1453  return;
1454  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1455  cm_value =
1456  string_to_kvp_value ((gchar *) xmlNodeGetContent (node),
1457  cm_type);
1458  cm_kvp = (KvpFrame *) cm_param->param_getfcn (qsf_ent, cm_param);
1459  cm_kvp = kvp_frame_set_value (cm_kvp, (gchar *) xmlGetProp (node,
1460  BAD_CAST QSF_OBJECT_KVP), cm_value);
1461  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1462  g_free (cm_value);
1463  }
1464  if (safe_strcmp (qof_type, QOF_TYPE_COLLECT) == 0)
1465  {
1466  QofCollection *qsf_coll;
1467  QofIdType G_GNUC_UNUSED type;
1468  QofEntityReference *reference;
1469  QofParam *copy_param;
1470  /* retrieve the *type* of the collection, ignore any contents. */
1471  qsf_coll = cm_param->param_getfcn (qsf_ent, cm_param);
1472  type = qof_collection_get_type (qsf_coll);
1473  cm_guid = g_new0 (GUID, 1);
1474  if (TRUE !=
1475  string_to_guid ((gchar *) xmlNodeGetContent (node), cm_guid))
1476  {
1477  qof_error_set_be (params->be, (qof_error_register(
1478  _("The selected QSF object file '%s' contains one or "
1479  "more invalid 'collect' values. The file cannot be processed - "
1480  "please check the source of the file and try again."),
1481  TRUE)));
1482  PINFO (" string to guid collect failed for %s",
1483  xmlNodeGetContent (node));
1484  return;
1485  }
1486  /* create a QofEntityReference with this type and GUID.
1487  there is only one entity each time.
1488  cm_guid contains the GUID of the reference.
1489  type is the type of the reference. */
1490  reference = g_new0 (QofEntityReference, 1);
1491  reference->type = g_strdup (qsf_ent->e_type);
1492  reference->ref_guid = cm_guid;
1493  reference->ent_guid = &qsf_ent->guid;
1494  copy_param = g_new0 (QofParam, 1);
1495  copy_param->param_name = g_strdup (cm_param->param_name);
1496  copy_param->param_type = g_strdup (cm_param->param_type);
1497  reference->param = copy_param;
1498  params->referenceList =
1499  g_list_append (params->referenceList, reference);
1500  }
1501  if (safe_strcmp (qof_type, QOF_TYPE_CHAR) == 0)
1502  {
1503  char_getter = (gchar (*)(xmlNodePtr)) xmlNodeGetContent;
1504  cm_char = char_getter (node);
1505  char_setter = (void (*)(QofEntity *, gchar)) cm_setter;
1506  if (char_setter != NULL)
1507  {
1508  qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1509  char_setter (qsf_ent, cm_char);
1510  qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1511  }
1512  }
1513 }
1514 
1515 static QofBackend *
1516 qsf_backend_new (void)
1517 {
1518  QSFBackend *qsf_be;
1519  QofBackend *be;
1520 
1521  qsf_be = g_new0 (QSFBackend, 1);
1522  be = (QofBackend *) qsf_be;
1523  qof_backend_init (be);
1524  qsf_be->params = g_new0 (QsfParam, 1);
1525  qsf_be->params->be = be;
1526  qsf_param_init (qsf_be->params);
1527  qsf_be->be.session_begin = qsf_session_begin;
1528 
1529  be->session_end = qsf_session_end;
1530  be->destroy_backend = qsf_destroy_backend;
1531  be->load = qsf_file_type;
1532  be->save_may_clobber_data = NULL;
1533  /* The QSF backend will always load and save the entire QSF XML file. */
1534  be->begin = NULL;
1535  be->commit = NULL;
1536  be->rollback = NULL;
1537  /* QSF uses the built-in SQL, not a dedicated SQL server. */
1538  be->compile_query = NULL;
1539  be->free_query = NULL;
1540  be->run_query = NULL;
1541  be->counter = NULL;
1542  /* The QSF backend is not multi-user. */
1543  be->events_pending = NULL;
1544  be->process_events = NULL;
1545 
1546  be->sync = qsf_write_file;
1547  /* use for maps, later. */
1548  be->load_config = qsf_load_config;
1549  be->get_config = qsf_get_config;
1550 
1551  qsf_be->fullpath = NULL;
1552  return be;
1553 }
1554 
1555 /* The QOF method of loading each backend.
1556 QSF is loaded as a GModule using the QOF method - QofBackendProvider.
1557 */
1558 static void
1559 qsf_provider_free (QofBackendProvider * prov)
1560 {
1561  prov->provider_name = NULL;
1562  prov->access_method = NULL;
1563  g_free (prov);
1564 }
1565 
1566 void
1568 {
1569  QofBackendProvider *prov;
1570 
1571  bindtextdomain (PACKAGE, LOCALE_DIR);
1572  prov = g_new0 (QofBackendProvider, 1);
1573  prov->provider_name = "QSF Backend Version 0.4";
1574  prov->access_method = "file";
1575  prov->partial_book_supported = TRUE;
1576  prov->backend_new = qsf_backend_new;
1577  prov->check_data_type = qsf_determine_file_type;
1578  prov->provider_free = qsf_provider_free;
1580 }
QSF Parameters.
Definition: qsf-xml.h:469
xmlNsPtr qsf_ns
Definition: qsf-xml.h:507
Private KVP utilities for backends etc.
#define QOF_DATE_FORMAT_UTC
QOF UTC format, xsd:date compatible. QOF_UTC_DATE_FORMAT "%Y-%m-%dT%H:%M:%SZ".
Definition: qofdate.h:277
QofErrorId qof_error_register(const gchar *err_message, gboolean use_file)
Generate and register a new error.
Definition: qoferror.c:73
gchar * fullpath
Definition: qofbackend-p.h:332
gboolean(* save_may_clobber_data)(QofBackend *)
Definition: qofbackend-p.h:320
#define PERR(format, args...)
Definition: qoflog.h:183
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
Definition: qofobject.c:42
const GUID * ent_guid
Definition: qofreference.h:115
gchar * full_kvp_path
Definition: qsf-xml.h:537
gchar * qof_time_stamp_now(void)
Definition: qoftime.c:469
#define QOF_DATE_FORMAT_ISO
Short ISO form. "%F".
Definition: qofdate.h:268
#define QOF_TYPE_COLLECT
secondary collections are used for one-to-many references between entities and are implemented using ...
Definition: qofclass.h:121
#define QSF_DATE_CONVERT
Convert QOF_TYPE_DATE to QOF_TYPE_TIME.
const gchar * QofIdType
Definition: qofid.h:81
#define PINFO(format, args...)
Definition: qoflog.h:199
QofCollection * qof_book_get_collection(QofBook *book, QofIdType entity_type)
Definition: qofbook.c:220
gboolean qof_class_is_registered(QofIdTypeConst obj_name)
Definition: qofclass.c:133
#define QSF_OBJECT_COUNT
Definition: qsf-xml.h:105
struct _QofNumeric QofNumeric
A rational-number type.
Definition: qofnumeric.h:61
void qof_date_free(QofDate *date)
Definition: qofdate.c:642
#define QSF_OBJECT_KVP
Definition: qsf-xml.h:127
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
Definition: qofclass.c:268
void qof_backend_register_provider(QofBackendProvider *)
Definition: qofsession.c:59
#define QSF_ROOT_TAG
Definition: qsf-xml.h:81
gboolean is_qsf_object(const gchar *path)
Validate a QSF file and identify a suitable QSF map.
Definition: qsf-xml.c:218
QofSetterFunc qof_class_get_parameter_setter(QofIdTypeConst obj_name, const gchar *parameter)
Definition: qofclass.c:183
QofIdTypeConst kvp_value_type_to_qof_id(KvpValueType n)
Convert a KvpValueType to a QofIdType.
Definition: kvputil.c:246
QofDate * qof_date_get_current(void)
Definition: qofdate.c:616
KvpValueType
possible types in the union KvpValue
Definition: kvpframe.h:87
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofEntityForeachCB cb, gpointer user_data)
Definition: qofobject.c:174
gboolean string_to_guid(const gchar *string, GUID *guid)
Unique identifier.
Definition: kvpframe.h:118
gint count
Definition: qsf-xml.h:476
const gchar * description
Definition: qofbackend.h:119
QsfType file_type
Definition: qsf-xml.h:472
gboolean knowntype
Definition: qsf-xml.h:521
gpointer qof_book_get_data(QofBook *book, const gchar *key)
Definition: qofbook.c:212
gboolean qsf_is_valid(const gchar *schema_dir, const gchar *schema_filename, xmlDocPtr doc)
Compares an xmlDoc in memory against the schema file.
Definition: qsf-xml.c:74
gboolean partial_book_supported
Partial QofBook handler.
Definition: qofbackend-p.h:254
gint32 QofErrorId
The ID of this error.
Definition: qofbackend.h:54
QofEntity * qsf_ent
Definition: qsf-xml.h:517
struct _KvpFrame KvpFrame
Definition: kvpframe.h:74
gint safe_strcasecmp(const gchar *da, const gchar *db)
Definition: qofutil.c:95
gchar * qof_date_print(const QofDate *date, QofDateFormat df)
Convert a QofDate to a timestamp according to the specified date format.
Definition: qofdate.c:581
gboolean is_qsf_object_be(QsfParam *params)
Validate a QSF file and identify a suitable QSF map.
Definition: qsf-xml.c:298
QofBackend * be
Definition: qsf-xml.h:519
#define QSF_OBJECT_TAG
Definition: qsf-xml.h:101
KvpValue * kvp_value_new_boolean(gboolean value)
Definition: kvpframe.c:1223
QofErrorId qof_error_check_be(QofBackend *be)
Check for errors.
Definition: qoferror.c:204
GSList * qsf_sequence
Definition: qsf-xml.h:480
KvpFrame * qof_backend_complete_frame(QofBackend *be)
Definition: qofbackend.c:183
gpointer(* create)(QofBook *)
Definition: qofobject.h:80
Private QSF header - not for use by applications.
gint qof_util_bool_to_int(const gchar *val)
Definition: qofutil.c:252
gboolean kvp_frame_is_empty(KvpFrame *frame)
Definition: kvpframe.c:134
#define QSF_BOOK_COUNT
Definition: qsf-xml.h:99
#define LEAVE(format, args...)
Definition: qoflog.h:227
#define GUID_ENCODING_LENGTH
Definition: guid.h:64
#define QSF_OBJECT_TYPE
Definition: qsf-xml.h:103
QofTime * qof_date_to_qtime(const QofDate *qd)
Definition: qofdate.c:926
Full range replacement for struct tm.
Definition: qofdate.h:138
KvpFrame * kvp_frame_set_value(KvpFrame *frame, const gchar *key_path, const KvpValue *value)
Copy the KvpValue into the frame.
Definition: kvpframe.c:496
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:151
QofTime * qof_time_get_current(void)
Get the current QofTime.
Definition: qoftime.c:362
128bit denominator/numerator maths.
Definition: kvpframe.h:106
the Core Object Registration/Lookup Private Interface
struct QofCollection_s QofCollection
Definition: qofid.h:138
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const gchar *parameter)
Definition: qofclass.c:147
gboolean qof_util_param_edit(QofInstance *inst, const QofParam *param)
Prepare to edit a parameter.
Definition: qofutil.c:281
const gchar * encoding
Definition: qsf-xml.h:547
QofDate * qof_date_parse(const gchar *str, QofDateFormat df)
Convert a timestamp to a QofTime.
Definition: qofdate.c:557
struct _KvpValue KvpValue
Definition: kvpframe.h:78
gboolean is_our_qsf_object(const gchar *path)
Validate a QSF file.
Definition: qsf-xml.c:179
xmlDocPtr input_doc
Definition: qsf-xml.h:489
One iterator, two typedefs.
Definition: qsf-xml.h:689
guint qof_collection_count(QofCollection *col)
Definition: qofid.c:322
gchar * map_path
Definition: qsf-xml.h:535
#define QSF_BOOK_TAG
Definition: qsf-xml.h:94
#define QSF_XML_BOOLEAN_TEST
Definition: qsf-xml.h:417
gboolean qof_numeric_from_string(const gchar *str, QofNumeric *n)
Definition: qofnumeric.c:1116
QofEntity * qof_collection_lookup_entity(QofCollection *col, const GUID *guid)
Definition: qofid.c:292
GList ** qsf_map_prepare_list(GList **maps)
Prepare the default list of maps.
Definition: qsf-backend.c:167
QofEntityReference * qof_entity_get_reference_from(QofEntity *ent, const QofParam *param)
Get a reference from this entity to another entity.
Definition: qofreference.c:167
GList * qsf_object_list
Definition: qsf-xml.h:478
KvpValueType qof_id_to_kvp_value_type(QofIdTypeConst type_string)
Convert a QofIdType to a KvpValueType.
Definition: kvputil.c:228
void qof_time_free(QofTime *qt)
Free a QofTime when no longer required.
Definition: qoftime.c:56
void qof_backend_prepare_option(QofBackend *be, QofBackendOption *option)
Definition: qofbackend.c:101
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:392
#define QOF_SUCCESS
Definition: qoferror.h:124
GSList * supported_types
Definition: qsf-xml.h:487
64bit integer
Definition: kvpframe.h:94
void qsf_node_foreach(xmlNodePtr parent, QsfNodeCB cb, struct QsfNodeIterate *qsfiter, QsfParam *params)
Definition: qsf-xml.c:115
void qof_backend_option_foreach(KvpFrame *config, QofBackendOptionCB cb, gpointer data)
Definition: qofbackend.c:349
void(* provider_free)(QofBackendProvider *)
Definition: qofbackend-p.h:280
xmlNodePtr lister
Definition: qsf-xml.h:505
#define DEBUG(format, args...)
Definition: qoflog.h:208
QofBackend *(* backend_new)(void)
Definition: qofbackend-p.h:260
gchar * qof_util_param_to_string(QofEntity *ent, const QofParam *param)
Converts a parameter to a string for storage or display.
Definition: qofutil.c:464
KvpValue * string_to_kvp_value(const gchar *content, KvpValueType type)
Convert a string value into KvpValue.
Definition: qsf-backend.c:1164
gint64 convert
Definition: qsf-xml.h:549
const gchar * option_name
Definition: qofbackend.h:118
QSF API - Backend, maps, objects and configuration.
GList * referenceList
Definition: qsf-xml.h:482
gint64 use_gz_level
Definition: qsf-xml.h:539
gchar * guid_to_string_buff(const GUID *guid, gchar *buff)
gchar * kvp_value_to_bare_string(const KvpValue *val)
General purpose function to convert any KvpValue to a string.
Definition: kvpframe.c:1834
gboolean qof_util_param_commit(QofInstance *inst, const QofParam *param)
Commit this parameter change, with undo support.
Definition: qofutil.c:309
xmlNodePtr book_node
Definition: qsf-xml.h:503
void qof_book_set_data(QofBook *book, const gchar *key, gpointer data)
Definition: qofbook.c:191
QofParam * qof_param
Definition: qsf-xml.h:523
GHashTable * qsf_parameter_hash
Definition: qsf-xml.h:484
QofEntity entity
Definition: qofinstance-p.h:39
const QofParam * param
Definition: qofreference.h:113
GList * qof_class_get_referenceList(QofIdTypeConst type)
List of the parameters that could be references.
Definition: qofclass.c:329
const gchar * access_method
Definition: qofbackend-p.h:247
QofBook * book
Definition: qsf-xml.h:529
#define QSF_ENCODING
Encoding string.
void kvp_frame_for_each_slot(KvpFrame *f, KvpValueForeachCB proc, gpointer data)
Definition: kvpframe.c:1642
#define ENTITYREFERENCE
Definition: qofreference.h:137
QofIdType qof_collection_get_type(QofCollection *col)
Definition: qofid.c:146
Definition: guid.h:53
gboolean is_qsf_map_be(QsfParam *params)
Validate a QSF map file.
Definition: qsf-xml-map.c:318
gboolean(* check_data_type)(const gchar *)
Distinguish two providers with same access method.
Definition: qofbackend-p.h:277
gboolean is_qsf_map(const gchar *path)
Validate a QSF map file.
Definition: qsf-xml-map.c:370
GList * map_files
Definition: qsf-xml.h:545
#define QOF_STDOUT
Allow session data to be printed to stdout.
Definition: qofsession.h:385
QofIdType qof_obj_type
Definition: qsf-xml.h:511
const gchar * QofIdTypeConst
Definition: qofid.h:83
#define QSF_OBJECT_VALUE
Definition: qsf-xml.h:129
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
Definition: qoftime.h:112
gboolean is_our_qsf_object_be(QsfParam *params)
Validate a QSF file and determine type.
Definition: qsf-xml.c:242
Simple boolean type.
Definition: kvpframe.h:136
const GUID * qof_entity_get_guid(QofEntity *ent)
Definition: qofid.c:105
const gchar * tooltip
Definition: qofbackend.h:120
External references in a partial QofBook.
Definition: qofreference.h:105
QofBackend * qof_book_get_backend(QofBook *book)
Retrieve the backend used by this book.
Definition: qofbook.c:154
#define QSF_OBJECT_SCHEMA
Definition: qsf-xml.h:420
xmlNodePtr output_node
Definition: qsf-xml.h:499
gboolean qof_object_is_choice(QofIdType type)
Does this object contain a choice parameter?
Definition: qofchoice.c:45
standard C string
Definition: kvpframe.h:112
gchar * filepath
Definition: qsf-xml.h:533
Holds a description of the QofObject.
Definition: qsf-xml.h:63
void qof_entity_set_guid(QofEntity *ent, const GUID *guid)
Definition: qofid.c:92
const gchar * qof_type
Definition: qsf-xml.h:509
void(* foreach)(QofCollection *, QofEntityForeachCB, gpointer)
Definition: qofobject.h:105
gint safe_strcmp(const gchar *da, const gchar *db)
Definition: qofutil.c:75
KvpFrame * kvp_value_get_frame(const KvpValue *value)
Definition: kvpframe.c:1546
standard C double type
Definition: kvpframe.h:100
#define QSF_MAP_FILES
selected QSF maps
xmlDocPtr qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, QsfParam *params)
Convert between QSF objects.
Definition: qsf-xml-map.c:952
const gchar * provider_name
Definition: qofbackend-p.h:241
void qsf_book_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, QsfParam *params)
Book and book-guid node handler.
Definition: qsf-xml.c:423
#define QSF_DEFAULT_NS
Definition: qsf-xml.h:87
QsfObject * object_set
Definition: qsf-xml.h:474
#define QOF_TYPE_CHOICE
Identify an object as containing a choice.
Definition: qofchoice.h:103
#define ENTER(format, args...)
Definition: qoflog.h:217
xmlDocPtr output_doc
Definition: qsf-xml.h:491
void qof_object_foreach_type(QofForeachTypeCB cb, gpointer user_data)
Definition: qofobject.c:140
KvpValueType type
Definition: qofbackend.h:116
const gchar * QofLogModule
Definition: qofid.h:85
#define QSF_XML_VERSION
Definition: qsf-xml.h:107
64bit time/date handling.
Definition: kvpframe.h:124
#define QSF_BOOK_GUID
Definition: qsf-xml.h:97
#define QSF_COMPRESS
compression level
void qof_backend_prepare_frame(QofBackend *be)
Definition: qofbackend.c:89
void qsf_provider_init(void)
Describe this backend to the application.
Definition: qsf-backend.c:1567