[mapserver-commits] r10042 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Thu Apr 1 15:46:11 EDT 2010


Author: assefa
Date: 2010-04-01 15:46:10 -0400 (Thu, 01 Apr 2010)
New Revision: 10042

Modified:
   trunk/mapserver/maplibxml2.h
   trunk/mapserver/mapows.h
   trunk/mapserver/mapowscommon.c
   trunk/mapserver/mapowscommon.h
   trunk/mapserver/mapwfs.c
Log:
Support WFS parsing through libxml2 (#3364)

Modified: trunk/mapserver/maplibxml2.h
===================================================================
--- trunk/mapserver/maplibxml2.h	2010-04-01 19:15:32 UTC (rev 10041)
+++ trunk/mapserver/maplibxml2.h	2010-04-01 19:46:10 UTC (rev 10042)
@@ -36,6 +36,8 @@
 #include<libxml/tree.h>
 #include<libxml/xpath.h>
 #include<libxml/xpathInternals.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xmlschemastypes.h>
 
 xmlXPathObjectPtr msLibXml2GetXPath(xmlDocPtr doc, xmlXPathContextPtr context, xmlChar *xpath);
 

Modified: trunk/mapserver/mapows.h
===================================================================
--- trunk/mapserver/mapows.h	2010-04-01 19:15:32 UTC (rev 10041)
+++ trunk/mapserver/mapows.h	2010-04-01 19:46:10 UTC (rev 10042)
@@ -448,7 +448,7 @@
 #define OWS_SFE_SCHEMA 1 /* GML for simple feature exchange (formerly GML3L0) */
 
 MS_DLL_EXPORT int msWFSDispatch(mapObj *map, cgiRequestObj *requestobj, int force_wfs_mode);
-void msWFSParseRequest(cgiRequestObj *, wfsParamsObj *);
+int msWFSParseRequest(mapObj *map, cgiRequestObj *, wfsParamsObj *, int force_wfs_mode);
 wfsParamsObj *msWFSCreateParamsObj(void);
 void msWFSFreeParamsObj(wfsParamsObj *wfsparams);
 int msWFSIsLayerSupported(layerObj *lp);

Modified: trunk/mapserver/mapowscommon.c
===================================================================
--- trunk/mapserver/mapowscommon.c	2010-04-01 19:15:32 UTC (rev 10041)
+++ trunk/mapserver/mapowscommon.c	2010-04-01 19:46:10 UTC (rev 10042)
@@ -624,6 +624,71 @@
     else
       return xmlNewChild(psParent, psNs, BAD_CAST name, BAD_CAST content);
 }
+
+/*
+ * Valid an xml string against an XML schema
+ * Inpired from: http://xml.developpez.com/sources/?page=validation#validate_XSD_CppCLI_2
+ * taken from tinyows.org
+ */
+int msOWSSchemaValidation(const char* xml_schema, const char* xml)
+{
+    xmlSchemaPtr schema;
+    xmlSchemaParserCtxtPtr ctxt;
+    xmlSchemaValidCtxtPtr validctxt;
+    int ret;
+    xmlDocPtr doc;
+
+    if (!xml_schema || !xml)
+      return MS_FAILURE;
+
+    xmlInitParser();
+    schema = NULL;
+    ret = -1;
+
+    /* Open XML Schema File */
+    ctxt = xmlSchemaNewParserCtxt(xml_schema);
+    /*
+    else ctxt = xmlSchemaNewMemParserCtxt(xml_schema);
+    */
+    /*
+    xmlSchemaSetParserErrors(ctxt,
+                             (xmlSchemaValidityErrorFunc) libxml2_callback,
+                             (xmlSchemaValidityWarningFunc) libxml2_callback, stderr);
+    */
+
+    schema = xmlSchemaParse(ctxt);
+    xmlSchemaFreeParserCtxt(ctxt);
+
+    /* If XML Schema hasn't been rightly loaded */
+    if (schema == NULL) {
+        xmlSchemaCleanupTypes();
+        xmlMemoryDump();
+        xmlCleanupParser();
+        return ret;
+    }
+
+    doc = xmlParseDoc((xmlChar *)xml);
+
+    if (doc != NULL) {
+        /* Loading XML Schema content */
+        validctxt = xmlSchemaNewValidCtxt(schema);
+        /*
+        xmlSchemaSetValidErrors(validctxt,
+                                (xmlSchemaValidityErrorFunc) libxml2_callback,
+                                (xmlSchemaValidityWarningFunc) libxml2_callback, stderr);
+        */
+        /* validation */
+        ret = xmlSchemaValidateDoc(validctxt, doc);
+        xmlSchemaFreeValidCtxt(validctxt);
+    }
+
+    xmlSchemaFree(schema);
+    xmlFreeDoc(doc);
+    xmlCleanupParser();
+
+    return ret;
+}
+
 #endif /* defined(USE_LIBXML2) */
 
 

