Skip to content

Commit

Permalink
Fix bad JSON parsing of XML tag values (#5640)
Browse files Browse the repository at this point in the history
* Fix bad JSON parsing of XML tag values
* Sonar fixes
  • Loading branch information
bmarchant authored May 12, 2023
1 parent 347567d commit c784bcf
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 1 deletion.
76 changes: 76 additions & 0 deletions hoot-core-test/src/test/cpp/hoot/core/io/OsmJsonWriterTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* This file is part of Hootenanny.
*
* Hootenanny 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* --------------------------------------------------------------------
*
* The following copyright notices are generated automatically. If you
* have a new notice to add, please use the format:
* " * @copyright Copyright ..."
* This will properly maintain the copyright information. Maxar
* copyrights will be updated automatically.
*
* @copyright Copyright (C) 2023 Maxar (http://www.maxar.com/)
*/

// Hoot
#include <hoot/core/TestUtils.h>
#include <hoot/core/elements/OsmMap.h>
#include <hoot/core/io/OsmJsonWriter.h>
#include <hoot/core/io/OsmXmlReader.h>

namespace hoot
{

class OsmJsonWriterTest : public HootTestFixture
{
CPPUNIT_TEST_SUITE(OsmJsonWriterTest);
CPPUNIT_TEST(runJsonInTagsTest);
CPPUNIT_TEST_SUITE_END();

public:

OsmJsonWriterTest()
: HootTestFixture("test-files/io/Json/",
"test-output/io/Json/")
{
}

void runJsonInTagsTest()
{
QString input = "JsonInTags.osm";
QString output = "JsonInTags.json";
OsmXmlReader reader;

OsmMapPtr map = std::make_shared<OsmMap>();
reader.setDefaultStatus(Status::Unknown1);
reader.read(_inputPath + input, map);

OsmJsonWriter writer;

writer.open(_outputPath + output);

writer.setIncludeCircularError(false);

writer.write(map);
HOOT_FILE_EQUALS( _inputPath + output,
_outputPath + output);
}

};

CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(OsmJsonWriterTest, "quick");

}
33 changes: 32 additions & 1 deletion hoot-core/src/main/cpp/hoot/core/io/OsmJsonWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <QXmlStreamWriter>
#include <QtCore/QStringBuilder>

namespace pt = boost::property_tree;
using namespace std;

namespace hoot
Expand Down Expand Up @@ -87,7 +88,7 @@ QString OsmJsonWriter::markupString(const QString& str)
s.replace('\t', "\\t");
s.replace('\r', "\\r");
// Don't add quotes around JSON values
if (s.startsWith("{") || s.startsWith("[") || s == "null")
if ((s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]")) || (s.startsWith("\"") && s.endsWith("\"")) || s == "null")
return s;
else
{
Expand Down Expand Up @@ -386,6 +387,8 @@ void OsmJsonWriter::_writeTags(const ConstElementPtr& e)
{
if (key == "uuid")
value = value.replace("{", "").replace("}", "");
else if (value.contains("{") || value.contains("["))
value = _validateJsonString(value);
_writeTag(key, value, firstTag);
}
}
Expand Down Expand Up @@ -438,4 +441,32 @@ void OsmJsonWriter::_writeRelations()
}
}

QString OsmJsonWriter::_validateJsonString(const QString &value) const
{
bool isJson = false;

boost::property_tree::ptree t;
// Convert string to stringstream
stringstream ss(value.toUtf8().constData(), ios::in);

if (ss.good())
{
try
{
// Attempt to read and parse the JSON
pt::read_json(ss, t);
isJson = true;
}
catch (const std::exception&)
{
isJson = false;
}
}
// JSON data can be returned, otherwise it is book-ended with quotes
if (isJson)
return value;
else
return QString("\"%1\"").arg(value);
}

}
2 changes: 2 additions & 0 deletions hoot-core/src/main/cpp/hoot/core/io/OsmJsonWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ class OsmJsonWriter : public QXmlDefaultHandler, public PartialOsmMapWriter, pub

void _writeTag(const QString& key, const QString& value, bool& firstTag);
void _writeMetadata(const Element& element);

