Skip to content

Commit

Permalink
Notes parser: correctly handle XML entity refs and CDSECTs (fixes #5938)
Browse files Browse the repository at this point in the history
  • Loading branch information
westnordost committed Oct 2, 2024
1 parent fc2645e commit 11d5c5e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,45 @@ private fun XmlReader.parseNotes(): List<Note> = try {

var note: ApiNote? = null
var comment: ApiNoteComment? = null
val names = ArrayList<String>()
var string = ""

forEach { when (it) {
START_ELEMENT -> {
when (localName) {
"note" -> note = ApiNote(LatLon(attribute("lat").toDouble(), attribute("lon").toDouble()))
"comment" -> comment = ApiNoteComment()
}
names.add(localName)
string = ""
}
TEXT -> when (names.lastOrNull()) {
// regarding IGNORABLE_WHITESPACE: https://github.com/pdvrieze/xmlutil/issues/241
TEXT, ENTITY_REF, CDSECT, IGNORABLE_WHITESPACE -> {
string += text
}
END_ELEMENT -> when (localName) {
// in note
"id" -> note?.id = string.toLong()
"date_created" -> note?.timestampCreated = parseTimestamp(string)
"date_closed" -> note?.timestampClosed = parseTimestamp(string)
"status" -> note?.status = Note.Status.valueOf(string.uppercase())

// in comment
"date" -> comment?.date = parseTimestamp(string)
"action" -> comment?.action = NoteComment.Action.valueOf(string.uppercase())
"text" -> comment?.text = string
"uid" -> comment?.uid = string.toLong()
"user" -> comment?.user = string

// note
"id" -> note?.id = text.toLong()
"date_created" -> note?.timestampCreated = parseTimestamp(text)
"date_closed" -> note?.timestampClosed = parseTimestamp(text)
"status" -> note?.status = Note.Status.valueOf(text.uppercase())
"note" -> {
val n = note!!
result.add(Note(n.position, n.id!!, n.timestampCreated!!, n.timestampClosed, n.status!!, n.comments))
}
// comment
"date" -> comment?.date = parseTimestamp(text)
"action" -> comment?.action = NoteComment.Action.valueOf(text.uppercase())
"text" -> comment?.text = text
"uid" -> comment?.uid = text.toLong()
"user" -> comment?.user = text
}
END_ELEMENT -> {
when (localName) {
"note" -> {
val n = note!!
result.add(Note(n.position, n.id!!, n.timestampCreated!!, n.timestampClosed, n.status!!, n.comments))
}
"comment" -> {
val c = comment!!
val cUser = if (c.user != null && c.uid != null) User(c.uid!!, c.user!!) else null
note?.comments?.add(NoteComment(c.date!!, c.action!!, c.text, cUser))
}
"comment" -> {
val c = comment!!
val cUser = if (c.user != null && c.uid != null) User(c.uid!!, c.user!!) else null
note?.comments?.add(NoteComment(c.date!!, c.action!!, c.text, cUser))
}
names.removeLastOrNull()
}
else -> {}
} }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,32 @@ class NotesApiParserTest {

assertEquals(notes, NotesApiParser().parseNotes(xml))
}

@Test fun `parse note with XML entity refs`() {
val xml = """
<osm>
<note lon="0.0689357" lat="51.5085707">
<id>1</id>
<date_created>2024-06-06 12:47:50 UTC</date_created>
<status>open</status>
<comments>
<comment>
<date>2024-06-06 12:47:50 UTC</date>
<uid>1234</uid>
<user>dude &amp; &lt;dudette&gt;</user>
<user_url>https://api.openstreetmap.org/user/dude</user_url>
<action>opened</action>
<text>I opened it &amp; &quot;nothing&quot; broke!</text>
<html><p>Some</p><p>text</p></html>
</comment>
</comments>
</note>
</osm>
""".trimIndent()

val comment = NotesApiParser().parseNotes(xml)[0].comments[0]

assertEquals("dude & <dudette>", comment.user?.displayName)
assertEquals("I opened it & \"nothing\" broke!", comment.text)
}
}

0 comments on commit 11d5c5e

Please sign in to comment.