Skip to content

Commit

Permalink
GML parser: fix parsing of typenames and geometry names with non-ASCI…
Browse files Browse the repository at this point in the history
…I character (#16009)
  • Loading branch information
rouault committed Jan 14, 2017
1 parent 93770b1 commit e0d7374
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 5 deletions.
21 changes: 16 additions & 5 deletions src/core/qgsgml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,12 @@ QgsGmlStreamingParser::QgsGmlStreamingParser( const QString& typeName,
: mTypeName( typeName )
, mTypeNameBA( mTypeName.toUtf8() )
, mTypeNamePtr( mTypeNameBA.constData() )
, mTypeNameUTF8Len( strlen( mTypeNamePtr ) )
, mWkbType( QGis::WKBUnknown )
, mGeometryAttribute( geometryAttribute )
, mGeometryAttributeBA( geometryAttribute.toUtf8() )
, mGeometryAttributePtr( mGeometryAttributeBA.constData() )
, mGeometryAttributeUTF8Len( strlen( mGeometryAttributePtr ) )
, mFields( fields )
, mIsException( false )
, mTruncatedResponse( false )
Expand Down Expand Up @@ -320,6 +322,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 @@ -345,8 +348,10 @@ QgsGmlStreamingParser::QgsGmlStreamingParser( const QList<LayerProperties>& laye
bool invertAxisOrientation )
: mLayerProperties( layerProperties )
, mTypeNamePtr( nullptr )
, mTypeNameUTF8Len( 0 )
, mWkbType( QGis::WKBUnknown )
, mGeometryAttributePtr( nullptr )
, mGeometryAttributeUTF8Len( 0 )
, mFields( fields )
, mIsException( false )
, mTruncatedResponse( false )
Expand Down Expand Up @@ -402,13 +407,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 @@ -547,7 +554,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 @@ -611,6 +618,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 @@ -639,7 +647,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 @@ -862,7 +871,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 @@ -944,8 +954,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->geometry() )
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsgml.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ class CORE_EXPORT QgsGmlStreamingParser
QString mTypeName;
QByteArray mTypeNameBA;
const char* mTypeNamePtr;
size_t mTypeNameUTF8Len;

QGis::WkbType mWkbType;

Expand All @@ -253,6 +254,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
48 changes: 48 additions & 0 deletions tests/src/core/testqgsgml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,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 @@ -1101,6 +1102,53 @@ void TestQgsGML::testThroughOGRGeometry_urn_EPSG_4326()
QCOMPARE( multi[0][0][0], QgsPoint( 2, 49 ) );
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(), QGis::WKBMultiPolygon );
QVector<QgsGmlStreamingParser::QgsGmlFeaturePtrGmlIdPair> features = gmlParser.getAndStealReadyFeatures();
QCOMPARE( features.size(), 1 );
QVERIFY( features[0].first->constGeometry() != nullptr );
QCOMPARE( features[0].first->constGeometry()->wkbType(), QGis::WKBMultiPolygon );
QgsMultiPolygon multi = features[0].first->constGeometry()->asMultiPolygon();
QCOMPARE( multi.size(), 2 );
QCOMPARE( multi[0].size(), 1 );
QCOMPARE( multi[0][0].size(), 5 );
delete features[0].first;
}

QTEST_MAIN( TestQgsGML )
#include "testqgsgml.moc"

0 comments on commit e0d7374

Please sign in to comment.