00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include <glib.h>
00026 #include <libxml/xmlversion.h>
00027 #include <libxml/xmlmemory.h>
00028 #include <libxml/tree.h>
00029 #include <libxml/parser.h>
00030 #include <libxml/xmlschemas.h>
00031 #include "qof.h"
00032 #include "qof-backend-qsf.h"
00033 #include "qsf-dir.h"
00034 #include "qsf-xml.h"
00035
00036 static QofLogModule log_module = QOF_MOD_QSF;
00037
00038 gint
00039 qsf_compare_tag_strings (const xmlChar * node_name, gchar * tag_name)
00040 {
00041 return xmlStrcmp (node_name, (const xmlChar *) tag_name);
00042 }
00043
00044 gint
00045 qsf_strings_equal (const xmlChar * node_name, gchar * tag_name)
00046 {
00047 if (0 == qsf_compare_tag_strings (node_name, tag_name))
00048 {
00049 return 1;
00050 }
00051 return 0;
00052 }
00053
00054 gint
00055 qsf_is_element (xmlNodePtr a, xmlNsPtr ns, gchar * c)
00056 {
00057 g_return_val_if_fail (a != NULL, 0);
00058 g_return_val_if_fail (ns != NULL, 0);
00059 g_return_val_if_fail (c != NULL, 0);
00060 if ((a->ns == ns) && (a->type == XML_ELEMENT_NODE) &&
00061 qsf_strings_equal (a->name, c))
00062 {
00063 return 1;
00064 }
00065 return 0;
00066 }
00067
00068 gint
00069 qsf_check_tag (qsf_param * params, gchar * qof_type)
00070 {
00071 return qsf_is_element (params->child_node, params->qsf_ns, qof_type);
00072 }
00073
00074 gboolean
00075 qsf_is_valid (const gchar * schema_dir, const gchar * schema_filename,
00076 xmlDocPtr doc)
00077 {
00078 xmlSchemaParserCtxtPtr qsf_schema_file;
00079 xmlSchemaPtr qsf_schema;
00080 xmlSchemaValidCtxtPtr qsf_context;
00081 gchar *schema_path;
00082 gint result;
00083
00084 g_return_val_if_fail (doc || schema_filename, FALSE);
00085 schema_path = g_strdup_printf ("%s/%s", schema_dir, schema_filename);
00086 qsf_schema_file = xmlSchemaNewParserCtxt (schema_path);
00087 qsf_schema = xmlSchemaParse (qsf_schema_file);
00088 qsf_context = xmlSchemaNewValidCtxt (qsf_schema);
00089 result = xmlSchemaValidateDoc (qsf_context, doc);
00090 xmlSchemaFreeParserCtxt (qsf_schema_file);
00091 xmlSchemaFreeValidCtxt (qsf_context);
00092 xmlSchemaFree (qsf_schema);
00093 g_free (schema_path);
00094 if (result == 0)
00095 {
00096 return TRUE;
00097 }
00098 return FALSE;
00099 }
00100
00101 void
00102 qsf_valid_foreach (xmlNodePtr parent, qsf_validCB cb,
00103 struct qsf_node_iterate *iter, qsf_validator * valid)
00104 {
00105 xmlNodePtr cur_node;
00106
00107 iter->v_fcn = &cb;
00108 for (cur_node = parent->children; cur_node != NULL;
00109 cur_node = cur_node->next)
00110 {
00111 cb (cur_node, iter->ns, valid);
00112 }
00113 }
00114
00115 void
00116 qsf_node_foreach (xmlNodePtr parent, qsf_nodeCB cb,
00117 struct qsf_node_iterate *iter, qsf_param * params)
00118 {
00119 xmlNodePtr cur_node;
00120
00121 g_return_if_fail (iter->ns);
00122 iter->fcn = &cb;
00123 for (cur_node = parent->children; cur_node != NULL;
00124 cur_node = cur_node->next)
00125 {
00126 cb (cur_node, iter->ns, params);
00127 }
00128 }
00129
00130 void
00131 qsf_object_validation_handler (xmlNodePtr child, xmlNsPtr ns,
00132 qsf_validator * valid)
00133 {
00134 xmlNodePtr cur_node;
00135 xmlChar *object_declaration;
00136 guint count;
00137 QsfStatus type;
00138 gboolean is_registered;
00139
00140 count = 0;
00141 type = QSF_NO_OBJECT;
00142 is_registered = FALSE;
00143 for (cur_node = child->children; cur_node != NULL;
00144 cur_node = cur_node->next)
00145 {
00146 if (qsf_is_element (cur_node, ns, QSF_OBJECT_TAG))
00147 {
00148 object_declaration =
00149 xmlGetProp (cur_node, BAD_CAST QSF_OBJECT_TYPE);
00150 is_registered = qof_class_is_registered (object_declaration);
00151 if (is_registered)
00152 {
00153 type = QSF_REGISTERED_OBJECT;
00154 }
00155 else
00156 {
00157 type = QSF_DEFINED_OBJECT;
00158 }
00159 xmlFree (object_declaration);
00160 count = g_hash_table_size (valid->object_table);
00161 g_hash_table_insert (valid->object_table, object_declaration,
00162 GINT_TO_POINTER (type));
00163
00164 if (g_hash_table_size (valid->object_table) > count)
00165 {
00166 valid->valid_object_count++;
00167 if (is_registered)
00168 {
00169 valid->qof_registered_count++;
00170 }
00171 }
00172 }
00173 }
00174 }
00175
00176 gboolean
00177 is_our_qsf_object (const gchar * path)
00178 {
00179 xmlDocPtr doc;
00180 struct qsf_node_iterate iter;
00181 xmlNodePtr object_root;
00182 qsf_validator valid;
00183 gint table_count;
00184
00185 g_return_val_if_fail ((path != NULL), FALSE);
00186 doc = xmlParseFile (path);
00187 if (doc == NULL)
00188 {
00189 return FALSE;
00190 }
00191 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00192 {
00193 PINFO (" validation failed %s %s %s", QSF_SCHEMA_DIR,
00194 QSF_OBJECT_SCHEMA, path);
00195 return FALSE;
00196 }
00197 object_root = xmlDocGetRootElement (doc);
00198
00199 valid.object_table = g_hash_table_new (g_str_hash, g_str_equal);
00200 valid.qof_registered_count = 0;
00201 valid.valid_object_count = 0;
00202 iter.ns = object_root->ns;
00203 qsf_valid_foreach (object_root, qsf_object_validation_handler, &iter,
00204 &valid);
00205 table_count = g_hash_table_size (valid.object_table);
00206 g_hash_table_destroy (valid.object_table);
00207 xmlFreeDoc (doc);
00208 if (table_count == valid.qof_registered_count)
00209 {
00210 return TRUE;
00211 }
00212 return FALSE;
00213 }
00214
00215 gboolean
00216 is_qsf_object (const gchar * path)
00217 {
00218 xmlDocPtr doc;
00219
00220 g_return_val_if_fail ((path != NULL), FALSE);
00221 if (path == NULL)
00222 {
00223 return FALSE;
00224 }
00225 doc = xmlParseFile (path);
00226 if (doc == NULL)
00227 {
00228 return FALSE;
00229 }
00230 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00231 {
00232 return FALSE;
00233 }
00234
00235
00236 return TRUE;
00237 }
00238
00239 gboolean
00240 is_our_qsf_object_be (qsf_param * params)
00241 {
00242 xmlDocPtr doc;
00243 struct qsf_node_iterate iter;
00244 xmlNodePtr object_root;
00245 qsf_validator valid;
00246 gint table_count;
00247
00248 g_return_val_if_fail ((params != NULL), FALSE);
00249 if (params->filepath == NULL)
00250 {
00251 qof_backend_set_error (params->be, ERR_FILEIO_FILE_NOT_FOUND);
00252 return FALSE;
00253 }
00254 if (params->file_type != QSF_UNDEF)
00255 {
00256 return FALSE;
00257 }
00258 doc = xmlParseFile (params->filepath);
00259 if (doc == NULL)
00260 {
00261 qof_backend_set_error (params->be, ERR_FILEIO_PARSE_ERROR);
00262 return FALSE;
00263 }
00264 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00265 {
00266 qof_backend_set_error (params->be, ERR_QSF_INVALID_OBJ);
00267 xmlFreeDoc (doc);
00268 return FALSE;
00269 }
00270 params->file_type = IS_QSF_OBJ;
00271 object_root = xmlDocGetRootElement (doc);
00272 xmlFreeDoc (doc);
00273 valid.object_table = g_hash_table_new (g_str_hash, g_str_equal);
00274 valid.qof_registered_count = 0;
00275 iter.ns = object_root->ns;
00276 qsf_valid_foreach (object_root, qsf_object_validation_handler, &iter,
00277 &valid);
00278 table_count = g_hash_table_size (valid.object_table);
00279 if (table_count == valid.qof_registered_count)
00280 {
00281 g_hash_table_destroy (valid.object_table);
00282 qof_backend_set_error (params->be, ERR_BACKEND_NO_ERR);
00283 return TRUE;
00284 }
00285 g_hash_table_destroy (valid.object_table);
00286 qof_backend_set_error (params->be, ERR_QSF_NO_MAP);
00287 return FALSE;
00288 }
00289
00290 gboolean
00291 is_qsf_object_be (qsf_param * params)
00292 {
00293 gboolean result;
00294 xmlDocPtr doc;
00295 GList *maps;
00296 gchar *path;
00297
00298 g_return_val_if_fail ((params != NULL), FALSE);
00299 path = g_strdup (params->filepath);
00300 if (path == NULL)
00301 {
00302 qof_backend_set_error (params->be, ERR_FILEIO_FILE_NOT_FOUND);
00303 return FALSE;
00304 }
00305
00306 if (ERR_QSF_INVALID_OBJ == qof_backend_get_error (params->be))
00307 {
00308 return FALSE;
00309 }
00310 if (params->file_type == QSF_UNDEF)
00311 {
00312 doc = xmlParseFile (path);
00313 if (doc == NULL)
00314 {
00315 qof_backend_set_error (params->be, ERR_FILEIO_PARSE_ERROR);
00316 return FALSE;
00317 }
00318 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00319 {
00320 qof_backend_set_error (params->be, ERR_QSF_INVALID_OBJ);
00321 return FALSE;
00322 }
00323 }
00324 result = FALSE;
00325
00326 for (maps = params->map_files; maps; maps = maps->next)
00327 {
00328 QofBackendError err;
00329 result = is_qsf_object_with_map_be (maps->data, params);
00330 err = qof_backend_get_error (params->be);
00331 if ((err == ERR_BACKEND_NO_ERR) && result)
00332 {
00333 params->map_path = maps->data;
00334 PINFO ("map chosen = %s", params->map_path);
00335 break;
00336 }
00337
00338 else
00339 {
00340 qof_backend_set_error (params->be, err);
00341 }
00342 }
00343 return result;
00344 }
00345
00346 static void
00347 qsf_supported_data_types (gpointer type, gpointer user_data)
00348 {
00349 qsf_param *params;
00350
00351 g_return_if_fail (user_data != NULL);
00352 g_return_if_fail (type != NULL);
00353 params = (qsf_param *) user_data;
00354 if (qsf_is_element (params->param_node, params->qsf_ns,
00355 (gchar *) type))
00356 {
00357 g_hash_table_insert (params->qsf_parameter_hash,
00358 xmlGetProp (params->param_node,
00359 BAD_CAST QSF_OBJECT_TYPE), params->param_node);
00360 }
00361 }
00362
00363 static void
00364 qsf_parameter_handler (xmlNodePtr child, xmlNsPtr qsf_ns,
00365 qsf_param * params)
00366 {
00367
00368 if (!qsf_ns)
00369 return;
00370 params->param_node = child;
00371 g_slist_foreach (params->supported_types, qsf_supported_data_types,
00372 params);
00373 }
00374
00375 void
00376 qsf_object_node_handler (xmlNodePtr child, xmlNsPtr qsf_ns,
00377 qsf_param * params)
00378 {
00379 struct qsf_node_iterate iter;
00380 qsf_objects *object_set;
00381 gchar *tail, *object_count_s;
00382 gint64 c;
00383
00384 g_return_if_fail (child != NULL);
00385 g_return_if_fail (qsf_ns != NULL);
00386 params->qsf_ns = qsf_ns;
00387 if (qsf_is_element (child, qsf_ns, QSF_OBJECT_TAG))
00388 {
00389 params->qsf_parameter_hash = NULL;
00390 c = 0;
00391 object_set = g_new (qsf_objects, 1);
00392 params->object_set = object_set;
00393 object_set->object_count = 0;
00394 object_set->parameters =
00395 g_hash_table_new (g_str_hash, g_str_equal);
00396 object_set->object_type = ((gchar *) xmlGetProp (child,
00397 BAD_CAST QSF_OBJECT_TYPE));
00398 object_count_s = ((gchar *) xmlGetProp (child,
00399 BAD_CAST QSF_OBJECT_COUNT));
00400 c = (gint64) strtol (object_count_s, &tail, 0);
00401 object_set->object_count = (gint) c;
00402 g_free (object_count_s);
00403 params->qsf_object_list =
00404 g_list_prepend (params->qsf_object_list, object_set);
00405 iter.ns = qsf_ns;
00406 params->qsf_parameter_hash = object_set->parameters;
00407 qsf_node_foreach (child, qsf_parameter_handler, &iter, params);
00408 }
00409 }
00410
00411 void
00412 qsf_book_node_handler (xmlNodePtr child, xmlNsPtr ns, qsf_param * params)
00413 {
00414 gchar *book_count_s, *tail;
00415 gint book_count;
00416 xmlNodePtr child_node;
00417 struct qsf_node_iterate iter;
00418 gchar *buffer;
00419 GUID book_guid;
00420
00421 g_return_if_fail (child);
00422 g_return_if_fail (params);
00423 ENTER (" child=%s", child->name);
00424 if (qsf_is_element (child, ns, QSF_BOOK_TAG))
00425 {
00426 book_count_s =
00427 (gchar *) xmlGetProp (child, BAD_CAST QSF_BOOK_COUNT);
00428 if (book_count_s)
00429 {
00430 book_count = (gint) strtol (book_count_s, &tail, 0);
00431
00432 g_free (book_count_s);
00433 g_return_if_fail (book_count == 1);
00434 }
00435 iter.ns = ns;
00436 child_node = child->children->next;
00437 if (qsf_is_element (child_node, ns, QSF_BOOK_GUID))
00438 {
00439 DEBUG (" trying to set book GUID");
00440 buffer = BAD_CAST xmlNodeGetContent (child_node);
00441 g_return_if_fail (TRUE == string_to_guid (buffer, &book_guid));
00442 qof_entity_set_guid ((QofEntity *) params->book, &book_guid);
00443 xmlNewChild (params->output_node, params->qsf_ns,
00444 BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
00445 xmlFree (buffer);
00446 }
00447 qsf_node_foreach (child, qsf_object_node_handler, &iter, params);
00448 }
00449 LEAVE (" ");
00450 }