Modified: trunk/mapserver/mapowscommon.h
===================================================================
--- trunk/mapserver/mapowscommon.h	2010-04-01 19:15:32 UTC (rev 10041)
+++ trunk/mapserver/mapowscommon.h	2010-04-01 19:46:10 UTC (rev 10042)
@@ -95,6 +95,9 @@
 
 xmlNodePtr msOWSCommonxmlNewChildEncoded( xmlNodePtr psParent, xmlNsPtr psNs, const char* name,
                                           const char *content, const char *encoding);
+
+int msOWSSchemaValidation(const char* xml_schema, const char* xml);
+
 #endif /* defined(USE_LIBXML2) */
 
 int msOWSCommonNegotiateVersion(int requested_version, int supported_versions[], int num_supported_versions);

Modified: trunk/mapserver/mapwfs.c
===================================================================
--- trunk/mapserver/mapwfs.c	2010-04-01 19:15:32 UTC (rev 10041)
+++ trunk/mapserver/mapwfs.c	2010-04-01 19:46:10 UTC (rev 10042)
@@ -37,6 +37,11 @@
 
 #include "mapogcfilter.h"
 #include "mapowscommon.h"
+
+#ifdef WFS_USE_LIBXML2
+#include "maplibxml2.h"
+#endif
+
 /*
 ** msWFSException()
 **
@@ -2275,8 +2280,8 @@
   paramsObj = msWFSCreateParamsObj();
   /* TODO : store also parameters that are inside the map object */
   /* into the paramsObj.  */
