/* * * ProLinga-Run * * Copyright (C) 2002-2009 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(const char **argList, int argHits, bool isMainThread) { int insHits, *textContentsLength = NULL; char tmpValue[255], *nodeContents = NULL, 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"); }