/*
*
* ProLinga-Run
*
* Copyright (C) 2002-2008 Xobas Software.
* All rights reserved.
*
* This file is part of ProLinga-Run.
*
* ProLinga-Run is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProLinga-Run is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProLinga-Run. If not, see .
*
* More information is available at the following addresses:
*
* Website : http://www.prolinga.org
*
* Email : prolinga-list@prolinga.org
*
*
*/
#include "RunCommon.h"
#include
#include
#include
#include
#include
#include
#include
#include "DataRef.hpp"
extern BiXmlStatusPtr biXmlStatusPtr;
extern TextDocumentPtr textPtr;
extern XmlDocumentPtr xmlPtr;
/* Command : XML */
/* Syntax : */
void CmdXml(char **argList, int argHits, bool isMainThread)
{
int insHits, *textContentsLength;
char tmpValue[255], *nodeContents, docName[255], nodeName[1024], tmpNodeName[1024];
char evalString[1024],*rootName, tmpNav[1024], tmpString[255], *retString, *textSrc;
FILE *fpXml;
xmlDocPtr doc, docSrc, docDest, docXslt;
xmlNodePtr cur, curNew, curSource;
xmlXPathContextPtr ctx;
xmlXPathObjectPtr res;
xsltStylesheetPtr stylePtr = NULL;
xmlChar *attrValue, *textContents;
bool processed = false;
/* Init */
biXmlStatusPtr->setXmlStatus(0);
/* Get option */
if (strcmp(argList[1], "ADD") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get node name */
getDataRef(argList[4], isMainThread, nodeName, false);
/* Ignore full path in ADD for the moment */
if ((nodeName[0] == '/') || (strstr(nodeName, "/") != NULL))
{
biXmlStatusPtr->setXmlStatus(10501);
return;
}
/* Add node */
if (argHits > 4 )
{
/* Get node contents */
nodeContents = getDataRefRaw(argList[6], isMainThread, nodeContents, true);
if (nodeContents == NULL)
{
nodeContents = new char[2];
strcpy(nodeContents, "");
}
if (nodeName[0] == '@')
xmlNewProp(cur, (const xmlChar *)(nodeName+1), (const xmlChar *)nodeContents);
else
xmlNewTextChild(cur, NULL, (const xmlChar *)nodeName, (const xmlChar *)nodeContents);
/* Clean up */
delete nodeContents;
}
else
{
if (nodeName[0] == '@')
xmlNewProp(cur, (const xmlChar *)(nodeName+1), NULL);
else
xmlNewTextChild(cur, NULL, (const xmlChar *)nodeName, NULL);
}
}
else if (strcmp(argList[1], "CDATA") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get node contents */
nodeContents = getDataRef(argList[4], isMainThread, nodeContents, true);
if (nodeContents == NULL)
{
nodeContents = new char[2];
strcpy(nodeContents, "");
}
/* Add and link in comment */
xmlAddChild(cur, xmlNewCDataBlock(doc,(const xmlChar *)nodeContents, strlen(nodeContents)));
/* Clean up */
delete nodeContents;
}
else if (strcmp(argList[1], "COMMENT") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get node contents */
nodeContents = getDataRef(argList[4], isMainThread, nodeContents, true);
if (nodeContents == NULL)
{
nodeContents = new char[2];
strcpy(nodeContents, "");
}
/* Add and link in comment */
xmlAddChild(cur, xmlNewComment((const xmlChar *)nodeContents));
/* Clean up */
delete nodeContents;
}
else if (strcmp(argList[1], "COUNT") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get node name */
getDataRef(argList[4], isMainThread, nodeName, false);
/* Set Node Path */
if (nodeName[0] == '/')
{
rootName = xmlPtr->getRootElementName(xmlPtr, docName);
if (strlen(nodeName) == 0)
sprintf(tmpNodeName, "/%s",rootName);
else
{
/* Allow closing "/" in path setting */
if (nodeName[(strlen(nodeName)-1)] == '/')
nodeName[(strlen(nodeName)-1)] = '\0';
sprintf(tmpNodeName, "/%s%s",rootName, nodeName);
}
}
else
sprintf(tmpNodeName,"%s/%s", xmlPtr->getNavPath(xmlPtr, docName), nodeName);
/* Create eval string */
sprintf(evalString,"count(%s)", tmpNodeName);
/* Execute XPath query */
ctx = xmlXPathNewContext(doc);
res = xmlXPathEval((const xmlChar *)evalString, ctx);
if (res == NULL)
{
xmlXPathFreeObject(res);
xmlXPathFreeContext(ctx);
biXmlStatusPtr->setXmlStatus(10502);
return;
}
insHits = (int)xmlXPathCastToNumber(res);
/* Put DataRef */
sprintf(tmpString,"%d", insHits);
putDataRef(argList[6], tmpString, 0, isMainThread);
/* Free */
xmlXPathFreeObject(res);
xmlXPathFreeContext(ctx);
}
else if (strcmp(argList[1], "LOAD") == 0)
{
if (strcmp(getDataRef(argList[4], isMainThread, tmpValue, false), "FILE") == 0)
{
/* Parse File */
doc = xmlParseFile(getDataRef(argList[5], isMainThread, tmpValue, false));
if (doc == NULL)
{
biXmlStatusPtr->setXmlStatus(10503);
return;
}
/* Put document in mem */
xmlPtr->putDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false), doc);
}
else if (strcmp(getDataRef(argList[4], isMainThread, tmpValue, false), "TEXT") == 0)
{
/* Get contents from Text Document */
nodeContents = getDataRef(argList[5], isMainThread, nodeContents, true);
if (nodeContents == NULL)
{
nodeContents = new char[2];
strcpy(nodeContents, "");
}
/* Parse Document */
doc = xmlParseMemory(nodeContents, strlen(nodeContents));
if (doc == NULL)
{
biXmlStatusPtr->setXmlStatus(10504);
return;
}
/* Put document in mem */
xmlPtr->putDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false), doc);
/* Clean up */
delete nodeContents;
}
else
biXmlStatusPtr->setXmlStatus(10505);
}
else if (strcmp(argList[1], "MERGE") == 0)
{
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the source node */
curSource = xmlPtr->getNode(xmlPtr, getDataRef(argList[4], isMainThread, tmpValue, false));
/* Add nodes */
xmlAddChildList(cur, xmlCopyNodeList(curSource));
}
else if (strcmp(argList[1], "MODIFY") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get doc name */
getDataRef(argList[2], isMainThread, docName, false);
/* Get node name */
getDataRef(argList[4], isMainThread, nodeName, false);
/* Get node contents */
nodeContents = getDataRefRaw(argList[6], isMainThread, nodeContents, true);
if (nodeContents == NULL)
{
nodeContents = new char[2];
strcpy(nodeContents, "");
}
/* Ignore full path in ADD for the moment */
if ((nodeName[0] == '/') || (strstr(nodeName, "/") != NULL))
{
biXmlStatusPtr->setXmlStatus(10501);
return;
}
/* Test if attribute */
if (nodeName[0] == '@')
{
/* Check if attribute exists */
attrValue = xmlGetProp(cur, (const xmlChar *)(nodeName+1));
if (attrValue == NULL)
{
biXmlStatusPtr->setXmlStatus(10506);
return;
}
/* Set the attribute */
xmlSetProp(cur, (const xmlChar *)(nodeName+1), (const xmlChar *)nodeContents);
/* Free */
xmlFree(attrValue);
}
else
{
/* Loop through all children until node found */
processed = false;
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
if ((!xmlStrcmp(cur->name, (const xmlChar *)nodeName)))
{
/* Set new contents of node */
xmlNodeSetContent(cur, (const xmlChar *)nodeContents);
processed = true;
break;
}
cur = cur->next;
}
if (processed == false)
biXmlStatusPtr->setXmlStatus(10507);
}
/* Clean up */
delete nodeContents;
}
else if (strcmp(argList[1], "NODEPTR") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get doc name */
getDataRef(argList[2], isMainThread, docName, false);
/* Get node name */
getDataRef(argList[4], isMainThread, nodeName, false);
/* Find out CHILD, PARENT or path */
if (strcmp(nodeName, "CHILD") == 0)
{
curNew = xmlGetLastChild(cur);
if (curNew != NULL)
{
/* Set new node ptr */
xmlPtr->putNode(&xmlPtr, docName, curNew);
/* update navigation path */
sprintf(tmpNav,"%s/%s", xmlPtr->getNavPath(xmlPtr, docName), curNew->name);
xmlPtr->putNavPath(&xmlPtr, docName, tmpNav);
}
}
else if (strcmp(nodeName, "PARENT") == 0)
{
curNew = cur->parent;
if (curNew != NULL)
{
xmlPtr->putNode(&xmlPtr, docName, curNew);
strcpy(tmpNav, xmlPtr->getNavPath(xmlPtr, docName));
tmpNav[(strlen(xmlPtr->getNavPath(xmlPtr, docName)) - (strlen((const char *)cur->name) + 1))] = '\0';
xmlPtr->putNavPath(&xmlPtr, docName, tmpNav);
}
}
else
{
/* Set Node Path */
if (nodeName[0] == '/')
{
rootName = xmlPtr->getRootElementName(xmlPtr, docName);
if (strlen(nodeName) == 0)
sprintf(tmpNodeName, "/%s",rootName);
else
{
/* Allow closing "/" in path setting */
if (nodeName[(strlen(nodeName)-1)] == '/')
nodeName[(strlen(nodeName)-1)] = '\0';
sprintf(tmpNodeName, "/%s%s",rootName, nodeName);
}
}
else
sprintf(tmpNodeName,"%s/%s", xmlPtr->getNavPath(xmlPtr, docName), nodeName);
/* Set path using XPath */
ctx = xmlXPathNewContext(doc);
res = xmlXPathEval((const xmlChar *)tmpNodeName, ctx);
if (res == NULL)
{
xmlXPathFreeObject(res);
xmlXPathFreeContext(ctx);
biXmlStatusPtr->setXmlStatus(10508);
return;
}
if (res->nodesetval->nodeNr > 0 )
{
/* Set pointer to new node */
curNew = res->nodesetval->nodeTab[0];
if (curNew != NULL)
{
xmlPtr->putNode(&xmlPtr, docName, curNew);
xmlPtr->putNavPath(&xmlPtr, docName, tmpNodeName);
}
else
biXmlStatusPtr->setXmlStatus(10508);
}
else
biXmlStatusPtr->setXmlStatus(10508);
/* Free */
xmlXPathFreeObject(res);
xmlXPathFreeContext(ctx);
}
}
else if (strcmp(argList[1], "READ") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get node name */
getDataRef(argList[4], isMainThread, nodeName, false);
/* Set Node Path */
if (nodeName[0] == '/')
{
rootName = xmlPtr->getRootElementName(xmlPtr, docName);
if (strlen(nodeName) == 0)
sprintf(tmpNodeName, "/%s",rootName);
else
{
/* Allow closing "/" in path setting */
if (nodeName[(strlen(nodeName)-1)] == '/')
nodeName[(strlen(nodeName)-1)] = '\0';
sprintf(tmpNodeName, "/%s%s",rootName, nodeName);
}
}
else
sprintf(tmpNodeName,"%s/%s", xmlPtr->getNavPath(xmlPtr, docName), nodeName);
/* Execute XPath query */
ctx = xmlXPathNewContext(doc);
res = xmlXPathEval((const xmlChar *)tmpNodeName, ctx);
if (res == NULL)
{
xmlXPathFreeObject(res);
xmlXPathFreeContext(ctx);
biXmlStatusPtr->setXmlStatus(10508);
return;
}
retString = (char *)xmlXPathCastToString(res);
/* Put DataRef */
putDataRef(argList[6], retString, 0, isMainThread);
/* Clean up */
xmlXPathFreeObject(res);
xmlXPathFreeContext(ctx);
}
else if (strcmp(argList[1], "REMOVE") == 0)
{
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the node */
cur = xmlPtr->getNode(xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get doc name */
getDataRef(argList[2], isMainThread, docName, false);
/* Get node name */
getDataRef(argList[4], isMainThread, nodeName, false);
/* Ignore full path in ADD for the moment */
if ((nodeName[0] == '/') || (strstr(nodeName, "/") != NULL))
{
biXmlStatusPtr->setXmlStatus(10501);
return;
}
/* Loop through all children until node found */
processed = false;
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
if ((!xmlStrcmp(cur->name, (const xmlChar *)nodeName)))
{
/* Remove node */
xmlUnlinkNode(cur);
xmlFreeNode(cur);
processed = true;
break;
}
cur = cur->next;
}
if (processed == false)
biXmlStatusPtr->setXmlStatus(10508);
}
else if (strcmp(argList[1], "ROOT") == 0)
{
/* Removed. XML ROOT not allowed anymore */
/* Root can only be set in the developer */
/* Get a pointer to the document */
doc = xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false));
/* Get a pointer to the root element */
curNew = xmlDocGetRootElement(doc);
/* Set new Root element text */
xmlNodeSetName(doc->children, (const xmlChar *)"test");
}
else if (strcmp(argList[1], "SAVE") == 0)
{
/* Open File */
fpXml = fopen(getDataRef(argList[5], isMainThread, tmpValue, false), "w");
if (fpXml == NULL)
{
biXmlStatusPtr->setXmlStatus(10509);
return;
}
/* Dump XML Document to file */
if ((argHits == 7) && (strcmp(argList[7], "FORMAT") == 0))
{
xmlIndentTreeOutput = 1;
xmlKeepBlanksDefault(0);
xmlDocFormatDump(fpXml, xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false)),1);
}
else
xmlDocDump(fpXml, xmlPtr->getDocument(&xmlPtr, getDataRef(argList[2], isMainThread, tmpValue, false)));
/* Close File */
fclose(fpXml);
}
else if (strcmp(argList[1], "TRANSFORM") == 0)
{
/* Get the Source Document */
if (strcmp(argList[3], "FILE") == 0)
{
/* Parse file */
docSrc = xmlParseFile(getDataRef(argList[4], isMainThread, tmpValue, false));
if (docSrc == NULL)
{
biXmlStatusPtr->setXmlStatus(10503);
return;
}
}
else if (strcmp(argList[3], "TEXT") == 0)
{
/* Extra text document to string */
textSrc = textPtr->getValue(&textPtr, getDataRef(argList[4], isMainThread, tmpValue, false));
/* Parse string */
docSrc = xmlParseMemory(textSrc, strlen(textSrc));
if (docSrc == NULL)
{
biXmlStatusPtr->setXmlStatus(10504);
return;
}
}
else if (strcmp(argList[3], "XML") == 0)
{
docSrc = xmlCopyDoc(xmlPtr->getDocument(&xmlPtr, getDataRef(argList[4], isMainThread, tmpValue, false)),1);
if (docSrc == NULL)
{
biXmlStatusPtr->setXmlStatus(10510);
return;
}
}
else
{
/* Error. Invalid option */
biXmlStatusPtr->setXmlStatus(10505);
return;
}
/* Get the stylesheet */
if (strcmp(argList[6], "FILE") == 0)
{
/* Parse file */
docXslt = xmlParseFile(getDataRef(argList[7], isMainThread, tmpValue, false));
if (docXslt == NULL)
{
biXmlStatusPtr->setXmlStatus(10503);
xmlFreeDoc(docSrc);
return;
}
}
else if (strcmp(argList[6], "TEXT") == 0)
{
/* Extra text document to string */
textSrc = textPtr->getValue(&textPtr, getDataRef(argList[7], isMainThread, tmpValue, false));
/* Parse string */
docXslt = xmlParseMemory(textSrc, strlen(textSrc));
if (docXslt == NULL)
{
biXmlStatusPtr->setXmlStatus(10504);
xmlFreeDoc(docSrc);
return;
}
}
else if (strcmp(argList[6], "XML") == 0)
{
docXslt = xmlCopyDoc(xmlPtr->getDocument(&xmlPtr, getDataRef(argList[7], isMainThread, tmpValue, false)),1);
if (docSrc == NULL)
{
biXmlStatusPtr->setXmlStatus(10510);
return;
}
}
else
{
/* Error. Invalid option */
biXmlStatusPtr->setXmlStatus(10505);
xmlFreeDoc(docSrc);
return;
}
/* Load stylesheet */
//xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
stylePtr = xsltParseStylesheetDoc(docXslt);
if (stylePtr == NULL)
{
biXmlStatusPtr->setXmlStatus(10511);
xmlFreeDoc(docSrc);
xmlFreeDoc(docXslt);
return;
}
/* Transform */
docDest = xsltApplyStylesheet(stylePtr, docSrc, NULL);
if (docDest == NULL)
{
biXmlStatusPtr->setXmlStatus(10512);
xmlFreeDoc(docSrc);
xmlFreeDoc(docXslt);
return;
}
/* Save results */
if (strcmp(argList[9], "FILE") == 0)
{
if ( xsltSaveResultToFilename(getDataRef(argList[10], isMainThread, tmpValue, false), docDest, stylePtr, 0) == -1)
{
biXmlStatusPtr->setXmlStatus(10513);
xmlFreeDoc(docSrc);
xmlFreeDoc(docDest);
xmlFreeDoc(docXslt);
return;
}
}
else if (strcmp(argList[9], "TEXT") == 0)
{
/* Extra text document to string */
if (xsltSaveResultToString(&textContents, textContentsLength, docDest, stylePtr) == -1)
{
biXmlStatusPtr->setXmlStatus(10514);
xmlFreeDoc(docSrc);
xmlFreeDoc(docDest);
xmlFreeDoc(docXslt);
return;
}
textPtr->appendStringValue(&textPtr, getDataRef(argList[10], isMainThread, tmpValue, false), (char *)textContents);
xmlFree(textContents);
}
else if (strcmp(argList[9], "XML") == 0)
{
xmlPtr->putDocument(&xmlPtr, getDataRef(argList[10], isMainThread, tmpValue, false), xmlCopyDoc(docDest,1));
}
else
{
/* Error. Invalid option */
biXmlStatusPtr->setXmlStatus(10505);
xmlFreeDoc(docSrc);
xmlFreeDoc(docDest);
xmlFreeDoc(docXslt);
return;
}
/* Clean up */
xmlFreeDoc(docSrc);
xmlFreeDoc(docDest);
xmlFreeDoc(docXslt);
xsltCleanupGlobals();
}
else if (strcmp(argList[1], "VALIDATE") == 0)
{
/* Not yet implemented */
biXmlStatusPtr->setXmlStatus(10598);
return;
}
else
printf("Invalid XML option\n");
}