QString _validateJsonString(const QString& value) const;
};

}
Expand Down
19 changes: 19 additions & 0 deletions test-files/io/Json/JsonInTags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{"version": 0.6,"generator": "Hootenanny","elements": [
{"type":"node","id":-14,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59349717330424,"lon":-104.8050061945212},
{"type":"node","id":-13,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59349717330424,"lon":-104.8048403015621},
{"type":"node","id":-12,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59370033890474,"lon":-104.8048343768135},
{"type":"node","id":-11,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.5937026216609,"lon":-104.8049113985445},
{"type":"node","id":-10,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59376653880315,"lon":-104.8049143609188},
{"type":"node","id":-9,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59376425604909,"lon":-104.805003232147},
{"type":"node","id":-8,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59358163548018,"lon":-104.8043811335501},
{"type":"node","id":-7,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59357935272003,"lon":-104.8041352564857},
{"type":"node","id":-6,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59381219386865,"lon":-104.8041234069886},
{"type":"node","id":-5,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59380991111609,"lon":-104.8043722464273},
{"type":"node","id":-4,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59403590325468,"lon":-104.8041411812342},
{"type":"node","id":-3,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59424591549021,"lon":-104.8039041912926},
{"type":"node","id":-2,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59441940337849,"lon":-104.8041559931056},
{"type":"node","id":-1,"timestamp":"1970-01-01T00:00:00Z","version":1,"lat":39.59421395714762,"lon":-104.8043781711759},
{"type":"way","id":-3,"timestamp":"1970-01-01T00:00:00Z","version":1,"nodes":[-9,-10,-11,-12,-13,-14,-9],"tags":{"REF1":"Freddy's","bad:name":"[","building":"yes","name":"Freddy's"}},
{"type":"way","id":-2,"timestamp":"1970-01-01T00:00:00Z","version":1,"nodes":[-5,-6,-7,-8,-5],"tags":{"REF1":"Biondi","building":"yes","name":"[海とcafe] kashima"}},
{"type":"way","id":-1,"timestamp":"1970-01-01T00:00:00Z","version":1,"nodes":[-1,-2,-3,-4,-1],"tags":{"REF1":"Cheddar's","amenity":"restaurant","building":"yes","name":"Cheddar's Casual Cafe","source":"{survey, Bing 7/02/2013=1}"}}]
}
53 changes: 53 additions & 0 deletions test-files/io/Json/JsonInTags.osm
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="hootenanny" srs="+epsg:4326">
<bounds minlat="39.59093588103891" minlon="-104.8070473857991" maxlat="39.59441940337849" maxlon="-104.8037828099172"/>
<node visible="true" id="-70" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5942139571476162" lon="-104.8043781711758697"/>
<node visible="true" id="-69" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5944194033784882" lon="-104.8041559931055815"/>
<node visible="true" id="-68" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5942459154902124" lon="-104.8039041912925882"/>
<node visible="true" id="-67" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5940359032546780" lon="-104.8041411812342432"/>
<node visible="true" id="-66" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5938099111160895" lon="-104.8043722464273344"/>
<node visible="true" id="-65" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5938121938686507" lon="-104.8041234069886087"/>
<node visible="true" id="-64" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5935793527200275" lon="-104.8041352564856936"/>
<node visible="true" id="-63" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5935816354801773" lon="-104.8043811335501374"/>
<node visible="true" id="-62" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5937642560490914" lon="-104.8050032321469587"/>
<node visible="true" id="-61" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5937665388031519" lon="-104.8049143609188434"/>
<node visible="true" id="-60" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5937026216609027" lon="-104.8049113985445473"/>
<node visible="true" id="-59" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5937003389047391" lon="-104.8048343768135453"/>
<node visible="true" id="-58" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5934971733042431" lon="-104.8048403015620806"/>
<node visible="true" id="-57" timestamp="1970-01-01T00:00:00Z" version="1" lat="39.5934971733042431" lon="-104.8050061945212263"/>
<way visible="true" id="-10" timestamp="1970-01-01T00:00:00Z" version="1">
<nd ref="-70"/>
<nd ref="-69"/>
<nd ref="-68"/>
<nd ref="-67"/>
<nd ref="-70"/>
<tag k="REF1" v="Cheddar's"/>
<tag k="amenity" v="restaurant"/>
<tag k="building" v="yes"/>
<tag k="name" v="Cheddar's Casual Cafe"/>
<tag k="source" v="{survey, Bing 7/02/2013=1}"/>
</way>
<way visible="true" id="-9" timestamp="1970-01-01T00:00:00Z" version="1">
<nd ref="-66"/>
<nd ref="-65"/>
<nd ref="-64"/>
<nd ref="-63"/>
<nd ref="-66"/>
<tag k="REF1" v="Biondi"/>
<tag k="building" v="yes"/>
<tag k="name" v="[海とcafe] kashima"/>
</way>
<way visible="true" id="-8" timestamp="1970-01-01T00:00:00Z" version="1">
<nd ref="-62"/>
<nd ref="-61"/>
<nd ref="-60"/>
<nd ref="-59"/>
<nd ref="-58"/>
<nd ref="-57"/>
<nd ref="-62"/>
<tag k="REF1" v="Freddy's"/>
<tag k="building" v="yes"/>
<tag k="name" v="Freddy's"/>
<tag k="bad:name" v="["/>
</way>
</osm>

0 comments on commit c784bcf

Please sign in to comment.