00001
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 #include "../config.h"
00097
00098 #ifdef USE_XPATH
00099
00100 #include <libxml/xmlmemory.h>
00101 #include <libxml/parser.h>
00102 #include <libxml/tree.h>
00103 #include <libxml/xpath.h>
00104 #include "buf.h"
00105 #include "dbapi.h"
00106
00108 #define XMLFILE "XML File"
00109
00111 enum {
00112 FLD_TYPE = 0,
00113 FLD_NAME,
00114 FLD_ATTRIB,
00115 FLD_CONTENT
00116 } FldTypes;
00117
00119 #define FLD_COUNT 4
00120
00122 typedef struct {
00123
00124 int tableCount;
00125 DBTableDef *tableDef;
00126 xmlDocPtr doc;
00127 char *filename;
00128 xmlXPathObjectPtr result;
00129 int status;
00130 char *errmsg;
00131 } DBConnection_XPath;
00132
00134 static char *xpathKeywords[] = {
00135 "SELECT",
00136 NULL
00137 };
00138
00142 void *xpath_query(DBConnection * dbc, char *xpstr)
00143 {
00144 DBConnection_XPath *dbcxp;
00145 xmlXPathContextPtr context;
00146 if (!dbc)
00147 return NULL;
00148
00149 if (!dbc->pvt)
00150 return NULL;
00151
00152 dbcxp = (DBConnection_XPath *) (dbc->pvt);
00153 dbcxp->status = DB_QUERY_RECORDS_OK;
00154
00155 if (!dbcxp->doc) {
00156 dbcxp->status = DB_QUERY_ERROR;
00157 return NULL;
00158 }
00159
00160 if (dbcxp->result) {
00161 printf("WARNING: Result already exists.\n");
00162 xmlXPathFreeObject(dbcxp->result);
00163 }
00164
00165 context = xmlXPathNewContext(dbcxp->doc);
00166 dbcxp->result = xmlXPathEvalExpression(xpstr, context);
00167
00168 if (xmlXPathNodeSetIsEmpty(dbcxp->result->nodesetval)) {
00169 dbcxp->status = DB_QUERY_EMPTY;
00170 printf("No result\n");
00171 }
00172
00173 xmlXPathFreeContext(context);
00174 return dbcxp->result;
00175 }
00176
00180 DBConnection *xpath_dbconnection_free(DBConnection * c)
00181 {
00182 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00183 free(dbxpath->filename);
00184
00185
00186 keywords_remove_all(c);
00187
00188
00189 free(dbxpath);
00190 free(c);
00191 return NULL;
00192 }
00193
00196 char *xpath_error()
00197 {
00198 g_warning("xpath_error() not implemented\n");
00199 return "Not implemented";
00200 }
00201
00205 static void xp_DBclear_result(DBConnection * c, void *result)
00206 {
00207 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00208 if (!dbxpath)
00209 return;
00210
00211 if (dbxpath->result) {
00212 xmlXPathFreeObject(dbxpath->result);
00213 dbxpath->result = NULL;
00214 }
00215 }
00216
00220 static int xp_DBdisconnect(DBConnection * c)
00221 {
00222 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00223
00224
00225 xp_DBclear_result(c, NULL);
00226 if (dbxpath->doc) {
00227 xmlFreeDoc(dbxpath->doc);
00228 dbxpath->doc = NULL;
00229 }
00230 return 0;
00231 }
00232
00236 static char *xp_DBget_error_message(DBConnection * c)
00237 {
00238 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00239 if (!dbxpath)
00240 return "Connection invalid";
00241
00242 return xpath_error(dbxpath->filename);
00243 }
00244
00248 static char *xp_DBget_db_name(DBConnection * c)
00249 {
00250 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00251 if (!dbxpath)
00252 return NULL;
00253 return dbxpath->filename;
00254 }
00255
00260 static void *xp_DBexecute_query(DBConnection * c, char *query)
00261 {
00262 return xpath_query(c, query);
00263 }
00264
00270 static int xp_DBget_query_status(DBConnection * c, void *result)
00271 {
00272 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00273 if (!dbxpath)
00274 return DB_QUERY_ERROR;
00275
00276 return dbxpath->status;
00277 }
00278
00283 static int xp_DBget_record_number(DBConnection * c, void *result)
00284 {
00285 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00286 if (!dbxpath)
00287 return 0;
00288
00289 if (!dbxpath->result)
00290 return 0;
00291
00292 if (!dbxpath->result->nodesetval)
00293 return 0;
00294
00295 return dbxpath->result->nodesetval->nodeNr;
00296 }
00297
00302 static int xp_DBget_field_number(DBConnection * c, void *result)
00303 {
00304 return FLD_COUNT;
00305 }
00306
00311 static char *xp_DBget_field_name(DBConnection * c, void *result, int field)
00312 {
00313 switch (field) {
00314 case FLD_TYPE:
00315 return "Type";
00316 case FLD_NAME:
00317 return "Name";
00318 case FLD_ATTRIB:
00319 return "Attributes";
00320 case FLD_CONTENT:
00321 return "Content";
00322 }
00323 return "";
00324 }
00325
00329 char *xp_DBget_field_value_type(xmlNodePtr node)
00330 {
00331 if (! node)
00332 return "";
00333
00334 switch (node->type) {
00335 case XML_ELEMENT_NODE:
00336 return "NODE";
00337 case XML_ATTRIBUTE_NODE:
00338 return "ATTRIBUTE";
00339 case XML_TEXT_NODE:
00340 return "TEXT";
00341 case XML_CDATA_SECTION_NODE:
00342 return "CDATA";
00343 case XML_ENTITY_REF_NODE:
00344 return "ENTITY_REF";
00345 case XML_ENTITY_NODE:
00346 return "ENTITY";
00347 case XML_PI_NODE:
00348 return "PI";
00349 case XML_COMMENT_NODE:
00350 return "COMMENT";
00351 case XML_DOCUMENT_NODE:
00352 return "DOCUMENT";
00353 case XML_DOCUMENT_TYPE_NODE:
00354 return "DOCUMENT_TYPE";
00355 case XML_DOCUMENT_FRAG_NODE:
00356 return "DOCUMENT_FRAG";
00357 case XML_NOTATION_NODE:
00358 return "NOTATION";
00359 case XML_HTML_DOCUMENT_NODE:
00360 return "HTML_DOCUMENT";
00361 case XML_DTD_NODE:
00362 return "DTD";
00363 case XML_ELEMENT_DECL:
00364 return "ELEMENT_DECL";
00365 case XML_ATTRIBUTE_DECL:
00366 return "ATTRIBUTE_DECL";
00367 case XML_ENTITY_DECL:
00368 return "ENTITY_DECL";
00369 case XML_NAMESPACE_DECL:
00370 return "NAMESPACE_DECL";
00371 case XML_XINCLUDE_START:
00372 return "XINCLUDE_START";
00373 case XML_XINCLUDE_END:
00374 return "XINCLUDE_END";
00375 case XML_DOCB_DOCUMENT_NODE:
00376 return "DOCB_DOCUMENT";
00377 default:
00378 return "";
00379 }
00380 }
00381
00383 static ABuf *contentbuf = NULL;
00384 static ABuf *attrbuf = NULL;
00385
00389 char *xp_DBget_field_value_attrib(xmlNodePtr node) {
00390 xmlAttrPtr attr = NULL;
00391 xmlChar *txt;
00392 xmlNodePtr cur;
00393
00394 if (! node)
00395 return "";
00396
00397 cur = node;
00398 if (! cur)
00399 return "NIL: cur is NULL";
00400
00401 attrbuf = buf_check(attrbuf, 1024);
00402 attrbuf = buf_strcpy(attrbuf, "");
00403
00404
00405
00406 attr = cur->properties;
00407 if (attr == NULL)
00408 attr = cur;
00409
00410
00411
00412 while (attr != NULL) {
00413 if (attr->name)
00414 attrbuf = buf_strcat(attrbuf, (char *)attr->name);
00415 else
00416 attrbuf = buf_strcat(attrbuf, "NULL");
00417
00418 attrbuf = buf_strcat(attrbuf, "=\"");
00419 txt = xmlNodeListGetString(node->doc, attr->children, 1);
00420 if (txt != NULL)
00421 attrbuf = buf_strcat(attrbuf, txt);
00422
00423 attrbuf = buf_strcat(attrbuf, "\" ");
00424 attr = attr->next;
00425 }
00426 return attrbuf->b_dat;
00427 }
00428
00432 char *xp_DBget_field_value_content(xmlNodePtr node) {
00433 xmlNodePtr child = NULL;
00434
00435 if (! node)
00436 return "";
00437
00438 switch (node->type) {
00439 case XML_ELEMENT_NODE:
00440 child = node->children;
00441 contentbuf = buf_strcpy(contentbuf, "");
00442 while (child) {
00443 if (!strcmp(child->name, "text"))
00444 contentbuf = buf_strcat(contentbuf, trimtext(child->content));
00445 child = child->next;
00446 }
00447 return contentbuf->b_dat;
00448 case XML_ATTRIBUTE_NODE:
00449 return "ATTRIBUTE";
00450 case XML_TEXT_NODE:
00451 return "TEXT";
00452 case XML_CDATA_SECTION_NODE:
00453 return "CDATA";
00454 case XML_ENTITY_REF_NODE:
00455 return "ENTITY_REF";
00456 case XML_ENTITY_NODE:
00457 return "ENTITY";
00458 case XML_PI_NODE:
00459 return "PI";
00460 case XML_COMMENT_NODE:
00461 return "COMMENT";
00462 case XML_DOCUMENT_NODE:
00463 return "DOCUMENT";
00464 case XML_DOCUMENT_TYPE_NODE:
00465 return "DOCUMENT_TYPE";
00466 case XML_DOCUMENT_FRAG_NODE:
00467 return "DOCUMENT_FRAG";
00468 case XML_NOTATION_NODE:
00469 return "NOTATION";
00470 case XML_HTML_DOCUMENT_NODE:
00471 return "HTML_DOCUMENT";
00472 case XML_DTD_NODE:
00473 return "DTD";
00474 case XML_ELEMENT_DECL:
00475 return "ELEMENT_DECL";
00476 case XML_ATTRIBUTE_DECL:
00477 return "ATTRIBUTE_DECL";
00478 case XML_ENTITY_DECL:
00479 return "ENTITY_DECL";
00480 case XML_XINCLUDE_START:
00481 return "XINCLUDE_START";
00482 case XML_XINCLUDE_END:
00483 return "XINCLUDE_END";
00484 case XML_DOCB_DOCUMENT_NODE:
00485 return "DOCB_DOCUMENT";
00486 default:
00487 return "";
00488 }
00489 }
00490
00497 static char *xp_DBget_field_value(DBConnection * c, void *result, int record,
00498 int field)
00499 {
00500 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00501 xmlNodePtr node = NULL;
00502
00503 int rows = 0;
00504
00505 if (!dbxpath)
00506 return "";
00507
00508 if (!dbxpath->result)
00509 return "";
00510
00511 if (!dbxpath->result->nodesetval)
00512 return "";
00513
00514 rows = dbxpath->result->nodesetval->nodeNr;
00515 if (record >= rows)
00516 return "";
00517
00518 node = dbxpath->result->nodesetval->nodeTab[record];
00519 if (!node)
00520 return "";
00521
00522
00523
00524 switch (field) {
00525 case FLD_TYPE: return xp_DBget_field_value_type(node);
00526 case FLD_NAME: return (char *)node->name;
00527 case FLD_ATTRIB: return xp_DBget_field_value_attrib(node);
00528 case FLD_CONTENT: return xp_DBget_field_value_content(node);
00529 default:
00530 return "";
00531 }
00532 }
00533
00538 void xp_DBurl_to_form(Form *frm, char *url) {
00539 char *u;
00540 char *p;
00541 char *start;
00542
00543
00544 frm_clear_fields(frm);
00545
00546 if (url == NULL)
00547 return;
00548
00549 u = strdup(url);
00550 start = u;
00551
00552
00553 p = strstr(start, "://");
00554 if (p != NULL) {
00555 p += 3;
00556
00557
00558 frm_set_value_by_name(frm, XMLFILE, p);
00559 }
00560 free(u);
00561 }
00562
00567 static int xp_add_field_def(DBConnection * c, DBTableDef * tbf)
00568 {
00569 int i;
00570 char *fname;
00571 char *rtype, *rnotnull, *rhasdef;
00572
00573 tbf->field_num = FLD_COUNT;
00574 tbf->field_def =
00575 (DBFieldDef *) malloc(tbf->field_num * sizeof(DBFieldDef));
00576
00577 for (i = 0; i < tbf->field_num; i++) {
00578 switch (i) {
00579 case FLD_TYPE:
00580 fname = "Type";
00581 break;
00582 case FLD_NAME:
00583 fname = "Name";
00584 break;
00585 case FLD_ATTRIB:
00586 fname = "Atrib";
00587 break;
00588 case FLD_CONTENT:
00589 fname = "Content";
00590 break;
00591 default:
00592 fname = "";
00593 }
00594 add_keyword(c, fname, KEYWORD_FIELD);
00595 rtype = "int";
00596 rnotnull = "NO";
00597 rhasdef = "";
00598
00599
00600 tbf->field_def[i].name = g_strdup(fname);
00601 tbf->field_def[i].type = g_strdup("varchar(255)");
00602 tbf->field_def[i].length = g_strdup("??");
00603 }
00604 return 0;
00605 }
00606
00611 static int xp_DBget_table_def(DBConnection * c)
00612 {
00613 int tables_in_list = 1;
00614
00615 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00616
00617 if (dbxpath->tableDef != NULL) {
00618 fprintf(stderr, "Internal error (memory leak)...\n");
00619 return -1;
00620 }
00621
00622
00623 dbxpath->tableCount = 1;
00624 dbxpath->tableDef =
00625 (DBTableDef *) malloc(tables_in_list * sizeof(DBTableDef));
00626
00627
00628
00629
00630 dbxpath->tableDef[0].name = g_strdup("Dummy");
00631
00632
00633 if (xp_add_field_def(c, dbxpath->tableDef + 0) < 0) {
00634 dbxpath->tableDef = NULL;
00635 return -1;
00636 }
00637
00638
00639
00640 return 0;
00641 }
00642
00643 static ABuf *f2ubuf = NULL;
00644
00648 char *xp_DBform_to_url(Form *frm) {
00649 char *s;
00650
00651 if (frm == NULL)
00652 return NULL;
00653
00654 f2ubuf = buf_check(f2ubuf, 100);
00655 f2ubuf = buf_strcat(f2ubuf, "xpath://");
00656 s = frm_get_value_by_name(frm, XMLFILE);
00657 if (s != NULL) {
00658 f2ubuf = buf_strcat(f2ubuf, s);
00659 }
00660
00661 return f2ubuf->b_dat;
00662 }
00663
00666 static void xp_DBfree_table_def(DBConnection * c)
00667 {
00668 DBConnection_XPath *dbxpath = (DBConnection_XPath *) (c->pvt);
00669
00670 if (dbxpath->tableDef == NULL) {
00671 fprintf(stderr, "Internal error (freeing a NULL connection)...\n");
00672
00673
00674
00675
00676
00677
00678 return;
00679 }
00680 else {
00681 DBFieldDef *dbf;
00682 int i, j;
00683
00684 for (j = 0; j < dbxpath->tableCount; j++) {
00685 int fnum = (dbxpath->tableDef)[j].field_num;
00686
00687 if (dbxpath->tableDef[j].name)
00688 free(dbxpath->tableDef[j].name);
00689
00690 dbf = (dbxpath->tableDef)[j].field_def;
00691 for (i = 0; i < fnum; i++) {
00692 free(dbf[i].name);
00693 free(dbf[i].type);
00694 }
00695 free(dbf);
00696 }
00697 free(dbxpath->tableDef);
00698 dbxpath->tableDef = NULL;
00699
00700
00701 keywords_remove(c, KEYWORD_TABLE);
00702 keywords_remove(c, KEYWORD_FIELD);
00703 }
00704 }
00705
00709 static int xp_DBget_table_num(DBConnection * c)
00710 {
00711 DBConnection_XPath *xpconn = (DBConnection_XPath *) (c->pvt);
00712 return xpconn->tableCount;
00713 }
00714
00719 static DBTableDef *xp_DBget_table(DBConnection * c, int table)
00720 {
00721 DBConnection_XPath *xpconn = (DBConnection_XPath *) (c->pvt);
00722
00723 if (table > 0) {
00724 fprintf(stderr, "Internal error (table number too big)...\n");
00725 return NULL;
00726 }
00727
00728 if (xpconn->tableDef == NULL) {
00729 fprintf(stderr, "Internal error (searching a NULL table)...\n");
00730 return NULL;
00731 }
00732 else {
00733 return xpconn->tableDef + table;
00734 }
00735 return NULL;
00736 }
00737
00740 DBConnection *xpath_dbconnection_new()
00741 {
00742 DBConnection *dbc = calloc(1, sizeof(DBConnection));
00743 DBConnection_XPath *pvtdata;
00744 int i;
00745
00746 if (dbc) {
00747 dbc->DBdisconnect = xp_DBdisconnect;
00748 dbc->DBget_error_message = xp_DBget_error_message;
00749 dbc->DBget_db_name = xp_DBget_db_name;
00750 dbc->DBexecute_query = xp_DBexecute_query;
00751 dbc->DBget_query_status = xp_DBget_query_status;
00752 dbc->DBget_record_number = xp_DBget_record_number;
00753 dbc->DBget_field_number = xp_DBget_field_number;
00754 dbc->DBget_field_name = xp_DBget_field_name;
00755 dbc->DBget_field_value = xp_DBget_field_value;
00756 dbc->DBclear_result = xp_DBclear_result;
00757
00758
00759 dbc->keylist = NULL;
00760 i = 0;
00761 while (xpathKeywords[i] != NULL)
00762 add_keyword((DBConnection *) dbc, xpathKeywords[i++],
00763 KEYWORD_SQL);
00764
00765 dbc->DBget_table_def = xp_DBget_table_def;
00766 dbc->DBfree_table_def = xp_DBfree_table_def;
00767 dbc->DBget_table_num = xp_DBget_table_num;
00768 dbc->DBget_table = xp_DBget_table;
00769
00770
00771 pvtdata = calloc(1, sizeof(DBConnection_XPath));
00772 dbc->pvt = pvtdata;
00773 dbc->pvtlen = sizeof(DBConnection_XPath);
00774 }
00775 return dbc;
00776 }
00777
00781 void dbconnection_xpath_set_filename(DBConnection * dbc, char *fn)
00782 {
00783 DBConnection_XPath *dbcxp;
00784
00785 if (!dbc)
00786 return;
00787
00788 dbcxp = (DBConnection_XPath *) (dbc->pvt);
00789 if (!dbcxp)
00790 return;
00791
00792 if (dbcxp->filename)
00793 free(dbcxp->filename);
00794
00795 dbcxp->filename = strdup(fn);
00796 }
00797
00801 void xpath_set_error(DBConnection_XPath * dbc, char *s)
00802 {
00803 if (!dbc)
00804 return;
00805
00806 if (dbc->errmsg)
00807 free(dbc->errmsg);
00808
00809 dbc->errmsg = strdup(s);
00810 }
00811
00816 int dbconnection_xpath_open_doc(DBConnection * dbc, char *fn)
00817 {
00818 DBConnection_XPath *dbcxp;
00819 xmlNodePtr cur;
00820
00821 if (!dbc)
00822 return CONNECT_ERROR;
00823
00824 dbcxp = (DBConnection_XPath *) (dbc->pvt);
00825
00826 if (!dbcxp)
00827 return CONNECT_ERROR;
00828
00829 dbconnection_xpath_set_filename(dbc, fn);
00830
00831 dbcxp->doc = xmlParseFile(fn);
00832 if (dbcxp->doc == NULL) {
00833 xpath_set_error(dbcxp, "Document not parsed successfully.");
00834 xmlFreeDoc(dbcxp->doc);
00835 dbcxp->doc = NULL;
00836 return CONNECT_ERROR;
00837 }
00838
00839 cur = xmlDocGetRootElement(dbcxp->doc);
00840 if (cur == NULL) {
00841 xpath_set_error(dbcxp, "Document empty");
00842 xmlFreeDoc(dbcxp->doc);
00843 dbcxp->doc = NULL;
00844 return CONNECT_ERROR;
00845 }
00846 return CONNECT_OK;
00847 }
00848
00856 static int connect_callback(DBConnector * dbc, DBConnection ** ret)
00857 {
00859 #define DB_CONNECT_ERROR_S "Database connection error : \n %s"
00860 char *xmlname;
00861 DBConnection *ret_my;
00862
00863
00864 xmlname = frm_get_value_by_name(dbc->db_frm, XMLFILE);
00865
00866
00867 if ((xmlname == NULL) || (strlen(xmlname) == 0)) {
00868 dbc->app_error_dialog("Connection Error",
00869 "You need to provide a database name");
00870 return CONNECT_ERROR;
00871 }
00872
00873 ret_my = xpath_dbconnection_new();
00874 if (!ret_my)
00875 return CONNECT_ERROR;
00876
00877 ret_my->connector = dbc;
00878
00879
00880 status_push("Parsing XML...");
00881 if (dbconnection_xpath_open_doc(ret_my, xmlname) != CONNECT_OK)
00882 return CONNECT_ERROR;
00883
00884 status_pop();
00885 *ret = ret_my;
00886 return CONNECT_OK;
00887 }
00888
00892 DBConnector *register_XPath(void (*error_dialog) (char *, char *))
00893 {
00895 #define XPATH_TYPEKEY "XPath"
00896 DBConnector *ret;
00897 FormField *fld;
00898
00899 ret = dbconnector_new();
00900 if (ret == NULL)
00901 return NULL;
00902
00903 ret->dbtype = XPATH_TYPEKEY;
00904
00905
00906 ret->app_error_dialog = error_dialog;
00907 ret->db_connect_callback = connect_callback;
00908 ret->url_to_form = xp_DBurl_to_form;
00909 ret->form_to_url = xp_DBform_to_url;
00910
00911
00912 ret->db_frm = frm_new(NULL);
00913 frm_set_title(ret->db_frm, "XPath");
00914 fld = frm_add_field(ret->db_frm, XMLFILE, NULL);
00915 fld_set_relevance(fld, FR_REQUIRED);
00916 fld_set_type(fld, 0, FT_FILENAME);
00917 fld_set_tip(fld, "The filename for the XML file (required)");
00918 return ret;
00919 }
00920
00921 #endif