Index: src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java =================================================================== --- src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java (revision 19570) +++ src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java (working copy) @@ -283,7 +283,7 @@ * @since 15316 */ public static Map parseUrlTagsToKeyValues(String urlSection) { - Map tags = TextTagParser.readTagsByRegexp(urlSection, "\\|", "(.*?)=(.*?)", false); + Map tags = TextTagParser.readTagsByRegexp(urlSection, "(? readTagsByRegexp(String text, String splitRegex, String tagRegex, boolean unescapeTextInQuotes) { + public static Map readTagsByRegexp(String text, String splitRegex, String tagRegex, boolean unescapeTextInQuotes, boolean unescapePipe) { String[] lines = text.split(splitRegex, -1); Pattern p = Pattern.compile(tagRegex); Map tags = new LinkedHashMap<>(); @@ -65,6 +66,10 @@ v = unescape(v); if (k == null || v == null) return null; } + if (unescapePipe) { + k = k.replaceAll("\\\\\\|","|"); + v = v.replaceAll("\\\\\\|","|"); + } tags.put(k, v); } else { return null; @@ -99,7 +104,7 @@ // Format // tag1\tval1\ntag2\tval2\n - tags = readTagsByRegexp(buf, "[\\r\\n]+", ".*?([a-zA-Z0-9:_]+).*\\t(.*?)", false); + tags = readTagsByRegexp(buf, "[\\r\\n]+", ".*?([a-zA-Z0-9:_]+).*\\t(.*?)", false, false); // try "tag\tvalue\n" format if (tags != null) return tags; @@ -108,7 +113,7 @@ // SORRY: "a=b" = c is not supported for now, only first = will be considered // a = "b=c" is OK // a = b=c - this method of parsing fails intentionally - tags = readTagsByRegexp(buf, "[\\n\\t\\r]+", "(.*?)=(.*?)", true); + tags = readTagsByRegexp(buf, "[\\n\\t\\r]+", "(.*?)=(.*?)", true, false ); // try format t1=v1\n t2=v2\n ... if (tags != null) return tags; @@ -118,7 +123,7 @@ if (bufJson.startsWith("{") && bufJson.endsWith("}")) bufJson = bufJson.substring(1, bufJson.length()-1); tags = readTagsByRegexp(bufJson, "[\\s]*,[\\s]*", - "[\\s]*(\\\".*?[^\\\\]\\\")"+"[\\s]*:[\\s]*"+"(\\\".*?[^\\\\]\\\")[\\s]*", true); + "[\\s]*(\\\".*?[^\\\\]\\\")"+"[\\s]*:[\\s]*"+"(\\\".*?[^\\\\]\\\")[\\s]*", true, false); if (tags != null) return tags; // Free format Index: test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java =================================================================== --- test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java (revision 19570) +++ test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java (working copy) @@ -23,4 +23,46 @@ assertEquals("Residenzschloss Dresden", strings.get("wikipedia:de")); assertEquals("Dresden Castle", strings.get("name:en")); } + + /** + * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters" + * A single URL section (value of addtags=...) with a single escaped pipe sysmbol + */ + @Test + void testParseUrlTagsToKeyValues_OneKeyValuePair_OneEscapedPipe() { + Map strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210"); + assertEquals(1, strings.size()); + assertEquals("de:mvv-muenchen:19-210|210", strings.get("gtfs:route_id")); + } + + /** + * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters" + * A single URL section (value of addtags=...) with two escaped pipe sysmbols + */ + @Test + void testParseUrlTagsToKeyValues_OneKeyValuePair_TwoEscapedPipe() { + Map strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179_3"); + assertEquals(1, strings.size()); + assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179_3", strings.get("gtfs:route_id")); + } + /** + * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters" + * Two URL sections (values of addtags=...) with a single escaped pipe sysmbol each + */ + @Test + void testParseUrlTagsToKeyValues_TwoKeyValuePairs_FourEscapedPipe() { + Map strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179_3|gtfs:trip_id:sample=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179-1-1-H-0-We#3-320-333"); + assertEquals(2, strings.size()); + assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179_3", strings.get("gtfs:route_id")); + assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179-1-1-H-0-We#3-320-333", strings.get("gtfs:trip_id:sample")); + } + /** + * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters" + * Two URL sections (values of addtags=...) with four un escaped pipe sysmbols in the value parts + */ + @Test + void testParseUrlTagsToKeyValues_PipeInValue_NoEscapedPipe() { + Map strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210|210|RegionalBus:1179_3|gtfs:trip_id:sample=de:mvv-muenchen:19-210|210|RegionalBus:1179-1-1-H-0-We#3-320-333"); + assertEquals(0, strings.size()); + } } Index: test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java =================================================================== --- test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java (revision 19570) +++ test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java (working copy) @@ -175,7 +175,7 @@ void testStableOrder() { List expected = Arrays.asList("foo4", "foo3", "foo2", "foo1"); ArrayList actual = new ArrayList<>(TextTagParser.readTagsByRegexp( - "foo4=bar4 foo3=bar3 foo2=bar2 foo1=bar1", " ", "(.*?)=(.*?)", true).keySet()); + "foo4=bar4 foo3=bar3 foo2=bar2 foo1=bar1", " ", "(.*?)=(.*?)", true, false).keySet()); assertEquals(expected, actual); } }