Skip to content

Commit

Permalink
Merge pull request #3993 from rouault/fix_16009
Browse files Browse the repository at this point in the history
GML parser: fix parsing of typenames and geometry names with non-ASCII character (#16009)
  • Loading branch information
rouault committed Jan 14, 2017
2 parents b412ceb + 6de4fce commit 283d45a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 5 deletions.
21 changes: 16 additions & 5 deletions src/core/qgsgml.cpp
Expand Up @@ -277,10 +277,12 @@ QgsGmlStreamingParser::QgsGmlStreamingParser( const QString& typeName,
: mTypeName( typeName )
, mTypeNameBA( mTypeName.toUtf8() )
, mTypeNamePtr( mTypeNameBA.constData() )
, mTypeNameUTF8Len( strlen( mTypeNamePtr ) )
, mWkbType( QgsWkbTypes::Unknown )
, mGeometryAttribute( geometryAttribute )
, mGeometryAttributeBA( geometryAttribute.toUtf8() )
, mGeometryAttributePtr( mGeometryAttributeBA.constData() )
, mGeometryAttributeUTF8Len( strlen( mGeometryAttributePtr ) )
, mFields( fields )
, mIsException( false )
, mTruncatedResponse( false )
Expand Down Expand Up @@ -315,6 +317,7 @@ QgsGmlStreamingParser::QgsGmlStreamingParser( const QString& typeName,
mTypeName = mTypeName.mid( index + 1 );
mTypeNameBA = mTypeName.toUtf8();
mTypeNamePtr = mTypeNameBA.constData();
mTypeNameUTF8Len = strlen( mTypeNamePtr );
}

mParser = XML_ParserCreateNS( nullptr, NS_SEPARATOR );
Expand All @@ -340,8 +343,10 @@ QgsGmlStreamingParser::QgsGmlStreamingParser( const QList<LayerProperties>& laye
bool invertAxisOrientation )
: mLayerProperties( layerProperties )
, mTypeNamePtr( nullptr )
, mTypeNameUTF8Len( 0 )
, mWkbType( QgsWkbTypes::Unknown )
, mGeometryAttributePtr( nullptr )
, mGeometryAttributeUTF8Len( 0 )
, mFields( fields )
, mIsException( false )
, mTruncatedResponse( false )
Expand Down Expand Up @@ -397,13 +402,15 @@ QgsGmlStreamingParser::QgsGmlStreamingParser( const QList<LayerProperties>& laye
mGeometryAttribute = mLayerProperties[0].mGeometryAttribute;
mGeometryAttributeBA = mGeometryAttribute.toUtf8();
mGeometryAttributePtr = mGeometryAttributeBA.constData();
mGeometryAttributeUTF8Len = strlen( mGeometryAttributePtr );
int index = mTypeName.indexOf( ':' );
if ( index != -1 && index < mTypeName.length() )
{
mTypeName = mTypeName.mid( index + 1 );
}
mTypeNameBA = mTypeName.toUtf8();
mTypeNamePtr = mTypeNameBA.constData();
mTypeNameUTF8Len = strlen( mTypeNamePtr );
}

mEndian = QgsApplication::endian();
Expand Down Expand Up @@ -542,7 +549,7 @@ void QgsGmlStreamingParser::startElement( const XML_Char* el, const XML_Char** a
}
}
}
else if ( localNameLen == mGeometryAttribute.size() &&
else if ( localNameLen == static_cast<int>( mGeometryAttributeUTF8Len ) &&
memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
{
mParseModeStack.push( QgsGmlStreamingParser::Geometry );
Expand Down Expand Up @@ -606,6 +613,7 @@ void QgsGmlStreamingParser::startElement( const XML_Char* el, const XML_Char** a
}
mGeometryAttributeBA = mGeometryAttribute.toUtf8();
mGeometryAttributePtr = mGeometryAttributeBA.constData();
mGeometryAttributeUTF8Len = strlen( mGeometryAttributePtr );
mParseModeStack.push( QgsGmlStreamingParser::FeatureTuple );
QString id;
if ( mGMLNameSpaceURI.isEmpty() )
Expand Down Expand Up @@ -634,7 +642,8 @@ void QgsGmlStreamingParser::startElement( const XML_Char* el, const XML_Char** a
}
}
else if ( theParseMode == None &&
localNameLen == mTypeName.size() && memcmp( pszLocalName, mTypeNamePtr, mTypeName.size() ) == 0 )
localNameLen == static_cast<int>( mTypeNameUTF8Len ) &&
memcmp( pszLocalName, mTypeNamePtr, mTypeNameUTF8Len ) == 0 )
{
Q_ASSERT( !mCurrentFeature );
mCurrentFeature = new QgsFeature( mFeatureCount );
Expand Down Expand Up @@ -857,7 +866,8 @@ void QgsGmlStreamingParser::endElement( const XML_Char* el )

setAttribute( mAttributeName, mStringCash );
}
else if ( theParseMode == Geometry && localNameLen == mGeometryAttribute.size() &&
else if ( theParseMode == Geometry &&
localNameLen == static_cast<int>( mGeometryAttributeUTF8Len ) &&
memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
{
mParseModeStack.pop();
Expand Down Expand Up @@ -935,8 +945,9 @@ void QgsGmlStreamingParser::endElement( const XML_Char* el )
}
else if (( theParseMode == Tuple && !mTypeNamePtr &&
LOCALNAME_EQUALS( "Tuple" ) ) ||
( theParseMode == Feature && localNameLen == mTypeName.size() &&
memcmp( pszLocalName, mTypeNamePtr, mTypeName.size() ) == 0 ) )
( theParseMode == Feature &&
localNameLen == static_cast<int>( mTypeNameUTF8Len ) &&
memcmp( pszLocalName, mTypeNamePtr, mTypeNameUTF8Len ) == 0 ) )
{
Q_ASSERT( mCurrentFeature );
if ( !mCurrentFeature->hasGeometry() )
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsgml.h
Expand Up @@ -250,6 +250,7 @@ class CORE_EXPORT QgsGmlStreamingParser
QString mTypeName;
QByteArray mTypeNameBA;
const char* mTypeNamePtr;
size_t mTypeNameUTF8Len;

QgsWkbTypes::Type mWkbType;

Expand All @@ -259,6 +260,7 @@ class CORE_EXPORT QgsGmlStreamingParser
QString mGeometryAttribute;
QByteArray mGeometryAttributeBA;
const char* mGeometryAttributePtr;
size_t mGeometryAttributeUTF8Len;

QgsFields mFields;
QMap<QString, QPair<int, QgsField> > mThematicAttributes;
Expand Down
49 changes: 49 additions & 0 deletions tests/src/core/testqgsgml.cpp
Expand Up @@ -76,6 +76,7 @@ class TestQgsGML : public QObject
void testPartialFeature();
void testThroughOGRGeometry();
void testThroughOGRGeometry_urn_EPSG_4326();
void testAccents();
};

const QString data1( "<myns:FeatureCollection "
Expand Down Expand Up @@ -1103,5 +1104,53 @@ void TestQgsGML::testThroughOGRGeometry_urn_EPSG_4326()
delete features[0].first;
}

void TestQgsGML::testAccents()
{
QgsFields fields;
QgsGmlStreamingParser gmlParser( QString::fromUtf8( QByteArray( "my\xc3\xa9typename" ) ),
QString::fromUtf8( QByteArray( "my\xc3\xa9geom" ) ),
fields );
QCOMPARE( gmlParser.processData( QByteArray( "<myns:FeatureCollection "
"xmlns:myns='http://myns' "
"xmlns:gml='http://www.opengis.net/gml'>"
"<gml:featureMember>"
"<myns:my\xc3\xa9typename fid='mytypename.1'>"
"<myns:my\xc3\xa9geom>"
"<gml:MultiSurface srsName='EPSG:27700'>"
"<gml:surfaceMember>"
"<gml:Polygon srsName='EPSG:27700'>"
"<gml:exterior>"
"<gml:LinearRing>"
"<gml:posList>0 0 0 10 10 10 10 0 0 0</gml:posList>"
"</gml:LinearRing>"
"</gml:exterior>"
"</gml:Polygon>"
"</gml:surfaceMember>"
"<gml:surfaceMember>"
"<gml:Polygon srsName='EPSG:27700'>"
"<gml:exterior>"
"<gml:LinearRing>"
"<gml:posList>0 0 0 10 10 10 10 0 0 0</gml:posList>"
"</gml:LinearRing>"
"</gml:exterior>"
"</gml:Polygon>"
"</gml:surfaceMember>"
"</gml:MultiSurface>"
"</myns:my\xc3\xa9geom>"
"</myns:my\xc3\xa9typename>"
"</gml:featureMember>"
"</myns:FeatureCollection>" ), true ), true );
QCOMPARE( gmlParser.wkbType(), QgsWkbTypes::MultiPolygon );
QVector<QgsGmlStreamingParser::QgsGmlFeaturePtrGmlIdPair> features = gmlParser.getAndStealReadyFeatures();
QCOMPARE( features.size(), 1 );
QVERIFY( features[0].first->hasGeometry() );
QCOMPARE( features[0].first->geometry().wkbType(), QgsWkbTypes::MultiPolygon );
QgsMultiPolygon multi = features[0].first->geometry().asMultiPolygon();
QCOMPARE( multi.size(), 2 );
QCOMPARE( multi[0].size(), 1 );
QCOMPARE( multi[0][0].size(), 5 );
delete features[0].first;
}

QGSTEST_MAIN( TestQgsGML )
#include "testqgsgml.moc"

0 comments on commit 283d45a

Please sign in to comment.