-  msWFSParseRequest(requestobj, paramsObj);
-
+  if (msWFSParseRequest(map, requestobj, paramsObj, force_wfs_mode) == MS_FAILURE)
+    return msWFSException(map, "request", "InvalidRequest", NULL);
   if (force_wfs_mode)
   {
       /*request is always required*/
@@ -2557,13 +2562,14 @@
 /*                                                                      */
 /*      Parse request into the params object.                           */
 /************************************************************************/
-void msWFSParseRequest(cgiRequestObj *request, wfsParamsObj *wfsparams)
+int msWFSParseRequest(mapObj *map, cgiRequestObj *request, 
+                      wfsParamsObj *wfsparams, int force_wfs_mode)
 {
 #ifdef USE_WFS_SVR
     int i = 0;
         
     if (!request || !wfsparams)
-      return;
+      return MS_FAILURE;
     
     if (request->NumParams > 0)
     {
@@ -2632,6 +2638,230 @@
 #ifdef USE_OGR
     if (request->postrequest)
     {
+#ifdef WFS_USE_LIBXML2
+        xmlDocPtr doc;
+        xmlNodePtr rootnode, node, node1;
+        char *schema_file =NULL;
+        const char *schema_location=NULL, *validate=NULL;
+        char *pszValue=NULL, *pszTmp=NULL;
+        char *pszLayerPropertyName=NULL, *pszLayerFilter=NULL;
+
+        //xmlXPathAxisFunc
+        /* load document */
+        doc = xmlParseDoc((xmlChar *)request->postrequest);
+        if (doc == NULL || (rootnode = xmlDocGetRootElement(doc)) == NULL) 
+        {
+            msSetError(MS_WFSERR, "Invalid POST request.  XML is not well-formed", "msWFSParseRequest()");
+            return MS_FAILURE;
+        }
+        
+        /*get the request*/
+        if (strcasecmp((char *)rootnode->name, "GetCapabilities") == 0)
+          wfsparams->pszRequest = "GetCapabilities";
+        else if (strcasecmp((char *)rootnode->name, "GetFeature") == 0)
+          wfsparams->pszRequest = "GetFeature";
+        else if (strcasecmp((char *)rootnode->name, "DescribeFeatureType") == 0)
+          wfsparams->pszRequest = "DescribeFeatureType";
+        
+        if (wfsparams->pszRequest == NULL)
+        {
+          /* Unsupported WFS request */
+            msSetError(MS_WFSERR, "Unsupported WFS request", "msWFSParseRequest()");
+            return MS_FAILURE;
+        }
+
+        /*get version and service if available*/
+        pszValue = (char *)xmlGetProp(rootnode, (xmlChar *)"version");
+        if (pszValue)
+          wfsparams->pszVersion = strdup(pszValue);
+        pszValue = (char *)xmlGetProp(rootnode, (xmlChar *)"service");
+        if (pszValue)
+          wfsparams->pszService = strdup(pszValue);     
+
+        
+        /* version is optional for the GetCapabilities. If not provided, set it*/
+        if (wfsparams->pszVersion == NULL && 
+            strcmp(wfsparams->pszRequest,"GetCapabilities") == 0)
+           wfsparams->pszVersion = strdup("1.1.0");
+
+
+        /*do we validate the xml ?*/
+        validate = msOWSLookupMetadata(&(map->web.metadata), "FO", "validate_xml");
+        if (validate && strcasecmp(validate, "true") == 0 &&
+            (schema_location = msOWSLookupMetadata(&(map->web.metadata), "FO", "schemas_dir")))
+        {       
+            if ((wfsparams->pszService  && strcmp(wfsparams->pszService, "WFS") == 0) ||
+                force_wfs_mode)
+            {
+                schema_file = msStringConcatenate(schema_file, (char *)schema_location);
+                if (wfsparams->pszVersion == NULL || 
+                    strncasecmp(wfsparams->pszVersion, "1.1", 3) ==0)
+                {
+                    schema_file = msStringConcatenate(schema_file,  "wfs/1.1.0/wfs.xsd");
+                    if (msOWSSchemaValidation(schema_file, request->postrequest) != 0)
+                    {
+                        msSetError(MS_WFSERR, "Invalid POST request.  XML is not valid", "msWFSParseRequest()");
+                        return MS_FAILURE;
+                    }
+                }
+            }
+        } 
+
+        /*parse describefeature*/
+        if (strcmp(wfsparams->pszRequest,"DescribeFeatureType") == 0)
+        {
+            /*look for TypeName and outputFormat*/
+            for (node = rootnode->children; node; node = node->next) 
+            {
+                if (node->type != XML_ELEMENT_NODE)
+                  continue;
+
+                if (strcmp((char *)node->name, "TypeName") == 0) 
+                {
+                    pszValue = (char *)xmlNodeGetContent(node);
+                    if (wfsparams->pszTypeName == NULL)
+                      wfsparams->pszTypeName = strdup(pszValue);
+                    else
+                    {
+                        wfsparams->pszTypeName = 
+                          msStringConcatenate(wfsparams->pszTypeName, ",");
+                        wfsparams->pszTypeName = 
+                          msStringConcatenate(wfsparams->pszTypeName, pszValue);
+                    }
+                }
+            }
+            pszValue = (char *)xmlGetProp(rootnode, (xmlChar *)"outputFormat");
+            if (pszValue)
+              wfsparams->pszOutputFormat = strdup(pszValue);            
+        }  
+
+        /*parse GetFeature*/
+        if (strcmp(wfsparams->pszRequest,"GetFeature") == 0)
+        {
+            pszValue = (char *)xmlGetProp(rootnode, (xmlChar *)"resultType");
+            if (pszValue)
+              wfsparams->pszResultType = strdup(pszValue);
+
+            pszValue = (char *)xmlGetProp(rootnode, (xmlChar *)"maxFeatures");
+            if (pszValue)
+              wfsparams->nMaxFeatures = atoi(pszValue);
+
+            pszValue = (char *)xmlGetProp(rootnode, (xmlChar *)"startIndex");
+            if (pszValue)
+              wfsparams->nStartIndex = atoi(pszValue);
+            
+             /* free typname and filter. There may have been */
+            /* values if they were passed in the URL */
+            if (wfsparams->pszTypeName)    
+              free(wfsparams->pszTypeName);
+            wfsparams->pszTypeName = NULL;
+                        
+            if (wfsparams->pszFilter)    
+              free(wfsparams->pszFilter);
+            wfsparams->pszFilter = NULL;
+
+            for (node = rootnode->children; node; node = node->next) 
+            {
+                if (node->type != XML_ELEMENT_NODE)
+                  continue;
+
+                if (strcmp((char *)node->name, "Query") == 0) 
+                {
+                    /* get SRS: TODO support srs per layer. Now we only have one srs 
+                     that applies to al layers*/
+                    pszValue = (char *)xmlGetProp(node, (xmlChar *)"srsName");
+                    if (pszValue)
+                    {
+                        if (wfsparams->pszSrs )
+                          msFree( wfsparams->pszSrs);
+                        wfsparams->pszSrs = strdup(pszValue);
+                    }
+                    /*type name*/
+                    pszValue = (char *)xmlGetProp(node, (xmlChar *)"typeName");
+                    if (pszValue)
+                    {   
+                        if (wfsparams->pszTypeName == NULL)
+                          wfsparams->pszTypeName = strdup(pszValue);
+                        else
+                        {
+                            wfsparams->pszTypeName = 
+                              msStringConcatenate(wfsparams->pszTypeName, ",");
+                            wfsparams->pszTypeName = 
+                              msStringConcatenate(wfsparams->pszTypeName, pszValue);
+                        }
+                    }
+                    /*PropertyName and Filter*/
+                    pszLayerPropertyName = NULL;
+                    pszLayerFilter = NULL;
+                    for (node1 = node->children; node1; node1 = node1->next) 
+                    {
+                        if (node1->type != XML_ELEMENT_NODE)
+                          continue;
+
+                        if (strcmp((char *)node1->name, "PropertyName") == 0) 
+                        {
+                            pszValue = (char *)xmlNodeGetContent(node1);
+                            if (pszLayerPropertyName == NULL)
+                              pszLayerPropertyName = strdup(pszValue);
+                            else
+                            {   
+                                pszLayerPropertyName= 
+                                  msStringConcatenate(pszLayerPropertyName, ",");
+                                pszLayerPropertyName = 
+                                  msStringConcatenate(pszLayerPropertyName, pszValue);
+                            }
+                        }
+                        if (strcmp((char *)node1->name, "Filter") == 0) 
+                        {
+                            
+                            pszValue = (char *)xmlNodeGetContent(node1);
+                            if (pszValue)
+                            {   
+                                xmlBufferPtr buffer;
+
+                                pszTmp = NULL;
+                                buffer = xmlBufferCreate();
+                                xmlNodeDump(buffer, node1->doc, node1, 0, 0);
+
+                                pszTmp = msStringConcatenate(pszTmp, "(");
+                                pszTmp = msStringConcatenate(pszTmp, (char *)buffer->content);
+                                pszTmp = msStringConcatenate(pszTmp, ")");
+                                
+                                xmlBufferFree(buffer);
+                                wfsparams->pszFilter = 
+                                  msStringConcatenate(wfsparams->pszFilter,pszTmp);
+                                msFree(pszTmp);
+                            }
+                        }
+                    }
+                    pszTmp = NULL;
+                    if (pszLayerPropertyName == NULL)
+                      pszTmp = strdup("()");
+                    else
+                    {
+                        pszTmp = msStringConcatenate(pszTmp, "(");
+                        pszTmp = msStringConcatenate(pszTmp, pszLayerPropertyName);
+                        pszTmp = msStringConcatenate(pszTmp, ")");
+                        msFree(pszLayerPropertyName);
+                    }
+                    wfsparams->pszPropertyName = msStringConcatenate(wfsparams->pszPropertyName, pszTmp);
+                    msFree(pszTmp);
+                        
+                }/*Query node*/
+            }
+
+        }              
+        
+        
+         /* check for request */
+        /* only works??? if <wfs:getCapbilites ...>
+        psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/wfs:GetCapabilities|/GetCapabilities");
+        psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/GetCapabilities");
+        psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/wfs:GetCapabilities");
+        psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"GetCapabilities");
+        psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"//GetCapabilities");
+        */
+#else /*#ifdef WFS_USE_LIBXML2*/
         CPLXMLNode *psRoot, *psQuery, *psFilter, *psTypeName,  *psPropertyName  = NULL;
         CPLXMLNode *psGetFeature = NULL;
         CPLXMLNode  *psGetCapabilities = NULL;
@@ -2641,7 +2871,10 @@
         int bMultiLayer = 0;
 
         psRoot = CPLParseXMLString(request->postrequest);
-
+        if(map->debug == MS_DEBUGLEVEL_VVV)
+        {
+            msDebug("msWFSParseRequest(): WFS post request: %s\n", request->postrequest);
+        }
         if (psRoot)
         {
             /* need to strip namespaces */
@@ -2956,8 +3189,11 @@
 
             }/* end of DescibeFeatureType */
         }
+#endif /*USE_LIBXML2_WFS*/
+        
     }
 #endif
 #endif
+    return MS_SUCCESS;
 }
 



More information about the mapserver-commits mailing list