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