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, xmlDocPtr doc)
00076 {
00077 xmlSchemaParserCtxtPtr qsf_schema_file;
00078 xmlSchemaPtr qsf_schema;
00079 xmlSchemaValidCtxtPtr qsf_context;
00080 gchar *schema_path;
00081 gint result;
00082
00083 g_return_val_if_fail(doc || schema_filename, FALSE);
00084 schema_path = g_strdup_printf("%s/%s", schema_dir, schema_filename);
00085 qsf_schema_file = xmlSchemaNewParserCtxt(schema_path);
00086 qsf_schema = xmlSchemaParse(qsf_schema_file);
00087 qsf_context = xmlSchemaNewValidCtxt(qsf_schema);
00088 result = xmlSchemaValidateDoc(qsf_context, doc);
00089 xmlSchemaFreeParserCtxt(qsf_schema_file);
00090 xmlSchemaFreeValidCtxt(qsf_context);
00091 xmlSchemaFree(qsf_schema);
00092 g_free(schema_path);
00093 if (result == 0)
00094 {
00095 return TRUE;
00096 }
00097 return FALSE;
00098 }
00099
00100 void
00101 qsf_valid_foreach(xmlNodePtr parent, qsf_validCB cb,
00102 struct qsf_node_iterate *iter, qsf_validator *valid)
00103 {
00104 xmlNodePtr cur_node;
00105
00106 iter->v_fcn = &cb;
00107 for (cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
00108 {
00109 cb(cur_node, iter->ns, valid);
00110 }
00111 }
00112
00113 void
00114 qsf_node_foreach(xmlNodePtr parent, qsf_nodeCB cb,
00115 struct qsf_node_iterate *iter, qsf_param *params)
00116 {
00117 xmlNodePtr cur_node;
00118
00119 g_return_if_fail(iter->ns);
00120 iter->fcn = &cb;
00121 for (cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
00122 {
00123 cb(cur_node, iter->ns, params);
00124 }
00125 }
00126
00127 void
00128 qsf_object_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid)
00129 {
00130 xmlNodePtr cur_node;
00131 xmlChar *object_declaration;
00132 guint count;
00133
00134 count = 0;
00135 for (cur_node = child->children; cur_node != NULL;
00136 cur_node = cur_node->next)
00137 {
00138 if (qsf_is_element(cur_node, ns, QSF_OBJECT_TAG))
00139 {
00140 object_declaration = xmlGetProp(cur_node, BAD_CAST QSF_OBJECT_TYPE);
00141 count = g_hash_table_size(valid->validation_table);
00142 g_hash_table_insert(valid->validation_table, object_declaration, xmlNodeGetContent(cur_node));
00143 if (g_hash_table_size(valid->validation_table) > count)
00144 {
00145 valid->valid_object_count++;
00146 if (TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration))
00147 {
00148 valid->qof_registered_count++;
00149 }
00150 }
00151 }
00152 }
00153 }
00154
00155 gboolean is_our_qsf_object(const gchar *path)
00156 {
00157 xmlDocPtr doc;
00158 struct qsf_node_iterate iter;
00159 xmlNodePtr object_root;
00160 qsf_validator valid;
00161 gint table_count;
00162
00163 g_return_val_if_fail((path != NULL), FALSE);
00164 doc = xmlParseFile(path);
00165 if (doc == NULL)
00166 {
00167 return FALSE;
00168 }
00169 if (TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00170 {
00171 PINFO (" validation failed %s %s %s", QSF_SCHEMA_DIR,
00172 QSF_OBJECT_SCHEMA, path);
00173 xmlFreeDoc(doc);
00174 return FALSE;
00175 }
00176 object_root = xmlDocGetRootElement(doc);
00177
00178 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
00179 valid.qof_registered_count = 0;
00180 valid.valid_object_count = 0;
00181 iter.ns = object_root->ns;
00182 qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
00183 table_count = g_hash_table_size(valid.validation_table);
00184 g_hash_table_destroy(valid.validation_table);
00185 if (table_count == valid.qof_registered_count)
00186 {
00187 return TRUE;
00188 }
00189 return FALSE;
00190 }
00191
00192 gboolean is_qsf_object(const gchar *path)
00193 {
00194 xmlDocPtr doc;
00195
00196 g_return_val_if_fail((path != NULL), FALSE);
00197 if (path == NULL)
00198 {
00199 return FALSE;
00200 }
00201 doc = xmlParseFile(path);
00202 if (doc == NULL)
00203 {
00204 return FALSE;
00205 }
00206 if (TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00207 {
00208 xmlFreeDoc(doc);
00209 return FALSE;
00210 }
00211 xmlFreeDoc(doc);
00212
00213
00214 return TRUE;
00215 }
00216
00217 gboolean is_our_qsf_object_be(qsf_param *params)
00218 {
00219 xmlDocPtr doc;
00220 struct qsf_node_iterate iter;
00221 xmlNodePtr object_root;
00222 qsf_validator valid;
00223 gint table_count;
00224 gchar *path;
00225
00226 g_return_val_if_fail((params != NULL), FALSE);
00227 path = g_strdup(params->filepath);
00228 if (path == NULL)
00229 {
00230 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
00231 return FALSE;
00232 }
00233 if (params->file_type != QSF_UNDEF)
00234 {
00235 return FALSE;
00236 }
00237 doc = xmlParseFile(path);
00238 if (doc == NULL)
00239 {
00240 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
00241 return FALSE;
00242 }
00243 if (TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00244 {
00245 qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
00246 return FALSE;
00247 }
00248 params->file_type = IS_QSF_OBJ;
00249 object_root = xmlDocGetRootElement(doc);
00250 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
00251 valid.qof_registered_count = 0;
00252 iter.ns = object_root->ns;
00253 qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
00254 table_count = g_hash_table_size(valid.validation_table);
00255 if (table_count == valid.qof_registered_count)
00256 {
00257 g_hash_table_destroy(valid.validation_table);
00258 qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR);
00259 return TRUE;
00260 }
00261 g_hash_table_destroy(valid.validation_table);
00262 qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
00263 return FALSE;
00264 }
00265
00266 gboolean is_qsf_object_be(qsf_param *params)
00267 {
00268 gboolean result;
00269 xmlDocPtr doc;
00270 GList *maps;
00271 gchar *path;
00272
00273 g_return_val_if_fail((params != NULL), FALSE);
00274 path = g_strdup(params->filepath);
00275 if (path == NULL)
00276 {
00277 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
00278 return FALSE;
00279 }
00280
00281 if (ERR_QSF_INVALID_OBJ == qof_backend_get_error(params->be))
00282 {
00283 return FALSE;
00284 }
00285 if (params->file_type == QSF_UNDEF)
00286 {
00287 doc = xmlParseFile(path);
00288 if (doc == NULL)
00289 {
00290 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
00291 return FALSE;
00292 }
00293 if (TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00294 {
00295 qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
00296 return FALSE;
00297 }
00298 }
00299 result = FALSE;
00300
00301 for (maps = params->map_files; maps; maps = maps->next)
00302 {
00303 QofBackendError err;
00304 result = is_qsf_object_with_map_be(maps->data, params);
00305 err = qof_backend_get_error(params->be);
00306 if ((err == ERR_BACKEND_NO_ERR) && result)
00307 {
00308 params->map_path = maps->data;
00309 PINFO ("map chosen = %s", params->map_path);
00310 break;
00311 }
00312
00313 else
00314 {
00315 qof_backend_set_error(params->be, err);
00316 }
00317 }
00318 return result;
00319 }
00320
00321 static void
00322 qsf_supported_data_types(gpointer type, gpointer user_data)
00323 {
00324 qsf_param *params;
00325
00326 g_return_if_fail(user_data != NULL);
00327 g_return_if_fail(type != NULL);
00328 params = (qsf_param*) user_data;
00329 if (qsf_is_element(params->param_node, params->qsf_ns, (gchar*)type))
00330 {
00331 g_hash_table_insert(params->qsf_parameter_hash,
00332 xmlGetProp(params->param_node, BAD_CAST QSF_OBJECT_TYPE), params->param_node);
00333 }
00334 }
00335
00336 static void
00337 qsf_parameter_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
00338 {
00339 params->param_node = child;
00340 g_slist_foreach(params->supported_types, qsf_supported_data_types, params);
00341 }
00342
00343 void
00344 qsf_object_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
00345 {
00346 struct qsf_node_iterate iter;
00347 qsf_objects *object_set;
00348 gchar *tail, *object_count_s;
00349 gint64 c;
00350
00351 g_return_if_fail(child != NULL);
00352 g_return_if_fail(qsf_ns != NULL);
00353 params->qsf_ns = qsf_ns;
00354 if (qsf_is_element(child, qsf_ns, QSF_OBJECT_TAG))
00355 {
00356 params->qsf_parameter_hash = NULL;
00357 c = 0;
00358 object_set = g_new(qsf_objects, 1);
00359 params->object_set = object_set;
00360 object_set->object_count = 0;
00361 object_set->parameters = g_hash_table_new(g_str_hash, g_str_equal);
00362 object_set->object_type = g_strdup((gchar*)xmlGetProp(child,
00363 BAD_CAST QSF_OBJECT_TYPE));
00364 object_count_s = g_strdup((gchar*)xmlGetProp(child,
00365 BAD_CAST QSF_OBJECT_COUNT));
00366 c = (gint64)strtol(object_count_s, &tail, 0);
00367 object_set->object_count = (gint)c;
00368 g_free(object_count_s);
00369 params->qsf_object_list = g_list_prepend(params->qsf_object_list, object_set);
00370 iter.ns = qsf_ns;
00371 params->qsf_parameter_hash = object_set->parameters;
00372 qsf_node_foreach(child, qsf_parameter_handler, &iter, params);
00373 }
00374 }
00375
00376 void
00377 qsf_book_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
00378 {
00379 gchar *book_count_s, *tail;
00380 gint book_count;
00381 xmlNodePtr child_node;
00382 struct qsf_node_iterate iter;
00383 gchar *buffer;
00384 GncGUID book_guid;
00385
00386 g_return_if_fail(child);
00387 g_return_if_fail(params);
00388 ENTER (" child=%s", child->name);
00389 if (qsf_is_element(child, ns, QSF_BOOK_TAG))
00390 {
00391 book_count_s = (gchar*)xmlGetProp(child, BAD_CAST QSF_BOOK_COUNT);
00392 if (book_count_s)
00393 {
00394 book_count = (gint)strtol(book_count_s, &tail, 0);
00395
00396 g_return_if_fail(book_count == 1);
00397 }
00398 iter.ns = ns;
00399 child_node = child->children->next;
00400 if (qsf_is_element(child_node, ns, QSF_BOOK_GUID))
00401 {
00402 DEBUG (" trying to set book GncGUID");
00403 buffer = g_strdup((gchar*)xmlNodeGetContent(child_node));
00404 g_return_if_fail(TRUE == string_to_guid(buffer, &book_guid));
00405 qof_instance_set_guid(QOF_INSTANCE(params->book), &book_guid);
00406 xmlNewChild(params->output_node, params->qsf_ns,
00407 BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
00408 g_free(buffer);
00409 }
00410 qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
00411 }
00412 LEAVE (" ");
00413 }